mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
[Feat] (MG_Backend/DirectVulkan): native GPU indirect draws + draw parameters
- Enable multiDrawIndirect and shaderDrawParameters device features when supported (the latter via VkPhysicalDeviceShaderDrawParametersFeatures on Vulkan 1.1+), so DrawIndex/BaseInstance SPIR-V builtins are valid and vkCmdDrawIndexedIndirect(Count) may draw more than one command. - Plain glMultiDrawElementsIndirect no longer requires a GL_PARAMETER_BUFFER (it previously drew nothing for the standard Flywheel call); it now issues a native vkCmdDrawIndexedIndirect, with a per-command loop fallback when the multiDrawIndirect feature is unavailable. - glDrawElementsIndirect / glDrawArraysIndirect / glMultiDrawArraysIndirect read the live GPU buffer via native indirect draws instead of the CPU shadow (which cannot see compute-written commands); the CPU path remains only for client-memory commands. - Advertise the same five extensions as DirectGLES for Flywheel's capability probe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -409,7 +409,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawElementsIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawElementsIndirect called with null GL context");
|
||||
pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, 0, drawcount, stride);
|
||||
pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
}
|
||||
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer");
|
||||
@@ -418,6 +418,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (drawcount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawArraysIndirect(mode, indirect, drawcount, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stride == 0) {
|
||||
stride = sizeof(DrawArraysIndirectCommand);
|
||||
}
|
||||
@@ -427,6 +436,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return;
|
||||
}
|
||||
|
||||
// No indirect buffer bound: the pointer refers to client memory.
|
||||
const auto* commandBytes = ResolveIndirectCommandBytes(
|
||||
indirect,
|
||||
static_cast<SizeT>(stride) * static_cast<SizeT>(drawcount - 1) + sizeof(DrawArraysIndirectCommand),
|
||||
@@ -541,6 +551,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return;
|
||||
}
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawElementsIndirect(mode, type, indirect, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// No indirect buffer bound: the pointer refers to client memory.
|
||||
const auto* commandBytes =
|
||||
ResolveIndirectCommandBytes(indirect, sizeof(DrawElementsIndirectCommand), "DrawElementsIndirect");
|
||||
if (!commandBytes) {
|
||||
@@ -585,6 +604,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer");
|
||||
MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArraysIndirect called with null GL context");
|
||||
|
||||
// With a bound GL_DRAW_INDIRECT_BUFFER the command parameters may be GPU-written
|
||||
// (e.g. by a compute shader), so consume them natively on the GPU.
|
||||
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
pVulkanRenderer->MultiDrawArraysIndirect(mode, indirect, 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// No indirect buffer bound: the pointer refers to client memory.
|
||||
const auto* commandBytes =
|
||||
ResolveIndirectCommandBytes(indirect, sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect");
|
||||
if (!commandBytes) {
|
||||
|
||||
Reference in New Issue
Block a user