Optimize DrawCall to pack indirect draw arg and graphics draw data with union
This commit is contained in:
@@ -359,8 +359,8 @@ void Mesh::GetDrawCallGeometry(DrawCall& drawCall) const
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = _triangles * 3;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = _triangles * 3;
|
||||
}
|
||||
|
||||
void Mesh::Render(GPUContext* context) const
|
||||
@@ -386,11 +386,9 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = _triangles * 3;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = _triangles * 3;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Material = material;
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
@@ -449,11 +447,9 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
|
||||
drawCall.Geometry.VertexBuffers[2] = info.VertexColors[_lodIndex];
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = vertexOffset * sizeof(VB2ElementType);
|
||||
}
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = _triangles * 3;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = _triangles * 3;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
|
||||
@@ -186,11 +186,9 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = _triangles * 3;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = _triangles * 3;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
|
||||
@@ -353,8 +353,6 @@ void SplineModel::Draw(RenderContext& renderContext)
|
||||
// Draw all segments
|
||||
DrawCall drawCall;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Deformable.SplineDeformation = _deformationBuffer;
|
||||
drawCall.Deformable.ChunksPerSegment = _chunksPerSegment;
|
||||
drawCall.Deformable.MeshMinZ = _meshMinZ;
|
||||
|
||||
@@ -83,8 +83,8 @@ public:
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = IndexCount;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = IndexCount;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -173,10 +173,6 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
const auto context = GPUDevice::Instance->GetMainContext();
|
||||
auto emitter = buffer->Emitter;
|
||||
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
|
||||
// Check if need to perform any particles sorting
|
||||
if (emitter->Graph.SortModules.HasItems() && renderContext.View.Pass != DrawPass::Depth)
|
||||
{
|
||||
@@ -516,8 +512,8 @@ void DrawEmitterCPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = ribbonModulesDrawIndicesStart[ribbonModuleIndex];
|
||||
drawCall.Geometry.IndicesCount = ribbonModulesDrawIndicesCount[ribbonModuleIndex];
|
||||
drawCall.Draw.StartIndex = ribbonModulesDrawIndicesStart[ribbonModuleIndex];
|
||||
drawCall.Draw.IndicesCount = ribbonModulesDrawIndicesCount[ribbonModuleIndex];
|
||||
drawCall.InstanceCount = 1;
|
||||
renderContext.List->AddDrawCall((DrawPass)(drawModes & moduleDrawModes), staticFlags, drawCall, false);
|
||||
|
||||
@@ -802,8 +798,8 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
// Submit draw call
|
||||
SpriteRenderer.SetupDrawCall(drawCall);
|
||||
drawCall.InstanceCount = 0;
|
||||
drawCall.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||
drawCall.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||
renderContext.List->AddDrawCall((DrawPass)(drawModes & moduleDrawModes), staticFlags, drawCall, false);
|
||||
indirectDrawCallIndex++;
|
||||
|
||||
@@ -830,8 +826,8 @@ void DrawEmitterGPU(RenderContext& renderContext, ParticleBuffer* buffer, DrawCa
|
||||
// Execute draw call
|
||||
mesh.GetDrawCallGeometry(drawCall);
|
||||
drawCall.InstanceCount = 0;
|
||||
drawCall.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||
drawCall.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||
drawCall.Draw.IndirectArgsBuffer = buffer->GPU.IndirectDrawArgsBuffer;
|
||||
drawCall.Draw.IndirectArgsOffset = indirectDrawCallIndex * sizeof(GPUDrawIndexedIndirectArgs);
|
||||
renderContext.List->AddDrawCall((DrawPass)(drawModes & moduleDrawModes), staticFlags, drawCall, false);
|
||||
indirectDrawCallIndex++;
|
||||
}
|
||||
|
||||
@@ -134,16 +134,6 @@ struct DrawCall
|
||||
/// The geometry vertex buffers byte offsets.
|
||||
/// </summary>
|
||||
uint32 VertexBuffersOffsets[3];
|
||||
|
||||
/// <summary>
|
||||
/// The location of the first index read by the GPU from the index buffer.
|
||||
/// </summary>
|
||||
int32 StartIndex;
|
||||
|
||||
/// <summary>
|
||||
/// The indices count.
|
||||
/// </summary>
|
||||
int32 IndicesCount;
|
||||
} Geometry;
|
||||
|
||||
/// <summary>
|
||||
@@ -151,15 +141,34 @@ struct DrawCall
|
||||
/// </summary>
|
||||
int32 InstanceCount;
|
||||
|
||||
/// <summary>
|
||||
/// The indirect draw arguments offset.
|
||||
/// </summary>
|
||||
uint32 IndirectArgsOffset;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of the first index read by the GPU from the index buffer.
|
||||
/// </summary>
|
||||
int32 StartIndex;
|
||||
|
||||
/// <summary>
|
||||
/// The indirect draw arguments buffer.
|
||||
/// </summary>
|
||||
GPUBuffer* IndirectArgsBuffer;
|
||||
/// <summary>
|
||||
/// The indices count.
|
||||
/// </summary>
|
||||
int32 IndicesCount;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
/// <summary>
|
||||
/// The indirect draw arguments offset.
|
||||
/// </summary>
|
||||
uint32 IndirectArgsOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The indirect draw arguments buffer.
|
||||
/// </summary>
|
||||
GPUBuffer* IndirectArgsBuffer;
|
||||
};
|
||||
} Draw;
|
||||
|
||||
// Per-material shader data packed into union
|
||||
union
|
||||
|
||||
@@ -514,8 +514,8 @@ namespace
|
||||
return a.Material == b.Material &&
|
||||
a.Material->CanUseInstancing(handler) &&
|
||||
Platform::MemoryCompare(&a.Geometry, &b.Geometry, sizeof(a.Geometry)) == 0 &&
|
||||
a.IndirectArgsBuffer == nullptr &&
|
||||
b.IndirectArgsBuffer == nullptr &&
|
||||
a.InstanceCount != 0 &&
|
||||
b.InstanceCount != 0 &&
|
||||
a.WorldDeterminantSign == b.WorldDeterminantSign;
|
||||
}
|
||||
}
|
||||
@@ -690,20 +690,20 @@ DRAW:
|
||||
|
||||
context->BindIB(drawCall.Geometry.IndexBuffer);
|
||||
|
||||
if (drawCall.IndirectArgsBuffer)
|
||||
if (drawCall.InstanceCount == 0)
|
||||
{
|
||||
// No support for batching indirect draw calls
|
||||
ASSERT(batch.BatchSize == 1);
|
||||
|
||||
context->BindVB(ToSpan(vb, vbCount), vbOffsets);
|
||||
context->DrawIndexedInstancedIndirect(drawCall.IndirectArgsBuffer, drawCall.IndirectArgsOffset);
|
||||
context->DrawIndexedInstancedIndirect(drawCall.Draw.IndirectArgsBuffer, drawCall.Draw.IndirectArgsOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (batch.BatchSize == 1)
|
||||
{
|
||||
context->BindVB(ToSpan(vb, vbCount), vbOffsets);
|
||||
context->DrawIndexedInstanced(drawCall.Geometry.IndicesCount, batch.InstanceCount, 0, 0, drawCall.Geometry.StartIndex);
|
||||
context->DrawIndexedInstanced(drawCall.Draw.IndicesCount, batch.InstanceCount, 0, 0, drawCall.Draw.StartIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -712,7 +712,7 @@ DRAW:
|
||||
vbOffsets[vbCount] = 0;
|
||||
vbCount++;
|
||||
context->BindVB(ToSpan(vb, vbCount), vbOffsets);
|
||||
context->DrawIndexedInstanced(drawCall.Geometry.IndicesCount, batch.InstanceCount, instanceBufferOffset, 0, drawCall.Geometry.StartIndex);
|
||||
context->DrawIndexedInstanced(drawCall.Draw.IndicesCount, batch.InstanceCount, instanceBufferOffset, 0, drawCall.Draw.StartIndex);
|
||||
|
||||
instanceBufferOffset += batch.BatchSize;
|
||||
}
|
||||
@@ -735,13 +735,13 @@ DRAW:
|
||||
context->BindIB(drawCall.Geometry.IndexBuffer);
|
||||
context->BindVB(ToSpan(drawCall.Geometry.VertexBuffers, 3), drawCall.Geometry.VertexBuffersOffsets);
|
||||
|
||||
if (drawCall.IndirectArgsBuffer)
|
||||
if (drawCall.InstanceCount == 0)
|
||||
{
|
||||
context->DrawIndexedInstancedIndirect(drawCall.IndirectArgsBuffer, drawCall.IndirectArgsOffset);
|
||||
context->DrawIndexedInstancedIndirect(drawCall.Draw.IndirectArgsBuffer, drawCall.Draw.IndirectArgsOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
context->DrawIndexedInstanced(drawCall.Geometry.IndicesCount, drawCall.InstanceCount, 0, 0, drawCall.Geometry.StartIndex);
|
||||
context->DrawIndexedInstanced(drawCall.Draw.IndicesCount, drawCall.InstanceCount, 0, 0, drawCall.Draw.StartIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
context->SetState(_psRenderCacheTerrain);
|
||||
context->BindIB(drawCall.Geometry.IndexBuffer);
|
||||
context->BindVB(ToSpan(drawCall.Geometry.VertexBuffers, 1));
|
||||
context->DrawIndexed(drawCall.Geometry.IndicesCount, 0, drawCall.Geometry.StartIndex);
|
||||
context->DrawIndexed(drawCall.Draw.IndicesCount, 0, drawCall.Draw.StartIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -83,8 +83,6 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
|
||||
if (TerrainManager::GetChunkGeometry(drawCall, chunkSize, lod))
|
||||
return;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Material = _cachedDrawMaterial;
|
||||
drawCall.World = _world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
@@ -140,8 +138,6 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
|
||||
if (TerrainManager::GetChunkGeometry(drawCall, chunkSize, lod))
|
||||
return;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
drawCall.Material = material;
|
||||
drawCall.World = _world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
drawCall.Geometry.VertexBuffersOffsets[0] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.Geometry.StartIndex = 0;
|
||||
drawCall.Geometry.IndicesCount = IndicesCount;
|
||||
drawCall.Draw.StartIndex = 0;
|
||||
drawCall.Draw.IndicesCount = IndicesCount;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -336,14 +336,12 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
drawCall.Geometry.VertexBuffersOffsets[1] = 0;
|
||||
drawCall.Geometry.VertexBuffersOffsets[2] = 0;
|
||||
drawCall.InstanceCount = 1;
|
||||
drawCall.IndirectArgsBuffer = nullptr;
|
||||
drawCall.IndirectArgsOffset = 0;
|
||||
|
||||
// Submit draw calls
|
||||
for (const auto& e : _drawChunks)
|
||||
{
|
||||
drawCall.Geometry.IndicesCount = e.IndicesCount;
|
||||
drawCall.Geometry.StartIndex = e.StartIndex;
|
||||
drawCall.Draw.IndicesCount = e.IndicesCount;
|
||||
drawCall.Draw.StartIndex = e.StartIndex;
|
||||
drawCall.Material = e.Material;
|
||||
renderContext.List->AddDrawCall(drawModes, GetStaticFlags(), drawCall, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user