[Fix] (Diligent/Buffer): Create dynamic buffer in glDraw*.

This commit is contained in:
BZLZHH
2025-06-08 13:35:32 +08:00
parent 848f110658
commit 292c7eeecf
4 changed files with 172 additions and 82 deletions
@@ -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<char*>(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<Diligent::Uint64>(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<Diligent::Uint64>(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<Diligent::Uint64>(offset),
static_cast<Diligent::Uint64>(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<Diligent::Uint8*>(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;
@@ -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<Diligent::IBuffer*> vertexBuffers;
std::vector<Diligent::Uint32> 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<Diligent::Uint32>(
reinterpret_cast<size_t>(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<GLuint, Diligent::IBuffer*> 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<Diligent::IBuffer*> vertexBuffers;
std::vector<Diligent::Uint64> 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<Diligent::Uint64>(reinterpret_cast<size_t>(attrib.pointer)));
}
if (!vertexBuffers.empty()) {
MG_Diligent::g_pContext->SetVertexBuffers(
0,
static_cast<Diligent::Uint32>(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<uintptr_t>(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);
+2
View File
@@ -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);
+1
View File
@@ -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;