mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +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, GLProgramInfo> g_ProgramMap;
|
||||||
MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
|
MG_Global::unordered_map<GLuint, Diligent::ISampler*> g_SamplerMap;
|
||||||
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
|
MG_Global::unordered_map<GLuint, Diligent::IBuffer*> g_UniformBufferMap;
|
||||||
|
GLuint g_NextResourceId = 0;
|
||||||
bool IsInRenderPass = false;
|
bool IsInRenderPass = false;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
@@ -173,9 +174,9 @@ namespace MG_Diligent {
|
|||||||
PSOCreateInfo.PSODesc.Name = "Program_PSO";
|
PSOCreateInfo.PSODesc.Name = "Program_PSO";
|
||||||
PSOCreateInfo.PSODesc.PipelineType = Diligent::PIPELINE_TYPE_GRAPHICS;
|
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) {
|
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) {
|
switch (shader->GetDesc().ShaderType) {
|
||||||
case Diligent::SHADER_TYPE_VERTEX:
|
case Diligent::SHADER_TYPE_VERTEX:
|
||||||
PSOCreateInfo.pVS = shader;
|
PSOCreateInfo.pVS = shader;
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ namespace MG_Diligent {
|
|||||||
|
|
||||||
extern bool initialized;
|
extern bool initialized;
|
||||||
extern bool IsInRenderPass;
|
extern bool IsInRenderPass;
|
||||||
|
extern GLuint g_NextResourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MG_EGL::Diligent {
|
namespace MG_EGL::Diligent {
|
||||||
|
|||||||
@@ -684,30 +684,33 @@ namespace MG_GL::GL {
|
|||||||
MG_Util::Debug::LogD("DrawIndexed (BaseVertex) completed.");
|
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) {
|
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount) {
|
||||||
PrepareForDraw();
|
PrepareForDraw();
|
||||||
|
|
||||||
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
auto* pVAO = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||||
Diligent::IBuffer* pIndexBuffer = nullptr;
|
Diligent::IBuffer* pIndexBuffer = nullptr;
|
||||||
if (pVAO->elementBuffer != 0) {
|
if (pVAO->elementBuffer != 0) {
|
||||||
auto it = MG_Diligent::g_BufferMap.find(pVAO->elementBuffer);
|
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;
|
pIndexBuffer = it->second;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pIndexBuffer) {
|
if (!pIndexBuffer) {
|
||||||
MG_Util::Debug::LogE("No valid index buffer bound for multi-draw");
|
MG_Util::Debug::LogE("No valid index buffer bound for multi-draw");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Diligent::MultiDrawIndexedItem> drawItems;
|
|
||||||
drawItems.reserve(drawcount);
|
|
||||||
|
|
||||||
Diligent::VALUE_TYPE indexType = ConvertGLTypeToDiligent(type);
|
Diligent::VALUE_TYPE indexType = ConvertGLTypeToDiligent(type);
|
||||||
Diligent::Uint32 indexSize = 0;
|
Diligent::Uint32 indexSize = 0;
|
||||||
switch (indexType) {
|
switch (indexType) {
|
||||||
case Diligent::VT_UINT8: indexSize = 1; break;
|
|
||||||
case Diligent::VT_UINT16: indexSize = 2; break;
|
case Diligent::VT_UINT16: indexSize = 2; break;
|
||||||
case Diligent::VT_UINT32: indexSize = 4; break;
|
case Diligent::VT_UINT32: indexSize = 4; break;
|
||||||
default:
|
default:
|
||||||
@@ -715,34 +718,98 @@ namespace MG_GL::GL {
|
|||||||
return;
|
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;
|
if (count[i] <= 0) continue;
|
||||||
Diligent::MultiDrawIndexedItem item;
|
|
||||||
item.NumIndices = static_cast<Diligent::Uint32>(count[i]);
|
DrawIndexedArguments cmd{};
|
||||||
auto byteOffset = reinterpret_cast<Diligent::Uint64>(indices[i]);
|
cmd.IndexCount = static_cast<Diligent::Uint32>(count[i]);
|
||||||
item.FirstIndexLocation = static_cast<Diligent::Uint32>(byteOffset / indexSize);
|
cmd.InstanceCount = 1;
|
||||||
item.BaseVertex = 0; // No base vertex
|
cmd.FirstIndex = static_cast<Diligent::Uint32>(reinterpret_cast<uintptr_t>(indices[i]) / indexSize);
|
||||||
drawItems.push_back(item);
|
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");
|
MG_Util::Debug::LogW("No valid draw items in multi-draw");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Diligent::MultiDrawIndexedAttribs drawAttrs;
|
static GLuint indirectBufId = 0;
|
||||||
drawAttrs.DrawCount = static_cast<Diligent::Uint32>(drawItems.size());
|
Diligent::IBuffer* pIndirectBuffer = nullptr;
|
||||||
drawAttrs.pDrawItems = drawItems.data();
|
if (indirectBufId == 0) {
|
||||||
drawAttrs.IndexType = indexType;
|
bool isIdFree = false;
|
||||||
drawAttrs.Flags = Diligent::DRAW_FLAG_VERIFY_ALL;
|
while (!isIdFree) {
|
||||||
drawAttrs.NumInstances = 1;
|
MG_Diligent::g_NextResourceId++;
|
||||||
drawAttrs.FirstInstanceLocation = 0;
|
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();
|
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::g_pContext->EndRenderPass();
|
||||||
MG_Diligent::IsInRenderPass = false;
|
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) {
|
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