diff --git a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp index 9544c298..31cececa 100644 --- a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp +++ b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp @@ -53,7 +53,7 @@ namespace MG_GL::GL { if (pBuffer && bufferObj.data.size() >= end) { void * data; MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, - Diligent::MAP_FLAG_NONE, data); + Diligent::MAP_FLAG_DISCARD, data); if (data) { void* dst = static_cast(data) + offset; @@ -135,7 +135,7 @@ namespace MG_GL::GL { if (pBuffer) { void * data; MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, - Diligent::MAP_FLAG_NONE, data); + Diligent::MAP_FLAG_DISCARD, data); if (data) { memcpy(data, bufferObj.data.data(), bufferObj.data.size()); @@ -180,7 +180,10 @@ namespace MG_GL::GL { if (result == GL_NO_ERROR) { GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target); if (buffer == 0) return; - + auto& bufferObj = MG_State_T::bufferState->buffers_[buffer]; + if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw* + + bufferObj.dirty = false; Diligent::IBuffer*& pBuffer = MG_Diligent::g_BufferMap[buffer]; Diligent::BufferDesc BuffDesc; @@ -204,16 +207,8 @@ namespace MG_GL::GL { switch (usage) { case GL_STATIC_DRAW: - BuffDesc.Usage = Diligent::USAGE_UNIFIED; - BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; - break; - case GL_DYNAMIC_DRAW: - BuffDesc.Usage = Diligent::USAGE_UNIFIED; - BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; - break; - case GL_STREAM_DRAW: - BuffDesc.Usage = Diligent::USAGE_UNIFIED; - BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; + BuffDesc.Usage = Diligent::USAGE_IMMUTABLE; + BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_NONE; break; default: BuffDesc.Usage = Diligent::USAGE_DEFAULT; @@ -223,33 +218,15 @@ namespace MG_GL::GL { if (pBuffer == nullptr) { Diligent::BufferData BuffData; // Initial data must not be null for immutable buffers - if (BuffDesc.Usage == Diligent::USAGE_IMMUTABLE) { - BuffData.pData = data; - } - else { - BuffData.pData = nullptr; - } + BuffData.pData = BuffDesc.Usage != Diligent::USAGE_IMMUTABLE ? nullptr : bufferObj.data.data(); BuffData.DataSize = static_cast(size); MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, &BuffData, &pBuffer); } - if (data != nullptr) { - if (BuffDesc.Usage == Diligent::USAGE_DEFAULT || - BuffDesc.Usage == Diligent::USAGE_SPARSE) { + if (data != nullptr && BuffDesc.Usage != Diligent::USAGE_IMMUTABLE) { MG_Diligent::g_pContext->UpdateBuffer(pBuffer, 0, static_cast(size), data, Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - } else if (BuffDesc.Usage == Diligent::USAGE_UNIFIED || - BuffDesc.Usage == Diligent::USAGE_STAGING || - BuffDesc.Usage == Diligent::USAGE_DYNAMIC) { - void *pMappedData = nullptr; - MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, - Diligent::MAP_FLAG_NONE, pMappedData); - if (pMappedData) { - memcpy(pMappedData, data, size); - MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE); - } - } } return; } @@ -318,11 +295,20 @@ namespace MG_GL::GL { GLuint buffer = MG_State_T::bufferState->GetCurrentBinding(target); if (buffer == 0) return; + auto& bufferObj = MG_State_T::bufferState->buffers_[buffer]; + if (bufferObj.isDynamic) return; // Dynamic buffer should be created by glDraw* + Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer]; if (pBuffer) { - MG_Diligent::g_pContext->UpdateBuffer(pBuffer, static_cast(offset), - static_cast(size), data, - Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + void* pMappedData = nullptr; + MG_Diligent::g_pContext->MapBuffer(pBuffer, Diligent::MAP_WRITE, Diligent::MAP_FLAG_DISCARD, pMappedData); + if (pMappedData) + { + memcpy(static_cast(pMappedData) + offset, data, size); + MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE); + } else { + MG_Util::Debug::LogE("Failed to map buffer for BufferSubData"); + } } } void DeleteBuffers(GLsizei n, const GLuint *buffers) { @@ -333,9 +319,14 @@ namespace MG_GL::GL { for (GLsizei i = 0; i < n; ++i) { GLuint buffer = buffers[i]; if (buffer != 0) { - Diligent::IBuffer* pBuffer = MG_Diligent::g_BufferMap[buffer]; - if (pBuffer) pBuffer->Release(); - MG_Diligent::g_BufferMap.erase(buffer); + auto it = MG_Diligent::g_BufferMap.find(buffer); + if (it != MG_Diligent::g_BufferMap.end()) { + if (it->second) { + it->second->Release(); + } + MG_Diligent::g_BufferMap.erase(it); + } + } } return; diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp index efc9f94b..4eb58700 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp @@ -435,57 +435,144 @@ namespace MG_GL::GL { } MG_Diligent::g_pContext->SetPipelineState(programInfo.pPipelineState); - + auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO(); - if (pVAO) { - std::vector vertexBuffers; - std::vector offsets; - for (auto& attrib : pVAO->attribs) { - if (!attrib.second.enabled) { - MG_Util::Debug::LogD("Vertex attribute %u is not enabled, skipping.", attrib.first); - continue; - } + if (!pVAO) { + MG_Util::Debug::LogE("No current VAO found. A VAO must be bound before drawing."); + return; + } - GLuint buffer = attrib.second.buffer; - if (buffer != 0) { - MG_Util::Debug::LogD("Processing vertex attribute %u with buffer %u", attrib.first, buffer); - auto it = MG_Diligent::g_BufferMap.find(buffer); - if (it != MG_Diligent::g_BufferMap.end()) { - MG_Util::Debug::LogD("Found buffer %u in g_BufferMap", buffer); - vertexBuffers.push_back(it->second); - offsets.push_back(static_cast( - reinterpret_cast(attrib.second.pointer))); - } else { - MG_Util::Debug::LogW("Buffer %u not found in g_BufferMap for vertex attribute %u", buffer, attrib.first); + std::unordered_map createdBuffers; + + for (const auto& [attribIndex, attrib] : pVAO->attribs) { + if (!attrib.enabled || attrib.buffer == 0) continue; + + GLuint buffer = attrib.buffer; + auto& bufferObj = MG_State_T::bufferState->buffers_[buffer]; + + if (bufferObj.isDynamic || MG_Diligent::g_BufferMap.find(buffer) == MG_Diligent::g_BufferMap.end()) { + Diligent::IBuffer*& pBuffer = MG_Diligent::g_BufferMap[buffer]; + + if (!pBuffer) { + Diligent::BufferDesc BuffDesc; + BuffDesc.Name = "Buffer"; + BuffDesc.Size = bufferObj.data.size(); + BuffDesc.Usage = Diligent::USAGE_DYNAMIC; + BuffDesc.BindFlags = Diligent::BIND_VERTEX_BUFFER; + + if (bufferObj.isDynamic) { + BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; + } + + if (pBuffer) { + pBuffer->Release(); + } + + MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &pBuffer); + } + + if (pBuffer && !bufferObj.data.empty()) { + void* pMappedData = nullptr; + MG_Diligent::g_pContext->MapBuffer( + pBuffer, + Diligent::MAP_WRITE, + bufferObj.isDynamic ? Diligent::MAP_FLAG_DISCARD : Diligent::MAP_FLAG_NONE, + pMappedData + ); + + if (pMappedData) { + memcpy(pMappedData, bufferObj.data.data(), bufferObj.data.size()); + MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE); + bufferObj.dirty = false; + createdBuffers[buffer] = pBuffer; } } } + } - if (!vertexBuffers.empty()) { - MG_Util::Debug::LogD("Setting %zu vertex buffers", vertexBuffers.size()); - MG_Diligent::g_pContext->SetVertexBuffers( - 0, vertexBuffers.size(), vertexBuffers.data(), - (const Diligent::Uint64*) offsets.data(), - Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION, - Diligent::SET_VERTEX_BUFFERS_FLAG_RESET + if (pVAO->elementBuffer != 0) { + GLuint buffer = pVAO->elementBuffer; + auto& bufferObj = MG_State_T::bufferState->buffers_[buffer]; + + if (bufferObj.isDynamic || MG_Diligent::g_BufferMap.find(buffer) == MG_Diligent::g_BufferMap.end()) { + Diligent::IBuffer*& pBuffer = MG_Diligent::g_BufferMap[buffer]; + + if (!pBuffer) { + Diligent::BufferDesc BuffDesc; + BuffDesc.Name = "IndexBuffer"; + BuffDesc.Size = bufferObj.data.size(); + BuffDesc.Usage = bufferObj.isDynamic ? Diligent::USAGE_DYNAMIC + : Diligent::USAGE_DEFAULT; + BuffDesc.BindFlags = Diligent::BIND_INDEX_BUFFER; + + if (bufferObj.isDynamic) { + BuffDesc.CPUAccessFlags = Diligent::CPU_ACCESS_WRITE; + } + + if (pBuffer) { + pBuffer->Release(); + } + + MG_Diligent::g_pDevice->CreateBuffer(BuffDesc, nullptr, &pBuffer); + } + + if (pBuffer && !bufferObj.data.empty()) { + void* pMappedData = nullptr; + MG_Diligent::g_pContext->MapBuffer( + pBuffer, + Diligent::MAP_WRITE, + bufferObj.isDynamic ? Diligent::MAP_FLAG_DISCARD : Diligent::MAP_FLAG_NONE, + pMappedData + ); + + if (pMappedData) { + memcpy(pMappedData, bufferObj.data.data(), bufferObj.data.size()); + MG_Diligent::g_pContext->UnmapBuffer(pBuffer, Diligent::MAP_WRITE); + bufferObj.dirty = false; + createdBuffers[buffer] = pBuffer; + } + } + + } + } + + std::vector vertexBuffers; + std::vector offsets; + + for (const auto& [attribIndex, attrib] : pVAO->attribs) { + if (!attrib.enabled || attrib.buffer == 0) continue; + + GLuint buffer = attrib.buffer; + auto it = MG_Diligent::g_BufferMap.find(buffer); + if (it == MG_Diligent::g_BufferMap.end() || !it->second) continue; + + vertexBuffers.push_back(it->second); + offsets.push_back(static_cast(reinterpret_cast(attrib.pointer))); + } + + if (!vertexBuffers.empty()) { + MG_Diligent::g_pContext->SetVertexBuffers( + 0, + static_cast(vertexBuffers.size()), + vertexBuffers.data(), + offsets.data(), + Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION, + Diligent::SET_VERTEX_BUFFERS_FLAG_NONE + ); + } + + 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) { + Diligent::Uint64 offset = reinterpret_cast(indices); + + MG_Diligent::g_pContext->SetIndexBuffer( + it->second, + offset, + Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); } - - if (pVAO->elementBuffer != 0) { - MG_Util::Debug::LogD("Processing element buffer %u", pVAO->elementBuffer); - auto it = MG_Diligent::g_BufferMap.find(pVAO->elementBuffer); - if (it != MG_Diligent::g_BufferMap.end()) { - MG_Util::Debug::LogD("Found element buffer %u in g_BufferMap, setting index buffer.", pVAO->elementBuffer); - MG_Diligent::g_pContext->SetIndexBuffer( - it->second, 0, - Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION - ); - } else { - MG_Util::Debug::LogW("Element buffer %u not found in g_BufferMap.", pVAO->elementBuffer); - } - } - } else { - MG_Util::Debug::LogD("No current VAO found."); } MG_Util::Debug::LogD("Updating uniforms for program %u", program); @@ -504,6 +591,15 @@ namespace MG_GL::GL { drawAttrs.NumIndices = count; drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL; drawAttrs.IndexType = Diligent::VT_UINT32; + MG_Util::Debug::LogD("DrawIndexedAttribs Dump:"); + MG_Util::Debug::LogD(" NumIndices: %u", drawAttrs.NumIndices); + MG_Util::Debug::LogD(" IndexType: %d", drawAttrs.IndexType); + MG_Util::Debug::LogD(" Flags: %u", drawAttrs.Flags); + MG_Util::Debug::LogD(" NumInstances: %u", drawAttrs.NumInstances); + MG_Util::Debug::LogD(" BaseVertex: %u", drawAttrs.BaseVertex); + MG_Util::Debug::LogD(" FirstIndexLocation: %u", drawAttrs.FirstIndexLocation); + MG_Util::Debug::LogD(" FirstInstanceLocation: %u", drawAttrs.FirstInstanceLocation); + // DUMP_DRAW_ATTRIBS_END EnsureRenderPassActive(); MG_Diligent::g_pContext->DrawIndexed(drawAttrs); diff --git a/MG/MG_GL/State/Buffer/BufferState.cpp b/MG/MG_GL/State/Buffer/BufferState.cpp index a909e247..0797588c 100644 --- a/MG/MG_GL/State/Buffer/BufferState.cpp +++ b/MG/MG_GL/State/Buffer/BufferState.cpp @@ -74,6 +74,8 @@ GLenum BufferState::CommitStorage(GLenum target, GLsizeiptr size, const void* da BufferObject& obj = buffers_[it->second]; MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target); obj.usage = usage; + obj.isDynamic = (usage == GL_DYNAMIC_DRAW || usage == GL_DYNAMIC_READ || + usage == GL_DYNAMIC_COPY || usage == GL_STREAM_DRAW); obj.data.resize(size); if (data) { memcpy(obj.data.data(), data, size); diff --git a/MG/MG_GL/State/Buffer/BufferState.h b/MG/MG_GL/State/Buffer/BufferState.h index 15af2479..0901f0f7 100644 --- a/MG/MG_GL/State/Buffer/BufferState.h +++ b/MG/MG_GL/State/Buffer/BufferState.h @@ -18,6 +18,7 @@ public: bool dirty = false; // TODO: encapsulate this with an public API to RHI bool isMapped = false; bool generated = false; + bool isDynamic = false; GLenum accessMode = GL_READ_WRITE; GLintptr mapOffset = 0; GLsizeiptr mapLength = 0;