From a3092c476cd85baff63b8d8751fa7b9d67b022fa Mon Sep 17 00:00:00 2001 From: Light Date: Sun, 13 Jun 2021 19:35:48 +0430 Subject: [PATCH] Batch Rendering & IndexBuffers & RendererProgram --- Engine/src/Engine/Base.h | 3 +- Engine/src/Engine/Core/Application.cpp | 4 +- Engine/src/Engine/Graphics/Buffers.cpp | 5 +- Engine/src/Engine/Graphics/Buffers.h | 5 +- Engine/src/Engine/Graphics/Renderer.cpp | 91 ++++++++++++++++--- Engine/src/Engine/Graphics/Renderer.h | 61 +++++++++++-- Engine/src/Engine/Layer/Layer.h | 2 + Engine/src/Engine/Layer/LayerStack.cpp | 6 ++ Engine/src/Engine/Layer/LayerStack.h | 2 + .../GraphicsAPI/DirectX/dxBuffers.cpp | 54 ++++++++++- .../Platform/GraphicsAPI/DirectX/dxBuffers.h | 20 ++++ .../Platform/GraphicsAPI/OpenGL/glBuffers.cpp | 17 +++- .../Platform/GraphicsAPI/OpenGL/glBuffers.h | 3 + Engine/src/Platform/OS/Windows/wWindow.cpp | 2 +- Sandbox/imgui.ini | 4 +- Sandbox/res/fragment.fragment | 10 +- Sandbox/res/vertex.vertex | 19 ++-- Sandbox/src/SandboxApp.cpp | 2 +- Sandbox/src/SandboxLayer.h | 5 + 19 files changed, 263 insertions(+), 52 deletions(-) diff --git a/Engine/src/Engine/Base.h b/Engine/src/Engine/Base.h index 4649477..8df70ec 100644 --- a/Engine/src/Engine/Base.h +++ b/Engine/src/Engine/Base.h @@ -24,5 +24,4 @@ #define BIT(x) 1 << x #define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); __debugbreak(); } } -#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __debugbreak(); } } - +#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __debugbreak(); } } \ No newline at end of file diff --git a/Engine/src/Engine/Core/Application.cpp b/Engine/src/Engine/Core/Application.cpp index 3252459..88e557f 100644 --- a/Engine/src/Engine/Core/Application.cpp +++ b/Engine/src/Engine/Core/Application.cpp @@ -41,7 +41,9 @@ namespace Light { m_Window->PollEvents(); // Rendering - m_Window->GetGfxContext()->GetRenderer()->Draw(); + m_Window->GetGfxContext()->GetRenderer()->BeginScene(); + m_LayerStack.OnRender(); + m_Window->GetGfxContext()->GetRenderer()->EndScene(); // Buffer updates m_Window->GetGfxContext()->GetRenderCommand()->SwapBuffers(); diff --git a/Engine/src/Engine/Graphics/Buffers.cpp b/Engine/src/Engine/Graphics/Buffers.cpp index fbb974c..fefe474 100644 --- a/Engine/src/Engine/Graphics/Buffers.cpp +++ b/Engine/src/Engine/Graphics/Buffers.cpp @@ -27,12 +27,15 @@ namespace Light { } } - IndexBuffer* IndexBuffer::Create(unsigned int count, unsigned int* indices) + IndexBuffer* IndexBuffer::Create(unsigned int count, unsigned int* indices, void* sharedContext) { switch (GraphicsContext::GetGraphicsAPI()) { case GraphicsAPI::OpenGL: return new glIndexBuffer(count, indices); + case GraphicsAPI::DirectX: LT_WIN( + return new dxIndexBuffer(count, indices, sharedContext); + ) default: LT_ENGINE_ASSERT(false, "IndexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI()); return nullptr; diff --git a/Engine/src/Engine/Graphics/Buffers.h b/Engine/src/Engine/Graphics/Buffers.h index e49f1a8..d4b48bf 100644 --- a/Engine/src/Engine/Graphics/Buffers.h +++ b/Engine/src/Engine/Graphics/Buffers.h @@ -9,6 +9,9 @@ namespace Light { public: static VertexBuffer* Create(unsigned int stride, unsigned int count, float* vertices, void* sharedContext); + virtual void* Map() = 0; + virtual void UnMap() = 0; + virtual void Bind() = 0; virtual void UnBind() = 0; @@ -19,7 +22,7 @@ namespace Light { class IndexBuffer { public: - static IndexBuffer* Create(unsigned int count, unsigned int* indices); + static IndexBuffer* Create(unsigned int count, unsigned int* indices, void* sharedContext); virtual void Bind() = 0; virtual void UnBind() = 0; diff --git a/Engine/src/Engine/Graphics/Renderer.cpp b/Engine/src/Engine/Graphics/Renderer.cpp index 1655557..61b3b16 100644 --- a/Engine/src/Engine/Graphics/Renderer.cpp +++ b/Engine/src/Engine/Graphics/Renderer.cpp @@ -7,24 +7,36 @@ namespace Light { - Renderer* Renderer::m_Context; + Renderer* Renderer::s_Context; Renderer::Renderer(std::shared_ptr renderCommand, void* sharedContext) : m_RenderCommand(renderCommand), m_SharedContext(sharedContext) { - m_Context = this; + s_Context = this; - m_Shader = std::unique_ptr(Shader::Create("res/vertex.vertex", "res/fragment.fragment", m_SharedContext)); + // QUADRENDERER // + unsigned int offset = 0; + unsigned int* indices = new unsigned int[LT_MAX_QUAD * 6]; - float vertices[] = + for (int i = 0; i < LT_MAX_QUAD * 6; i += 6) { - 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, - 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, - }; + indices[i + 0] = offset + 0; + indices[i + 1] = offset + 1; + indices[i + 2] = offset + 2; - m_VertexBuffer = std::unique_ptr(VertexBuffer::Create(6 * sizeof(float), (2 + 4) * 3, vertices, m_SharedContext)); - m_VertexLayout = std::unique_ptr(VertexLayout::Create(m_VertexBuffer.get(), m_Shader.get(), { { "POSITION", VertexElementType::Float2 },{ "COLOR", VertexElementType::Float4 } }, m_SharedContext)); + indices[i + 3] = offset + 2; + indices[i + 4] = offset + 3; + indices[i + 5] = offset + 0; + + offset += 4; + } + + m_QuadRenderer.shader = std::unique_ptr(Shader::Create("res/vertex.vertex", "res/fragment.fragment", m_SharedContext)); + m_QuadRenderer.vertexBuffer = std::unique_ptr(VertexBuffer::Create(sizeof(QuadRendererProgram::QuadVertexData), LT_MAX_QUAD * 4, nullptr, m_SharedContext)); + m_QuadRenderer.vertexLayout = std::unique_ptr(VertexLayout::Create(m_QuadRenderer.vertexBuffer.get(), m_QuadRenderer.shader.get(), { { "POSITION", VertexElementType::Float3 },{ "COLOR", VertexElementType::Float4 } }, m_SharedContext)); + m_QuadRenderer.indexBuffer = std::unique_ptr(IndexBuffer::Create(LT_MAX_QUAD * 6, indices, m_SharedContext)); + delete[] indices; + // QUADRENDERER // } Renderer* Renderer::Create(std::shared_ptr renderCommand, void* sharedContext) @@ -32,14 +44,63 @@ namespace Light { return new Renderer(renderCommand, sharedContext); } - void Renderer::Draw() + void Renderer::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) { - m_Shader->Bind(); - m_VertexBuffer->Bind(); - m_VertexLayout->Bind(); + s_Context->DrawQuadImpl(position, size, tint); + } - m_RenderCommand->Draw(3u); + void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) + { + // check + if (m_QuadRenderer.mapCurrent + 4 >= m_QuadRenderer.mapEnd) + { + LT_ENGINE_WARN("Render::DrawQuad: max calls per frame exceeded the limit: {}", LT_MAX_QUAD); + + EndScene(); + m_QuadRenderer.Map(); + } + + // local + const float xMin = position.x; + const float yMin = position.y; + const float xMax = position.x + size.x; + const float yMax = position.y + size.y; + + // TOP LEFT + m_QuadRenderer.mapCurrent->position = { xMin, yMin, position.z }; + m_QuadRenderer.mapCurrent->tint = glm::vec4(1.0f, 0.1f, 0.1f, 1.0f); + m_QuadRenderer.mapCurrent++; + + // TOP RIGHT + m_QuadRenderer.mapCurrent->position = { xMax, yMin, position.z }; + m_QuadRenderer.mapCurrent->tint = glm::vec4(0.1f, 1.0f, 0.1f, 1.0f); + m_QuadRenderer.mapCurrent++; + + // BOTTOM RIGHT + m_QuadRenderer.mapCurrent->position = { xMax, yMax, position.z }; + m_QuadRenderer.mapCurrent->tint = glm::vec4(0.3f, 0.3f, 0.3f, 1.0f); + m_QuadRenderer.mapCurrent++; + + // BOTTOM LEFT + m_QuadRenderer.mapCurrent->position = { xMin, yMax, position.z }; + m_QuadRenderer.mapCurrent->tint = glm::vec4(0.1f, 0.1f, 1.0f, 1.0f); + m_QuadRenderer.mapCurrent++; + + // advance + m_QuadRenderer.quadCount++; } + void Renderer::BeginScene() + { + m_QuadRenderer.Map(); + } + + void Renderer::EndScene() + { + m_QuadRenderer.Bind(); + m_RenderCommand->DrawIndexed(m_QuadRenderer.quadCount * 6); + m_QuadRenderer.quadCount = 0; + } + } \ No newline at end of file diff --git a/Engine/src/Engine/Graphics/Renderer.h b/Engine/src/Engine/Graphics/Renderer.h index beb9f0a..7e45ff8 100644 --- a/Engine/src/Engine/Graphics/Renderer.h +++ b/Engine/src/Engine/Graphics/Renderer.h @@ -6,31 +6,80 @@ #include "Buffers.h" #include "VertexLayout.h" +#include + #include +#define LT_MAX_QUAD 124 + namespace Light { class RenderCommand; + struct RendererProgram + { + virtual void Map() = 0; + virtual void Bind() = 0; + }; + class Renderer { private: - static Renderer* m_Context; + struct QuadRendererProgram : RendererProgram + { + // graphics context + std::shared_ptr shader; + std::shared_ptr vertexLayout; + std::shared_ptr vertexBuffer; + std::shared_ptr indexBuffer; + + // buffer data + struct QuadVertexData + { + glm::vec3 position; + glm::vec4 tint; + }; + + QuadVertexData* mapCurrent = nullptr; + QuadVertexData* mapEnd = nullptr; + unsigned int quadCount = 0u; + + // functions + void Map() + { + mapCurrent = (QuadVertexData*)vertexBuffer->Map(); + mapEnd = mapCurrent + LT_MAX_QUAD * 4; + } + + void Bind() + { + vertexBuffer->UnMap(); + shader->Bind(); + vertexLayout->Bind(); + vertexBuffer->Bind(); + indexBuffer->Bind(); + } + }; + + static Renderer* s_Context; + + QuadRendererProgram m_QuadRenderer; std::shared_ptr m_RenderCommand; - std::unique_ptr m_Shader; - std::unique_ptr m_VertexBuffer; - std::unique_ptr m_VertexLayout; - void* m_SharedContext; public: static Renderer* Create(std::shared_ptr renderCommand, void* sharedContext); - void Draw(); + static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint); + + void BeginScene(); + void EndScene(); private: Renderer(std::shared_ptr renderCommand, void* sharedContext); + + void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint); }; } \ No newline at end of file diff --git a/Engine/src/Engine/Layer/Layer.h b/Engine/src/Engine/Layer/Layer.h index b536b46..3a51549 100644 --- a/Engine/src/Engine/Layer/Layer.h +++ b/Engine/src/Engine/Layer/Layer.h @@ -33,6 +33,8 @@ namespace Light { virtual void OnUpdate(float deltaTime) {} virtual void OnUserInterfaceUpdate() {} + virtual void OnRender() {} + // Mouse events virtual bool OnMouseMoved(const MouseMovedEvent& event) { return false; } virtual bool OnButtonPressed(const ButtonPressedEvent& event) { return false; } diff --git a/Engine/src/Engine/Layer/LayerStack.cpp b/Engine/src/Engine/Layer/LayerStack.cpp index 1a27660..18a1bc1 100644 --- a/Engine/src/Engine/Layer/LayerStack.cpp +++ b/Engine/src/Engine/Layer/LayerStack.cpp @@ -35,6 +35,12 @@ namespace Light { (*it)->OnUserInterfaceUpdate(); } + void LayerStack::OnRender() + { + for (auto it = m_Begin; it != m_End; it++) + (*it)->OnRender(); + } + void LayerStack::OnEvent(const Event& event) { switch (event.GetEventType()) diff --git a/Engine/src/Engine/Layer/LayerStack.h b/Engine/src/Engine/Layer/LayerStack.h index 914c4a2..3ca1471 100644 --- a/Engine/src/Engine/Layer/LayerStack.h +++ b/Engine/src/Engine/Layer/LayerStack.h @@ -30,6 +30,8 @@ namespace Light { void OnUpdate(float deltaTime); void OnUserInterfaceUpdate(); + void OnRender(); + void OnEvent(const Event& event); inline bool IsEmpty() { return m_Layers.empty(); } diff --git a/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.cpp b/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.cpp index 78554ff..47ba1b7 100644 --- a/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.cpp +++ b/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.cpp @@ -17,8 +17,6 @@ namespace Light { m_DeviceContext = dxContext->deviceContext; D3D11_BUFFER_DESC desc = { 0 }; - D3D11_SUBRESOURCE_DATA sd = { 0 }; - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.Usage = D3D11_USAGE_DYNAMIC; @@ -27,15 +25,24 @@ namespace Light { desc.ByteWidth = count * stride; desc.StructureByteStride = stride; - sd.pSysMem = vertices; - - DXC(m_Device->CreateBuffer(&desc, &sd, &m_Buffer)); + DXC(m_Device->CreateBuffer(&desc, nullptr, &m_Buffer)); } dxVertexBuffer::~dxVertexBuffer() { } + void* dxVertexBuffer::Map() + { + m_DeviceContext->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map); + return m_Map.pData; + } + + void dxVertexBuffer::UnMap() + { + m_DeviceContext->Unmap(m_Buffer.Get(), NULL); + } + void dxVertexBuffer::Bind() { static const unsigned int offset = 0u; @@ -46,4 +53,41 @@ namespace Light { { } + + dxIndexBuffer::dxIndexBuffer(unsigned int count, unsigned int* indices, void* sharedContext) + { + HRESULT hr; + + dxSharedContext* dxContext = static_cast(sharedContext); + LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext"); + + m_Device = dxContext->device; + m_DeviceContext = dxContext->deviceContext; + + D3D11_BUFFER_DESC bufferDesc = { 0 }; + D3D11_SUBRESOURCE_DATA sd = { 0 }; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + + bufferDesc.ByteWidth = count * sizeof(unsigned int); + bufferDesc.StructureByteStride = sizeof(unsigned int); + + sd.pSysMem = indices; + + DXC(m_Device->CreateBuffer(&bufferDesc, &sd, &m_Buffer)); + } + + dxIndexBuffer::~dxIndexBuffer() + { + } + + void dxIndexBuffer::Bind() + { + m_DeviceContext->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u); + } + + void dxIndexBuffer::UnBind() + { + } + } \ No newline at end of file diff --git a/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.h b/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.h index 26a9c25..8546fdf 100644 --- a/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.h +++ b/Engine/src/Platform/GraphicsAPI/DirectX/dxBuffers.h @@ -17,11 +17,31 @@ namespace Light { Microsoft::WRL::ComPtr m_Device; Microsoft::WRL::ComPtr m_DeviceContext; + D3D11_MAPPED_SUBRESOURCE m_Map; + unsigned int m_Stride; public: dxVertexBuffer(unsigned int count, unsigned int stride, float* vertices, void* sharedContext); ~dxVertexBuffer(); + void* Map() override; + void UnMap() override; + + void Bind() override; + void UnBind() override; + }; + + class dxIndexBuffer : public IndexBuffer + { + private: + Microsoft::WRL::ComPtr m_Buffer; + + Microsoft::WRL::ComPtr m_Device; + Microsoft::WRL::ComPtr m_DeviceContext; + public: + dxIndexBuffer(unsigned int count, unsigned int* indices, void* sharedContext); + ~dxIndexBuffer(); + void Bind() override; void UnBind() override; }; diff --git a/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.cpp b/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.cpp index 5ab8cdf..dd140fe 100644 --- a/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.cpp +++ b/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.cpp @@ -8,8 +8,7 @@ namespace Light { glVertexBuffer::glVertexBuffer(unsigned int count, float* vertices) { glCreateBuffers(1, &m_BufferID); - glBindBuffer(GL_ARRAY_BUFFER, m_BufferID); - glBufferData(GL_ARRAY_BUFFER, count * sizeof(float), vertices, GL_STATIC_DRAW); + glNamedBufferData(m_BufferID, count * sizeof(float), vertices, GL_DYNAMIC_DRAW); } glVertexBuffer::~glVertexBuffer() @@ -17,6 +16,16 @@ namespace Light { glDeleteBuffers(1, &m_BufferID); } + void* glVertexBuffer::Map() + { + return glMapNamedBuffer(m_BufferID, GL_WRITE_ONLY); + } + + void glVertexBuffer::UnMap() + { + glUnmapNamedBuffer(m_BufferID); + } + void glVertexBuffer::Bind() { glBindBuffer(GL_ARRAY_BUFFER, m_BufferID); @@ -30,9 +39,7 @@ namespace Light { glIndexBuffer::glIndexBuffer(unsigned int count, unsigned int* indices) { glCreateBuffers(1, &m_BufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_BufferID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), indices, GL_STATIC_DRAW); - + glNamedBufferData(m_BufferID, count * sizeof(unsigned int), indices, GL_STATIC_DRAW); } glIndexBuffer::~glIndexBuffer() diff --git a/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.h b/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.h index f7a8765..7307e9a 100644 --- a/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.h +++ b/Engine/src/Platform/GraphicsAPI/OpenGL/glBuffers.h @@ -14,6 +14,9 @@ namespace Light { glVertexBuffer(unsigned int count, float* vertices); ~glVertexBuffer(); + void* Map() override; + void UnMap() override; + void Bind() override; void UnBind() override; }; diff --git a/Engine/src/Platform/OS/Windows/wWindow.cpp b/Engine/src/Platform/OS/Windows/wWindow.cpp index d822e96..ee77820 100644 --- a/Engine/src/Platform/OS/Windows/wWindow.cpp +++ b/Engine/src/Platform/OS/Windows/wWindow.cpp @@ -28,7 +28,7 @@ namespace Light { glfwSetWindowUserPointer(m_Handle, &m_EventCallback); BindGlfwEvents(); - m_GraphicsContext = std::unique_ptr(GraphicsContext::Create(GraphicsAPI::DirectX, m_Handle)); + m_GraphicsContext = std::unique_ptr(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle)); LT_ENGINE_ASSERT(m_GraphicsContext, "wWindow::wWindow: graphics context creation failed"); } diff --git a/Sandbox/imgui.ini b/Sandbox/imgui.ini index f150ffd..dcce344 100644 --- a/Sandbox/imgui.ini +++ b/Sandbox/imgui.ini @@ -4,8 +4,8 @@ Size=400,400 Collapsed=0 [Window][Dear ImGui Demo] -Pos=-3,-1 -Size=244,247 +Pos=1,-3 +Size=405,290 Collapsed=0 [Window][Dear ImGui Metrics/Debugger] diff --git a/Sandbox/res/fragment.fragment b/Sandbox/res/fragment.fragment index 5ffca78..945034e 100644 --- a/Sandbox/res/fragment.fragment +++ b/Sandbox/res/fragment.fragment @@ -1,4 +1,10 @@ -float4 main(float4 Color : COLOR) : SV_Target +#version 440 core + +in vec4 fragColor; + +out vec4 FragmentColor; + +void main() { - return Color; + FragmentColor = fragColor; } \ No newline at end of file diff --git a/Sandbox/res/vertex.vertex b/Sandbox/res/vertex.vertex index bc40102..a82c3c0 100644 --- a/Sandbox/res/vertex.vertex +++ b/Sandbox/res/vertex.vertex @@ -1,13 +1,12 @@ -struct VertexOut -{ - float4 Color : COLOR; - float4 Position : SV_Position; -}; +#version 440 core -VertexOut main(float2 InPosition : POSITION, float4 InColor : COLOR) +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec4 a_Color; + +out vec4 fragColor; + +void main() { - VertexOut vso; - vso.Position = float4(InPosition.x, InPosition.y, 0.0f, 1.0f); - vso.Color = InColor; - return vso; + gl_Position = vec4(a_Position, 1.0); + fragColor = a_Color; } \ No newline at end of file diff --git a/Sandbox/src/SandboxApp.cpp b/Sandbox/src/SandboxApp.cpp index 8745c47..6f15588 100644 --- a/Sandbox/src/SandboxApp.cpp +++ b/Sandbox/src/SandboxApp.cpp @@ -1,7 +1,7 @@ #define LIGHT_ENTRY_POINT #include -#include "SandboxLayer.h" + #include "SandboxLayer.h" class Sandbox : public Light::Application { diff --git a/Sandbox/src/SandboxLayer.h b/Sandbox/src/SandboxLayer.h index 585fef0..7ffec6b 100644 --- a/Sandbox/src/SandboxLayer.h +++ b/Sandbox/src/SandboxLayer.h @@ -5,4 +5,9 @@ class SandboxLayer : public Light::Layer public: SandboxLayer(const std::string& name): Light::Layer(name) {} + void OnRender() override + { + Light::Renderer::DrawQuad(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec2(1.f, 1.f), glm::vec4(1.12f, 1.41f, 1.72f, 1.0f)); + } + };