feat: draw meshes with instanced multi-draw indirect
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
#include <destrum/Graphics/GfxDevice.h>
|
||||
#include <destrum/Graphics/RenderResources.h>
|
||||
#include <destrum/Graphics/Caches/MeshCache.h>
|
||||
#include <destrum/Graphics/Frustum.h>
|
||||
#include <destrum/Graphics/Util.h>
|
||||
|
||||
#include "volk.h"
|
||||
@@ -119,10 +118,9 @@ void MeshPipeline::drawDepthPrepass(
|
||||
VkCommandBuffer cmd,
|
||||
VkExtent2D renderExtent,
|
||||
const RenderResources& resources,
|
||||
const Camera& camera,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
const std::vector<MeshDrawCommand>& drawCommands,
|
||||
const std::vector<std::size_t>& sortedDrawCommands)
|
||||
const IndirectDrawList& drawList,
|
||||
const IndirectDrawList::View& view)
|
||||
{
|
||||
if (!m_depthPrepassPipeline)
|
||||
{
|
||||
@@ -134,20 +132,18 @@ void MeshPipeline::drawDepthPrepass(
|
||||
*m_depthPrepassPipeline,
|
||||
renderExtent,
|
||||
resources,
|
||||
camera,
|
||||
sceneDataBuffer,
|
||||
drawCommands,
|
||||
sortedDrawCommands);
|
||||
drawList,
|
||||
view);
|
||||
}
|
||||
|
||||
void MeshPipeline::draw(
|
||||
VkCommandBuffer cmd,
|
||||
VkExtent2D renderExtent,
|
||||
const RenderResources& resources,
|
||||
const Camera& camera,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
const std::vector<MeshDrawCommand>& drawCommands,
|
||||
const std::vector<std::size_t>& sortedDrawCommands)
|
||||
const IndirectDrawList& drawList,
|
||||
const IndirectDrawList::View& view)
|
||||
{
|
||||
if (!m_pipeline)
|
||||
{
|
||||
@@ -159,10 +155,9 @@ void MeshPipeline::draw(
|
||||
*m_pipeline,
|
||||
renderExtent,
|
||||
resources,
|
||||
camera,
|
||||
sceneDataBuffer,
|
||||
drawCommands,
|
||||
sortedDrawCommands);
|
||||
drawList,
|
||||
view);
|
||||
}
|
||||
|
||||
void MeshPipeline::drawMeshes(
|
||||
@@ -170,13 +165,10 @@ void MeshPipeline::drawMeshes(
|
||||
const Pipeline& pipeline,
|
||||
VkExtent2D renderExtent,
|
||||
const RenderResources& resources,
|
||||
const Camera& camera,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
const std::vector<MeshDrawCommand>& drawCommands,
|
||||
const std::vector<std::size_t>& sortedDrawCommands)
|
||||
const IndirectDrawList& drawList,
|
||||
const IndirectDrawList::View& view)
|
||||
{
|
||||
const MeshCache& meshCache = resources.meshes();
|
||||
|
||||
pipeline.bind(cmd);
|
||||
|
||||
resources.bindBindlessDescSet(cmd, m_pipelineLayout);
|
||||
@@ -204,86 +196,32 @@ void MeshPipeline::drawMeshes(
|
||||
m_renderWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL
|
||||
);
|
||||
|
||||
MeshID prevMeshId = NULL_MESH_ID;
|
||||
int actualDrawCalls = 0;
|
||||
|
||||
const auto frustum = edge::createFrustumFromCamera(camera);
|
||||
|
||||
const auto drawOne = [&](const MeshDrawCommand& dc)
|
||||
{
|
||||
if (!edge::isInFrustum(frustum, dc.worldBoundingSphere))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++actualDrawCalls;
|
||||
|
||||
const auto& mesh = meshCache.getMesh(dc.meshId);
|
||||
|
||||
const std::string& meshKey = meshCache.getMeshKey(dc.meshId);
|
||||
vkutil::cmdBeginLabelFormatted(
|
||||
cmd,
|
||||
vkutil::labelColors::draw,
|
||||
"%s [mesh %zu, material %u%s]",
|
||||
meshKey.empty() ? "Mesh" : meshKey.c_str(),
|
||||
dc.meshId,
|
||||
dc.materialId,
|
||||
dc.skinnedMesh != nullptr ? ", skinned" : "");
|
||||
|
||||
if (dc.meshId != prevMeshId)
|
||||
{
|
||||
prevMeshId = dc.meshId;
|
||||
|
||||
vkCmdBindIndexBuffer(
|
||||
cmd,
|
||||
mesh.indexBuffer.buffer,
|
||||
0,
|
||||
VK_INDEX_TYPE_UINT32
|
||||
);
|
||||
}
|
||||
|
||||
assert(dc.materialId != NULL_MATERIAL_ID);
|
||||
|
||||
const auto pushConstants = PushConstants{
|
||||
.transform = dc.transformMatrix,
|
||||
.sceneDataBuffer = sceneDataBuffer.address,
|
||||
.vertexBuffer =
|
||||
dc.skinnedMesh != nullptr
|
||||
? dc.skinnedMesh->skinnedVertexBuffer.address
|
||||
: mesh.vertexBuffer.address,
|
||||
.materialId = dc.materialId,
|
||||
.padding = 0,
|
||||
};
|
||||
|
||||
vkCmdPushConstants(
|
||||
cmd,
|
||||
m_pipelineLayout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0,
|
||||
sizeof(PushConstants),
|
||||
&pushConstants
|
||||
);
|
||||
|
||||
vkCmdDrawIndexed(cmd, mesh.numIndices, 1, 0, 0, 0);
|
||||
|
||||
vkutil::cmdEndLabel(cmd);
|
||||
// The same for every draw, per-draw data (transform, material, vertex buffer)
|
||||
// lives in the instance buffer and is looked up with gl_InstanceIndex
|
||||
const auto pushConstants = PushConstants{
|
||||
.sceneDataBuffer = sceneDataBuffer.address,
|
||||
.instanceBuffer = drawList.getInstanceBufferAddress(),
|
||||
};
|
||||
|
||||
if (!sortedDrawCommands.empty())
|
||||
{
|
||||
for (std::size_t drawIndex : sortedDrawCommands)
|
||||
{
|
||||
assert(drawIndex < drawCommands.size());
|
||||
drawOne(drawCommands[drawIndex]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const MeshDrawCommand& dc : drawCommands)
|
||||
{
|
||||
drawOne(dc);
|
||||
}
|
||||
}
|
||||
vkCmdPushConstants(
|
||||
cmd,
|
||||
m_pipelineLayout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0,
|
||||
sizeof(PushConstants),
|
||||
&pushConstants
|
||||
);
|
||||
|
||||
vkutil::cmdBeginLabelFormatted(
|
||||
cmd,
|
||||
vkutil::labelColors::draw,
|
||||
"%u indirect draws, %u instances",
|
||||
view.commandCount,
|
||||
view.instanceCount);
|
||||
|
||||
drawList.draw(cmd, resources.meshes().getIndexBuffer(), view);
|
||||
|
||||
vkutil::cmdEndLabel(cmd);
|
||||
}
|
||||
|
||||
void MeshPipeline::cleanup(VkDevice device)
|
||||
|
||||
Reference in New Issue
Block a user