mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (Diligent/Drawing): Reimplement glMultiDrawElements through indirect drawing.
This commit is contained in:
@@ -23,6 +23,7 @@ namespace MG_Diligent {
|
||||
MG_Global::unordered_map<GLuint, GLProgramInfo> g_ProgramMap;
|
||||
MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
|
||||
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> 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;
|
||||
|
||||
@@ -213,6 +213,7 @@ namespace MG_Diligent {
|
||||
|
||||
extern bool initialized;
|
||||
extern bool IsInRenderPass;
|
||||
extern GLuint g_NextResourceId;
|
||||
}
|
||||
|
||||
namespace MG_EGL::Diligent {
|
||||
|
||||
@@ -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<Diligent::MultiDrawIndexedItem> 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<DrawIndexedArguments> indirectCmds;
|
||||
indirectCmds.reserve(drawcount);
|
||||
for (GLsizei i = 0; i < drawcount; ++i) {
|
||||
if (count[i] <= 0) continue;
|
||||
Diligent::MultiDrawIndexedItem item;
|
||||
item.NumIndices = static_cast<Diligent::Uint32>(count[i]);
|
||||
auto byteOffset = reinterpret_cast<Diligent::Uint64>(indices[i]);
|
||||
item.FirstIndexLocation = static_cast<Diligent::Uint32>(byteOffset / indexSize);
|
||||
item.BaseVertex = 0; // No base vertex
|
||||
drawItems.push_back(item);
|
||||
|
||||
DrawIndexedArguments cmd{};
|
||||
cmd.IndexCount = static_cast<Diligent::Uint32>(count[i]);
|
||||
cmd.InstanceCount = 1;
|
||||
cmd.FirstIndex = static_cast<Diligent::Uint32>(reinterpret_cast<uintptr_t>(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<Diligent::Uint32>(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<Diligent::Uint64>(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<Diligent::Uint32>(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) {
|
||||
|
||||
Reference in New Issue
Block a user