From d056acf0af2aef1b396da165f2ada4511081f527 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 27 Jun 2025 10:14:05 +0800 Subject: [PATCH] [Feat] (Diligent/PSO, MG_State/Buffer): implement GL_TRIANGLE_FAN emulation, fixing sky --- .../Implementations/EGL/Diligent/EGL_impl.cpp | 17 ++- .../Implementations/EGL/Diligent/EGL_impl.h | 26 +++- .../Implementations/GL/Drawing/GL_Drawing.cpp | 121 ++++++++++++++---- .../Implementations/GL/Drawing/GL_Drawing.h | 2 + 4 files changed, 135 insertions(+), 31 deletions(-) diff --git a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp index 80364a06..a0cd2b94 100644 --- a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp +++ b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp @@ -23,6 +23,7 @@ namespace MG_Diligent { MG_Global::unordered_map g_ProgramMap; MG_Global::unordered_map g_SamplerMap; MG_Global::unordered_map g_UniformBufferMap; + Diligent::IBuffer* g_TriangleFanIndexBuffer = nullptr; GLuint g_NextResourceId = 0; bool IsInRenderPass = false; bool initialized = false; @@ -101,7 +102,8 @@ namespace MG_Diligent { uint64_t PipelineStateManager::CalculateStateHash( CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo) { + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology) { size_t hash = 0; auto& capabilities = commonState.capabilities; @@ -121,6 +123,7 @@ namespace MG_Diligent { hash_combine(hash, commonState.depthMask); hash_combine(hash, capabilities[GL_DEPTH_TEST]); + hash_combine(hash, primitiveTopology); hash_combine(hash, 0); // TODO: Cull Face Mode hash_combine(hash, capabilities[GL_CULL_FACE]); hash_combine(hash, capabilities[GL_STENCIL_TEST]); @@ -168,7 +171,8 @@ namespace MG_Diligent { GLProgramInfo &programInfo, CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo) { + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology) { PSOCreateInfo.PSODesc.Name = "Program_PSO"; PSOCreateInfo.PSODesc.PipelineType = Diligent::PIPELINE_TYPE_GRAPHICS; @@ -199,7 +203,7 @@ namespace MG_Diligent { PSOCreateInfo.GraphicsPipeline.pRenderPass = g_FramebufferMap[0].pRenderPass; // Default render pass } - PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + PSOCreateInfo.GraphicsPipeline.PrimitiveTopology = GLPrimitiveTopologyToDiligent(primitiveTopology); if (fbInfo.pRenderPass) { PSOCreateInfo.GraphicsPipeline.NumRenderTargets = 0; @@ -314,8 +318,9 @@ namespace MG_Diligent { GLProgramInfo &programInfo, CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo) { - uint64_t currentStateHash = CalculateStateHash(commonState, vaState, fbInfo); + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology) { + uint64_t currentStateHash = CalculateStateHash(commonState, vaState, fbInfo, primitiveTopology); if (programInfo.pPipelineState && programInfo.psoStateHash == currentStateHash && @@ -360,7 +365,7 @@ namespace MG_Diligent { MG_Diligent::BuildInputLayout(program, vaState, programInfo.inputLayout); Diligent::GraphicsPipelineStateCreateInfo PSOCreateInfo; - ConfigurePSO(PSOCreateInfo, programInfo, commonState, vaState, fbInfo); + ConfigurePSO(PSOCreateInfo, programInfo, commonState, vaState, fbInfo, primitiveTopology); MG_Util::Debug::LogD("Dumping PSOCreateInfo for program %u:", program); MG_Util::Debug::LogD(" PSODesc.Name: %s", PSOCreateInfo.PSODesc.Name); diff --git a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h index bda93697..2fc06fd7 100644 --- a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h +++ b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h @@ -56,6 +56,23 @@ namespace MG_Diligent { extern MG_Global::unordered_map g_SamplerMap; extern MG_Global::unordered_map g_UniformBufferMap; + extern Diligent::IBuffer* g_TriangleFanIndexBuffer; + + inline Diligent::PRIMITIVE_TOPOLOGY GLPrimitiveTopologyToDiligent(GLenum Topology) + { + switch (Topology) + { + case GL_TRIANGLE_STRIP: + return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case GL_TRIANGLES: + return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + case GL_TRIANGLE_FAN: + return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + // TODO: Handle other topologies + default: + return Diligent::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + } + } class PipelineStateManager { private: @@ -83,7 +100,8 @@ namespace MG_Diligent { GLProgramInfo &programInfo, CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo); + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology); void MarkPSODirty(GLuint program); @@ -191,14 +209,16 @@ namespace MG_Diligent { uint64_t CalculateStateHash( CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo); + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology); void ConfigurePSO( Diligent::GraphicsPipelineStateCreateInfo &PSOCreateInfo, GLProgramInfo &programInfo, CommonState &commonState, VertexArrayState &vaState, - GLFramebufferInfo& fbInfo); + GLFramebufferInfo& fbInfo, + GLenum primitiveTopology); void ConfigureResourceLayout( Diligent::GraphicsPipelineStateCreateInfo& PSOCreateInfo, diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp index ccc95643..afd68b9f 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp @@ -411,7 +411,22 @@ namespace MG_GL::GL { } } - void PrepareForDraw() { + template + void generate_triangle_fan_indices(std::vector& out_data, const void* in_indices, size_t count) { + const auto* pIn = static_cast(in_indices); + std::vector new_indices; + new_indices.reserve((count - 2) * 3); + T i0 = pIn[0]; + for (size_t i = 1; i < count - 1; ++i) { + new_indices.push_back(i0); + new_indices.push_back(pIn[i]); + new_indices.push_back(pIn[i+1]); + } + out_data.resize(new_indices.size() * sizeof(T)); + memcpy(out_data.data(), new_indices.data(), out_data.size()); + } + + void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum type, const void*& pIndices) { if (MG_Diligent::IsInRenderPass) { MG_Util::Debug::LogD("Ending current render pass."); MG_Diligent::g_pContext->EndRenderPass(); @@ -444,7 +459,8 @@ namespace MG_GL::GL { programInfo, *MG_State_T::commonState, *MG_State_T::vertexArrayState, - fbInfo + fbInfo, + mode ); if (!programInfo.pPipelineState) { @@ -473,7 +489,6 @@ namespace MG_GL::GL { return; } -// for (const auto& [attribIndex, attrib] : pVAO->attribs) { for (uint32_t attribIndex = 0; attribIndex < MG_Constants::VertexArray::MAX_VERTEX_ATTRIBS; ++attribIndex) { const auto& attrib = pVAO->attribs[attribIndex]; if (!attrib.enabled || attrib.buffer == 0) continue; @@ -507,7 +522,67 @@ namespace MG_GL::GL { } } - if (pVAO->elementBuffer != 0) { + if (mode == GL_TRIANGLE_FAN) + { + if (*pCount < 3) return; + + const void* pOriginalIndices = nullptr; + if (pVAO->elementBuffer != 0) + { + auto& bufferObj = MG_State_T::bufferState->buffers_[pVAO->elementBuffer]; + pOriginalIndices = bufferObj.data.data() + reinterpret_cast(pIndices); + } + else + { + pOriginalIndices = pIndices; + } + + std::vector newIndexData; + switch(type) { + case GL_UNSIGNED_BYTE: + generate_triangle_fan_indices(newIndexData, pOriginalIndices, *pCount); + break; + case GL_UNSIGNED_SHORT: + generate_triangle_fan_indices(newIndexData, pOriginalIndices, *pCount); + break; + case GL_UNSIGNED_INT: + generate_triangle_fan_indices(newIndexData, pOriginalIndices, *pCount); + break; + default: + MG_Util::Debug::LogE("Unsupported index type for triangle fan conversion: %X", type); + return; + } + + *pCount = (static_cast(*pCount) - 2) * 3; + pIndices = nullptr; + + if (!MG_Diligent::g_TriangleFanIndexBuffer || MG_Diligent::g_TriangleFanIndexBuffer->GetDesc().Size < newIndexData.size()) + { + if (MG_Diligent::g_TriangleFanIndexBuffer) + MG_Diligent::g_TriangleFanIndexBuffer->Release(); + + Diligent::BufferDesc BuffDesc; + BuffDesc.Name = "Triangle Fan Temp Index Buffer"; + BuffDesc.Size = newIndexData.size(); + BuffDesc.Usage = Diligent::USAGE_DYNAMIC; + BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER; + BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; + MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &MG_Diligent::g_TriangleFanIndexBuffer); + } + + if (MG_Diligent::g_TriangleFanIndexBuffer) + { + void* pMappedData = nullptr; + MG_Diligent::g_pContext->MapBuffer(MG_Diligent::g_TriangleFanIndexBuffer, Diligent::MAP_WRITE, Diligent::MAP_FLAG_DISCARD, pMappedData); + if (pMappedData) + { + memcpy(pMappedData, newIndexData.data(), newIndexData.size()); + MG_Diligent::g_pContext->UnmapBuffer(MG_Diligent::g_TriangleFanIndexBuffer, Diligent::MAP_WRITE); + } + MG_Diligent::g_pContext->SetIndexBuffer(MG_Diligent::g_TriangleFanIndexBuffer, 0, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + } + } + else if (pVAO->elementBuffer != 0) { GLuint buffer = pVAO->elementBuffer; auto& bufferObj = MG_State_T::bufferState->buffers_[buffer]; @@ -534,6 +609,10 @@ namespace MG_GL::GL { MG_Util::Debug::LogE("Failed to create dynamic index buffer %u", buffer); } } + if (pBuffer) + { + MG_Diligent::g_pContext->SetIndexBuffer(pBuffer, 0, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + } } // Update data for all dynamic buffers @@ -621,26 +700,22 @@ namespace MG_GL::GL { } void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { - PrepareForDraw(); - auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); - if (pVAO->elementBuffer != 0) { - GLuint buffer = pVAO->elementBuffer; - auto it = MG_Diligent::g_BufferMap.find(buffer); - if (it != MG_Diligent::g_BufferMap.end() && it->second) { - auto offset = reinterpret_cast(indices); - - MG_Diligent::g_pContext->SetIndexBuffer( - it->second, - offset, - Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION - ); - } - } + const void* pIndices = indices; + PrepareForDraw(mode, &count, type, pIndices); Diligent::DrawIndexedAttribs drawAttrs; drawAttrs.NumIndices = count; drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL; drawAttrs.IndexType = ConvertGLTypeToDiligent(type); + + auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); + if (pIndices != nullptr && pVAO != nullptr && pVAO->elementBuffer != 0) { + size_t indexSize = 1; + if (drawAttrs.IndexType == Diligent::VT_UINT16) indexSize = 2; + else if (drawAttrs.IndexType == Diligent::VT_UINT32) indexSize = 4; + drawAttrs.FirstIndexLocation = static_cast(reinterpret_cast(pIndices) / indexSize); + } + MG_Util::Debug::LogD("DrawIndexedAttribs Dump:"); MG_Util::Debug::LogD(" NumIndices: %u", drawAttrs.NumIndices); MG_Util::Debug::LogD(" IndexType: %d", drawAttrs.IndexType); @@ -708,8 +783,9 @@ namespace MG_GL::GL { }; void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount) { - PrepareForDraw(); - + return; + // PrepareForDraw(); + if (MG_Diligent::IsInRenderPass) { MG_Util::Debug::LogD("Ending current render pass."); MG_Diligent::g_pContext->EndRenderPass(); @@ -843,7 +919,8 @@ namespace MG_GL::GL { } void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex) { - PrepareForDraw(); + return; + // PrepareForDraw(); auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); Diligent::IBuffer* pIndexBuffer = nullptr; diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.h b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.h index f9bb16f3..6495fc92 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.h +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.h @@ -8,6 +8,8 @@ namespace MG_GL::GL { bool IsSamplerType(GLenum type); + Diligent::VALUE_TYPE ConvertGLTypeToDiligent(GLenum type); + void PrepareForDraw(GLenum mode, GLsizei* pCount, GLenum type, const void*& pIndices); void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); void DrawArrays(GLenum mode, GLint first, GLsizei count);