Optimize GPU particles indirect args building code
This commit is contained in:
@@ -783,8 +783,8 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
|||||||
int32 drawCalls = 0;
|
int32 drawCalls = 0;
|
||||||
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
||||||
{
|
{
|
||||||
int32 moduleIndex = renderModulesIndices[index];
|
int32 moduleIndex = renderModulesIndices.Get()[index];
|
||||||
auto module = emitter->Graph.RenderModules[moduleIndex];
|
auto module = emitter->Graph.RenderModules.Get()[moduleIndex];
|
||||||
switch (module->TypeID)
|
switch (module->TypeID)
|
||||||
{
|
{
|
||||||
// Sprite Rendering
|
// Sprite Rendering
|
||||||
@@ -832,76 +832,15 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
|||||||
// Ensure to have enough space for indirect draw arguments
|
// Ensure to have enough space for indirect draw arguments
|
||||||
const uint32 minSize = drawCalls * sizeof(GPUDrawIndexedIndirectArgs);
|
const uint32 minSize = drawCalls * sizeof(GPUDrawIndexedIndirectArgs);
|
||||||
if (buffer->GPU.IndirectDrawArgsBuffer->GetSize() < minSize)
|
if (buffer->GPU.IndirectDrawArgsBuffer->GetSize() < minSize)
|
||||||
{
|
|
||||||
buffer->GPU.IndirectDrawArgsBuffer->Init(GPUBufferDescription::Argument(minSize));
|
buffer->GPU.IndirectDrawArgsBuffer->Init(GPUBufferDescription::Argument(minSize));
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize indirect draw arguments contents (do it before drawing to reduce memory barriers amount when updating arguments buffer)
|
// Execute all rendering modules using indirect draw arguments
|
||||||
int32 indirectDrawCallIndex = 0;
|
int32 indirectDrawCallIndex = 0;
|
||||||
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
||||||
{
|
{
|
||||||
int32 moduleIndex = renderModulesIndices[index];
|
int32 moduleIndex = renderModulesIndices.Get()[index];
|
||||||
auto module = emitter->Graph.RenderModules[moduleIndex];
|
auto module = emitter->Graph.RenderModules.Get()[moduleIndex];
|
||||||
switch (module->TypeID)
|
|
||||||
{
|
|
||||||
// Sprite Rendering
|
|
||||||
case 400:
|
|
||||||
{
|
|
||||||
GPUDrawIndexedIndirectArgs indirectArgsBufferInitData{ SpriteParticleRenderer::IndexCount, 1, 0, 0, 0 };
|
|
||||||
const uint32 offset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
|
||||||
context->UpdateBuffer(buffer->GPU.IndirectDrawArgsBuffer, &indirectArgsBufferInitData, sizeof(indirectArgsBufferInitData), offset);
|
|
||||||
const uint32 counterOffset = buffer->GPU.ParticleCounterOffset;
|
|
||||||
context->CopyBuffer(buffer->GPU.IndirectDrawArgsBuffer, buffer->GPU.Buffer, 4, offset + 4, counterOffset);
|
|
||||||
indirectDrawCallIndex++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Model Rendering
|
|
||||||
case 403:
|
|
||||||
{
|
|
||||||
const auto model = (Model*)module->Assets[0].Get();
|
|
||||||
|
|
||||||
// TODO: model LOD picking for particles?
|
|
||||||
int32 lodIndex = 0;
|
|
||||||
ModelLOD& lod = model->LODs[lodIndex];
|
|
||||||
for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++)
|
|
||||||
{
|
|
||||||
Mesh& mesh = lod.Meshes[meshIndex];
|
|
||||||
if (!mesh.IsInitialized())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
GPUDrawIndexedIndirectArgs indirectArgsBufferInitData = { (uint32)mesh.GetTriangleCount() * 3, 1, 0, 0, 0 };
|
|
||||||
const uint32 offset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
|
||||||
context->UpdateBuffer(buffer->GPU.IndirectDrawArgsBuffer, &indirectArgsBufferInitData, sizeof(indirectArgsBufferInitData), offset);
|
|
||||||
const uint32 counterOffset = buffer->GPU.ParticleCounterOffset;
|
|
||||||
context->CopyBuffer(buffer->GPU.IndirectDrawArgsBuffer, buffer->GPU.Buffer, 4, offset + 4, counterOffset);
|
|
||||||
indirectDrawCallIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Ribbon Rendering
|
|
||||||
case 404:
|
|
||||||
{
|
|
||||||
// Not supported
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Volumetric Fog Rendering
|
|
||||||
case 405:
|
|
||||||
{
|
|
||||||
// Not supported
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute all rendering modules
|
|
||||||
indirectDrawCallIndex = 0;
|
|
||||||
for (int32 index = 0; index < renderModulesIndices.Count(); index++)
|
|
||||||
{
|
|
||||||
int32 moduleIndex = renderModulesIndices[index];
|
|
||||||
auto module = emitter->Graph.RenderModules[moduleIndex];
|
|
||||||
drawCall.Particle.Module = module;
|
drawCall.Particle.Module = module;
|
||||||
|
|
||||||
switch (module->TypeID)
|
switch (module->TypeID)
|
||||||
{
|
{
|
||||||
// Sprite Rendering
|
// Sprite Rendering
|
||||||
@@ -909,19 +848,24 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
|||||||
{
|
{
|
||||||
const auto material = (MaterialBase*)module->Assets[0].Get();
|
const auto material = (MaterialBase*)module->Assets[0].Get();
|
||||||
const auto moduleDrawModes = module->Values.Count() > 3 ? (DrawPass)module->Values[3].AsInt : DrawPass::Default;
|
const auto moduleDrawModes = module->Values.Count() > 3 ? (DrawPass)module->Values[3].AsInt : DrawPass::Default;
|
||||||
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
|
||||||
indirectDrawCallIndex++;
|
|
||||||
auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
|
auto dp = drawModes & moduleDrawModes & material->GetDrawModes();
|
||||||
if (dp == DrawPass::None || SpriteRenderer.Init())
|
if (dp == DrawPass::None || SpriteRenderer.Init())
|
||||||
break;
|
break;
|
||||||
drawCall.Material = material;
|
drawCall.Material = material;
|
||||||
|
|
||||||
|
// Initialize indirect draw arguments
|
||||||
|
GPUDrawIndexedIndirectArgs args { SpriteParticleRenderer::IndexCount, 1, 0, 0, 0 };
|
||||||
|
const uint32 argsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||||
|
context->UpdateBuffer(buffer->GPU.IndirectDrawArgsBuffer, &args, sizeof(args), argsOffset);
|
||||||
|
context->CopyBuffer(buffer->GPU.IndirectDrawArgsBuffer, buffer->GPU.Buffer, 4, argsOffset + 4, buffer->GPU.ParticleCounterOffset);
|
||||||
|
|
||||||
// Submit draw call
|
// Submit draw call
|
||||||
SpriteRenderer.SetupDrawCall(drawCall);
|
SpriteRenderer.SetupDrawCall(drawCall);
|
||||||
drawCall.InstanceCount = 0;
|
drawCall.InstanceCount = 0;
|
||||||
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||||
if (dp != DrawPass::None)
|
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||||
renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder);
|
renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder);
|
||||||
|
indirectDrawCallIndex++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Model Rendering
|
// Model Rendering
|
||||||
@@ -943,13 +887,18 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
|||||||
continue;
|
continue;
|
||||||
// TODO: include mesh entry transformation, visibility and shadows mode?
|
// TODO: include mesh entry transformation, visibility and shadows mode?
|
||||||
|
|
||||||
|
// Initialize indirect draw arguments
|
||||||
|
GPUDrawIndexedIndirectArgs args = { (uint32)mesh.GetTriangleCount() * 3, 1, 0, 0, 0 };
|
||||||
|
const uint32 argsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||||
|
context->UpdateBuffer(buffer->GPU.IndirectDrawArgsBuffer, &args, sizeof(args), argsOffset);
|
||||||
|
context->CopyBuffer(buffer->GPU.IndirectDrawArgsBuffer, buffer->GPU.Buffer, 4, argsOffset + 4, buffer->GPU.ParticleCounterOffset);
|
||||||
|
|
||||||
// Execute draw call
|
// Execute draw call
|
||||||
mesh.GetDrawCallGeometry(drawCall);
|
mesh.GetDrawCallGeometry(drawCall);
|
||||||
drawCall.InstanceCount = 0;
|
drawCall.InstanceCount = 0;
|
||||||
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||||
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||||
if (dp != DrawPass::None)
|
renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder);
|
||||||
renderContext.List->AddDrawCall(renderContext, dp, staticFlags, drawCall, false, sortOrder);
|
|
||||||
indirectDrawCallIndex++;
|
indirectDrawCallIndex++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user