diff --git a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.cpp index 68818149..12986c50 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; + GLuint g_NextResourceId = 0; bool IsInRenderPass = false; bool initialized = false; @@ -173,9 +174,9 @@ namespace MG_Diligent { PSOCreateInfo.PSODesc.Name = "Program_PSO"; PSOCreateInfo.PSODesc.PipelineType = Diligent::PIPELINE_TYPE_GRAPHICS; - __android_log_print(ANDROID_LOG_DEBUG, "Diligent Engine", "Num AttachedShaders: %zu", programInfo.AttachedShaders.size()); + MG_Util::Debug::LogD("Num AttachedShaders: %zu", programInfo.AttachedShaders.size()); for (auto shader: programInfo.AttachedShaders) { - __android_log_print(ANDROID_LOG_DEBUG, "Diligent Engine", "AttachedShader: %p, Type: %d", shader, shader->GetDesc().ShaderType); + MG_Util::Debug::LogD("AttachedShader: %p, Type: %d", shader, shader->GetDesc().ShaderType); switch (shader->GetDesc().ShaderType) { case Diligent::SHADER_TYPE_VERTEX: PSOCreateInfo.pVS = shader; diff --git a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h index 4c226099..c9ab159a 100644 --- a/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h +++ b/MG/MG_GL/Implementations/EGL/Diligent/EGL_impl.h @@ -213,6 +213,7 @@ namespace MG_Diligent { extern bool initialized; extern bool IsInRenderPass; + extern GLuint g_NextResourceId; } namespace MG_EGL::Diligent { diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp index 6d9a26fb..5e9a210b 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp @@ -684,30 +684,33 @@ namespace MG_GL::GL { MG_Util::Debug::LogD("DrawIndexed (BaseVertex) completed."); } + struct DrawIndexedArguments + { + Diligent::Uint32 IndexCount; + Diligent::Uint32 InstanceCount; + Diligent::Uint32 FirstIndex; + Diligent::Uint32 BaseVertex; + Diligent::Uint32 FirstInstance; + }; + void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount) { PrepareForDraw(); - + auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); Diligent::IBuffer* pIndexBuffer = nullptr; if (pVAO->elementBuffer != 0) { auto it = MG_Diligent::g_BufferMap.find(pVAO->elementBuffer); - if (it != MG_Diligent::g_BufferMap.end() && it->second) { + if (it != MG_Diligent::g_BufferMap.end()) pIndexBuffer = it->second; - } } - if (!pIndexBuffer) { MG_Util::Debug::LogE("No valid index buffer bound for multi-draw"); return; } - std::vector drawItems; - drawItems.reserve(drawcount); - Diligent::VALUE_TYPE indexType = ConvertGLTypeToDiligent(type); Diligent::Uint32 indexSize = 0; switch (indexType) { - case Diligent::VT_UINT8: indexSize = 1; break; case Diligent::VT_UINT16: indexSize = 2; break; case Diligent::VT_UINT32: indexSize = 4; break; default: @@ -715,34 +718,98 @@ namespace MG_GL::GL { return; } - for (GLsizei i = 0; i < drawcount; i++) { + std::vector indirectCmds; + indirectCmds.reserve(drawcount); + for (GLsizei i = 0; i < drawcount; ++i) { if (count[i] <= 0) continue; - Diligent::MultiDrawIndexedItem item; - item.NumIndices = static_cast(count[i]); - auto byteOffset = reinterpret_cast(indices[i]); - item.FirstIndexLocation = static_cast(byteOffset / indexSize); - item.BaseVertex = 0; // No base vertex - drawItems.push_back(item); + + DrawIndexedArguments cmd{}; + cmd.IndexCount = static_cast(count[i]); + cmd.InstanceCount = 1; + cmd.FirstIndex = static_cast(reinterpret_cast(indices[i]) / indexSize); + cmd.BaseVertex = 0; + cmd.FirstInstance = 0; + + indirectCmds.push_back(cmd); } - if (drawItems.empty()) { + if (indirectCmds.empty()) { MG_Util::Debug::LogW("No valid draw items in multi-draw"); return; } - Diligent::MultiDrawIndexedAttribs drawAttrs; - drawAttrs.DrawCount = static_cast(drawItems.size()); - drawAttrs.pDrawItems = drawItems.data(); - drawAttrs.IndexType = indexType; - drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL; - drawAttrs.NumInstances = 1; - drawAttrs.FirstInstanceLocation = 0; + static GLuint indirectBufId = 0; + Diligent::IBuffer* pIndirectBuffer = nullptr; + if (indirectBufId == 0) { + bool isIdFree = false; + while (!isIdFree) { + MG_Diligent::g_NextResourceId++; + bool isIdAlreadyExist = false; + for (auto& [id, bufferObj] : MG_State_T::bufferState->buffers_) { + if (MG_Diligent::g_NextResourceId == id) { + isIdAlreadyExist = true; + break; + } + } + isIdFree = !isIdAlreadyExist; + } + indirectBufId = MG_Diligent::g_NextResourceId; + MG_Diligent::g_NextResourceId++; + } + auto& bufEntry = MG_Diligent::g_BufferMap[indirectBufId]; + const auto requiredSize = indirectCmds.size() * sizeof(DrawIndexedArguments); + + bool recreateBuffer = !bufEntry || bufEntry->GetDesc().Size != requiredSize; + + if (recreateBuffer) { + if (bufEntry) { + bufEntry->Release(); + bufEntry = nullptr; + } + + Diligent::BufferDesc desc; + desc.Name = "MultiDrawIndirectArgs"; + desc.Usage = Diligent::USAGE_DYNAMIC; + desc.BindFlags = Diligent::BIND_INDIRECT_DRAW_ARGS; + desc.Size = static_cast(requiredSize); + desc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; + MG_Diligent::g_pDevice->CreateBuffer(desc, nullptr, &bufEntry); + } + pIndirectBuffer = bufEntry; + + void* pMappedData = nullptr; + + MG_Util::Debug::LogD("Mapping indirect draw buffer for multi-draw."); + MG_Diligent::g_pContext->MapBuffer( + pIndirectBuffer, + Diligent::MAP_WRITE, + Diligent::MAP_FLAG_DISCARD, + pMappedData + ); + + if (pMappedData) { + memcpy(pMappedData, indirectCmds.data(), requiredSize); + MG_Diligent::g_pContext->UnmapBuffer(pIndirectBuffer, Diligent::MAP_WRITE); + MG_Util::Debug::LogD("Successfully updated indirect draw buffer."); + } else { + MG_Util::Debug::LogE("Failed to map indirect draw buffer for multi-draw."); + return; + } + + // Execute multi-draw indirect! EnsureRenderPassActive(); - MG_Diligent::g_pContext->MultiDrawIndexed(drawAttrs); + Diligent::DrawIndexedIndirectAttribs mdAttribs; + mdAttribs.IndexType = indexType; + mdAttribs.pAttribsBuffer = pIndirectBuffer; + mdAttribs.DrawCount = static_cast(indirectCmds.size()); + + MG_Diligent::g_pContext->DrawIndexedIndirect(mdAttribs); + MG_Diligent::g_pContext->EndRenderPass(); MG_Diligent::IsInRenderPass = false; - MG_Util::Debug::LogD("MultiDrawElements completed."); + + MG_Util::Debug::LogD("MultiDrawElements completed with %d draws.", indirectCmds.size()); } void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex) {