Working on visibility pass

This commit is contained in:
Dynamitos
2024-06-07 09:19:47 +02:00
parent ad00e16cf9
commit cb21e8a85a
24 changed files with 450 additions and 373 deletions
+5 -4
View File
@@ -3,17 +3,18 @@ import Scene;
groupshared MeshPayload p; groupshared MeshPayload p;
groupshared uint head; groupshared uint head;
groupshared MeshData mesh;
[numthreads(TASK_GROUP_SIZE, 1, 1)] [numthreads(TASK_GROUP_SIZE, 1, 1)]
[shader("amplification")] [shader("amplification")]
void taskMain( void taskMain(
uint threadID: SV_GroupIndex, uint threadID: SV_GroupThreadID,
uint groupID: SV_GroupID, ) uint groupID: SV_GroupID, )
{ {
MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
if (threadID == 0) if (threadID == 0)
{ {
head = 0; head = 0;
mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
p.instanceId = pOffsets.instanceOffset + groupID; p.instanceId = pOffsets.instanceOffset + groupID;
p.meshletOffset = mesh.meshletOffset; p.meshletOffset = mesh.meshletOffset;
p.cullingOffset = pScene.cullingOffsets[p.instanceId]; p.cullingOffset = pScene.cullingOffsets[p.instanceId];
@@ -24,8 +25,8 @@ void taskMain(
uint m = p.meshletOffset + i; uint m = p.meshletOffset + i;
uint cull = p.cullingOffset + i; uint cull = p.cullingOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m]; MeshletDescription meshlet = pScene.meshletInfos[m];
MeshletCullingInfo culling = pScene.culledMeshlets[cull]; MeshletCullingInfo culling = pScene.cullingInfos[cull];
if(false) //if(!culling.anyVisible())
{ {
uint index; uint index;
InterlockedAdd(head, 1, index); InterlockedAdd(head, 1, index);
+2 -2
View File
@@ -8,7 +8,7 @@ groupshared MeshData mesh;
[numthreads(TASK_GROUP_SIZE, 1, 1)] [numthreads(TASK_GROUP_SIZE, 1, 1)]
[shader("amplification")] [shader("amplification")]
void taskMain( void taskMain(
uint threadID: SV_GroupIndex, uint threadID: SV_GroupThreadID,
uint groupID: SV_GroupID, ) uint groupID: SV_GroupID, )
{ {
if (threadID == 0) if (threadID == 0)
@@ -25,7 +25,7 @@ void taskMain(
uint m = p.meshletOffset + i; uint m = p.meshletOffset + i;
uint cull = p.cullingOffset + i; uint cull = p.cullingOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m]; MeshletDescription meshlet = pScene.meshletInfos[m];
MeshletCullingInfo culling = pScene.culledMeshlets[cull]; MeshletCullingInfo culling = pScene.cullingInfos[cull];
if(culling.anyVisible()) if(culling.anyVisible())
{ {
uint index; uint index;
+2 -2
View File
@@ -15,7 +15,7 @@ struct PrimitiveAttributes
[outputtopology("triangle")] [outputtopology("triangle")]
[shader("mesh")] [shader("mesh")]
void meshMain( void meshMain(
in uint threadID: SV_GroupIndex, in uint threadID: SV_GroupThreadID,
in uint groupID: SV_GroupID, in uint groupID: SV_GroupID,
in payload MeshPayload meshPayload, in payload MeshPayload meshPayload,
out vertices FragmentParameter vertices[MAX_VERTICES], out vertices FragmentParameter vertices[MAX_VERTICES],
@@ -27,7 +27,7 @@ void meshMain(
uint meshletId = meshPayload.cullingOffset + meshletNumber; uint meshletId = meshPayload.cullingOffset + meshletNumber;
InstanceData inst = pScene.instances[meshPayload.instanceId]; InstanceData inst = pScene.instances[meshPayload.instanceId];
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber]; MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
MeshletCullingInfo cull = pScene.culledMeshlets[meshletId]; MeshletCullingInfo cull = pScene.cullingInfos[meshletId];
SetMeshOutputCounts(m.vertexCount, m.primitiveCount); SetMeshOutputCounts(m.vertexCount, m.primitiveCount);
for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE) for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE)
+8 -28
View File
@@ -8,35 +8,15 @@ struct VisibilityCullingData
}; };
ParameterBlock<VisibilityCullingData> pVisibilityParams; ParameterBlock<VisibilityCullingData> pVisibilityParams;
groupshared MeshletCullingInfo cullInfo; [numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
[numthreads(BLOCK_SIZE, 1, 1)]
[shader("compute")] [shader("compute")]
void computeMain( void computeMain(
uint threadID: SV_GroupIndex, uint3 dispatchThreadID: SV_DispatchThreadID,
uint groupID: SV_GroupID,
){ ){
if (threadID < MAX_PRIMITIVES / 32) int3 texCoords = int3(dispatchThreadID.xy, 0);
{ uint encoded = pVisibilityParams.visibilityTexture.Load(texCoords).r;
cullInfo.visible[threadID] = 0; uint2 decoded = decodePrimitive(encoded);
} uint arrIdx = decoded.x / 32;
GroupMemoryBarrierWithGroupSync(); uint bit = decoded.x % 32;
for (uint y = 0; y < pViewParams.screenDimensions.y; y++) pVisibilityParams.cullingInfos[decoded.y].visible[arrIdx] |= (1 << bit);
{
for (uint x = threadID; x < pViewParams.screenDimensions.x; x += BLOCK_SIZE)
{
int3 texCoords = int3(x, y, 0);
uint encoded = pVisibilityParams.visibilityTexture.Load(texCoords).r;
uint2 decoded = decodePrimitive(encoded);
uint base = decoded.y == groupID ? 1 : 0;
uint arrIdx = decoded.x / 32;
uint bit = decoded.x % 32;
cullInfo.visible[arrIdx] |= (base << bit);
}
}
GroupMemoryBarrierWithGroupSync();
if (threadID < MAX_PRIMITIVES / 32)
{
pVisibilityParams.cullingInfos[groupID].visible[threadID] = cullInfo.visible[threadID];
}
} }
+2 -2
View File
@@ -66,10 +66,10 @@ struct Scene
StructuredBuffer<MeshletDescription> meshletInfos; StructuredBuffer<MeshletDescription> meshletInfos;
StructuredBuffer<uint8_t> primitiveIndices; StructuredBuffer<uint8_t> primitiveIndices;
StructuredBuffer<uint32_t> vertexIndices; StructuredBuffer<uint32_t> vertexIndices;
StructuredBuffer<MeshletCullingInfo> culledMeshlets;
StructuredBuffer<uint32_t> cullingOffsets; StructuredBuffer<uint32_t> cullingOffsets;
StructuredBuffer<MeshletCullingInfo> cullingInfos;
}; };
layout(set = 2) layout(set=2)
ParameterBlock<Scene> pScene; ParameterBlock<Scene> pScene;
uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId) uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId)
+2
View File
@@ -89,6 +89,8 @@ public:
bool writeOnly = true) = 0; bool writeOnly = true) = 0;
virtual void unmap() = 0; virtual void unmap() = 0;
virtual void clear() = 0;
protected: protected:
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(QueueType newOwner) = 0; virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
+6 -15
View File
@@ -85,19 +85,6 @@ void BasePass::beginFrame(const Component::Camera& cam)
void BasePass::render() void BasePass::render()
{ {
oLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
tLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
oLightGrid->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
tLightGrid->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
opaqueCulling->updateBuffer(0, oLightIndexList); opaqueCulling->updateBuffer(0, oLightIndexList);
opaqueCulling->updateTexture(1, oLightGrid); opaqueCulling->updateTexture(1, oLightGrid);
transparentCulling->updateBuffer(0, tLightIndexList); transparentCulling->updateBuffer(0, tLightIndexList);
@@ -112,6 +99,8 @@ void BasePass::render()
permutation.setViewCulling(useViewCulling); permutation.setViewCulling(useViewCulling);
for (VertexData* vertexData : VertexData::getList()) for (VertexData* vertexData : VertexData::getList())
{ {
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
vertexData->getInstanceDataSet()->writeChanges();
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
const auto& materials = vertexData->getMaterialData(); const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) for (const auto& materialData : materials)
@@ -176,11 +165,11 @@ void BasePass::render()
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline); command->bindPipeline(pipeline);
} }
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(viewParamsSet); command->bindDescriptor(viewParamsSet);
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(vertexData->getInstanceDataSet());
command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet()); command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet());
command->bindDescriptor(opaqueCulling); command->bindDescriptor(opaqueCulling);
command->bindDescriptor(vertexData->getInstanceDataSet());
for (const auto& drawCall : materialData.instances) for (const auto& drawCall : materialData.instances)
{ {
command->bindDescriptor(drawCall.materialInstance->getDescriptorSet()); command->bindDescriptor(drawCall.materialInstance->getDescriptorSet());
@@ -221,6 +210,8 @@ void BasePass::publishOutputs()
void BasePass::createRenderPass() void BasePass::createRenderPass()
{ {
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
@@ -32,6 +32,8 @@ private:
PCameraActor source; PCameraActor source;
Gfx::OPipelineLayout basePassLayout; Gfx::OPipelineLayout basePassLayout;
Gfx::ODescriptorLayout lightCullingLayout; Gfx::ODescriptorLayout lightCullingLayout;
Gfx::PShaderBuffer cullingBuffer;
}; };
DEFINE_REF(BasePass) DEFINE_REF(BasePass)
} // namespace Seele } // namespace Seele
@@ -66,6 +66,8 @@ void CachedDepthPass::render()
for (VertexData *vertexData : VertexData::getList()) for (VertexData *vertexData : VertexData::getList())
{ {
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
vertexData->getInstanceDataSet()->writeChanges();
// Create Pipeline(VertexData) // Create Pipeline(VertexData)
// Descriptors: // Descriptors:
@@ -120,8 +122,8 @@ void CachedDepthPass::render()
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline); command->bindPipeline(pipeline);
} }
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(viewParamsSet); command->bindDescriptor(viewParamsSet);
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(vertexData->getInstanceDataSet()); command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0; uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset); command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
@@ -205,6 +207,8 @@ void CachedDepthPass::publishOutputs()
void CachedDepthPass::createRenderPass() void CachedDepthPass::createRenderPass()
{ {
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {visibilityAttachment}, .colorAttachments = {visibilityAttachment},
.depthAttachment = depthAttachment, .depthAttachment = depthAttachment,
@@ -21,6 +21,8 @@ private:
Gfx::OTexture2D depthBuffer; Gfx::OTexture2D depthBuffer;
Gfx::OTexture2D visibilityBuffer; Gfx::OTexture2D visibilityBuffer;
Gfx::OPipelineLayout depthPrepassLayout; Gfx::OPipelineLayout depthPrepassLayout;
Gfx::PShaderBuffer cullingBuffer;
}; };
DEFINE_REF(CachedDepthPass) DEFINE_REF(CachedDepthPass)
} }
@@ -66,6 +66,8 @@ void DepthPrepass::render()
for (VertexData *vertexData : VertexData::getList()) for (VertexData *vertexData : VertexData::getList())
{ {
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
vertexData->getInstanceDataSet()->writeChanges();
// Create Pipeline(VertexData) // Create Pipeline(VertexData)
// Descriptors: // Descriptors:
// ViewData => global, static // ViewData => global, static
@@ -119,14 +121,14 @@ void DepthPrepass::render()
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline); command->bindPipeline(pipeline);
} }
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(viewParamsSet); command->bindDescriptor(viewParamsSet);
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(vertexData->getInstanceDataSet()); command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0; uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset); command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
//command->drawMesh(vertexData->getNumInstances(), 1, 1); command->drawMesh(vertexData->getNumInstances(), 1, 1);
} }
else else
{ {
@@ -174,6 +176,13 @@ void DepthPrepass::render()
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
); );
// Sync culling reads to compute write
cullingBuffer->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT,
Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
);
} }
void DepthPrepass::endFrame() void DepthPrepass::endFrame()
@@ -186,13 +195,15 @@ void DepthPrepass::publishOutputs()
void DepthPrepass::createRenderPass() void DepthPrepass::createRenderPass()
{ {
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
visibilityAttachment = resources->requestRenderTarget("VISIBILITY"); visibilityAttachment = resources->requestRenderTarget("VISIBILITY");
visibilityAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); visibilityAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
visibilityAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); visibilityAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
@@ -20,6 +20,8 @@ private:
Gfx::RenderTargetAttachment depthAttachment; Gfx::RenderTargetAttachment depthAttachment;
Gfx::RenderTargetAttachment visibilityAttachment; Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::OPipelineLayout depthPrepassLayout; Gfx::OPipelineLayout depthPrepassLayout;
Gfx::PShaderBuffer cullingBuffer;
}; };
DEFINE_REF(DepthPrepass) DEFINE_REF(DepthPrepass)
} // namespace Seele } // namespace Seele
@@ -81,6 +81,19 @@ void LightCullingPass::render()
commands.add(std::move(computeCommand)); commands.add(std::move(computeCommand));
//std::cout << "Execute" << std::endl; //std::cout << "Execute" << std::endl;
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
oLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
tLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
oLightGrid->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
tLightGrid->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
} }
void LightCullingPass::endFrame() void LightCullingPass::endFrame()
@@ -1,4 +1,5 @@
#include "VisibilityPass.h" #include "VisibilityPass.h"
#include "Graphics/Shader.h"
using namespace Seele; using namespace Seele;
@@ -15,15 +16,46 @@ VisibilityPass::~VisibilityPass()
void VisibilityPass::beginFrame(const Component::Camera& cam) void VisibilityPass::beginFrame(const Component::Camera& cam)
{ {
RenderPass::beginFrame(cam); RenderPass::beginFrame(cam);
visibilityDescriptor->reset();
visibilitySet = visibilityDescriptor->allocateDescriptorSet(); //Array<VertexData::MeshletCullingInfo> cullingData(VertexData::getMeshletCount());
visibilitySet->updateTexture(0, visibilityAttachment->getTexture()); //std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(VertexData::MeshletCullingInfo));
visibliitySet->updateBuffer(StaticMeshVertexData::getInstance()->get)
//cullingBuffer->updateContents(ShaderBufferCreateInfo{
// .sourceData = {
// .size = VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo),
// .data = (uint8 *)cullingData.data(),
// },
// .numElements = VertexData::getMeshletCount()});
//cullingBuffer->pipelineBarrier(
// Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
// Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
// Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
// Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
} }
void VisibilityPass::render() void VisibilityPass::render()
{ {
cullingBuffer->rotateBuffer(VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo));
cullingBuffer->clear();
visibilityDescriptor->reset();
visibilitySet = visibilityDescriptor->allocateDescriptorSet();
visibilitySet->updateTexture(0, visibilityAttachment.getTexture());
visibilitySet->updateBuffer(1, cullingBuffer);
visibilitySet->writeChanges();
Gfx::OComputeCommand command = graphics->createComputeCommand("VisibilityCommand");
command->bindPipeline(visibilityPipeline);
command->bindDescriptor({viewParamsSet, visibilitySet});
command->dispatch(threadGroupSize.x, threadGroupSize.y, threadGroupSize.z);
Array<Gfx::OComputeCommand> commands;
commands.add(std::move(command));
graphics->executeCommands(std::move(commands));
cullingBuffer->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
} }
void VisibilityPass::endFrame() void VisibilityPass::endFrame()
@@ -33,7 +65,10 @@ void VisibilityPass::endFrame()
void VisibilityPass::publishOutputs() void VisibilityPass::publishOutputs()
{ {
visibilityDescriptor = graphcis->createDescriptorLayout("pVisibilityParams"); uint32_t viewportWidth = viewport->getWidth();
uint32_t viewportHeight = viewport->getHeight();
threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, }); visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, });
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT, }); visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT, });
visibilityDescriptor->create(); visibilityDescriptor->create();
@@ -55,6 +90,9 @@ void VisibilityPass::publishOutputs()
pipelineInfo.computeShader = visibilityShader; pipelineInfo.computeShader = visibilityShader;
pipelineInfo.pipelineLayout = std::move(visibilityLayout); pipelineInfo.pipelineLayout = std::move(visibilityLayout);
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo)); visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.dynamic = true, .name = "CullingBuffer"});
resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer);
} }
void VisibilityPass::createRenderPass() void VisibilityPass::createRenderPass()
@@ -15,16 +15,18 @@ public:
virtual void endFrame() override; virtual void endFrame() override;
virtual void publishOutputs() override; virtual void publishOutputs() override;
virtual void createRenderPass() override; virtual void createRenderPass() override;
uint64 allocate
private: private:
static constexpr uint32 BLOCK_SIZE = 32;
Gfx::RenderTargetAttachment visibilityAttachment; Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::PDescriptorSet visibilitySet; Gfx::PDescriptorSet visibilitySet;
Gfx::ODescriptorLayout visibilityDescriptor; Gfx::ODescriptorLayout visibilityDescriptor;
Gfx::OPipelineLayout visibilityLayout; Gfx::OPipelineLayout visibilityLayout;
Gfx::OComputeShader visibilityShader;
Gfx::PComputePipeline visibilityPipeline; Gfx::PComputePipeline visibilityPipeline;
// Holds culling information for every meshlet for each instance // Holds culling information for every meshlet for each instance
Gfx::OShaderBuffer cullingBuffer; Gfx::OShaderBuffer cullingBuffer;
glm::uvec3 threadGroupSize;
}; };
DEFINE_REF(VisibilityPass) DEFINE_REF(VisibilityPass)
} }
+2 -1
View File
@@ -36,12 +36,13 @@ void ShaderCompiler::registerVertexData(VertexData *vd)
void ShaderCompiler::registerRenderPass(std::string name, PassConfig config) void ShaderCompiler::registerRenderPass(std::string name, PassConfig config)
{ {
passes[name] = config; passes[name] = std::move(config);
compile(); compile();
} }
ShaderPermutation ShaderCompiler::getTemplate(std::string name) ShaderPermutation ShaderCompiler::getTemplate(std::string name)
{ {
std::scoped_lock lock(shadersLock);
ShaderPermutation permutation; ShaderPermutation permutation;
PassConfig &pass = passes[name]; PassConfig &pass = passes[name];
if (pass.useMeshShading) if (pass.useMeshShading)
+296 -301
View File
@@ -12,370 +12,365 @@
using namespace Seele; using namespace Seele;
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024; constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024;
Map<VertexData::MeshMapping, VertexData::CullingMapping> VertexData::instanceIdMap;
uint64 VertexData::instanceCount = 0;
uint64 VertexData::meshletCount = 0;
void VertexData::resetMeshData() void VertexData::resetMeshData()
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
for (auto &mat : materialData) for (auto &mat : materialData)
{
for (auto &inst : mat.instances)
{ {
inst.instanceData.clear(); for (auto &inst : mat.instances)
inst.instanceMeshData.clear(); {
inst.instanceData.clear();
inst.instanceMeshData.clear();
}
if (mat.material != nullptr)
{
mat.material->getDescriptorLayout()->reset();
}
} }
if (mat.material != nullptr) if (dirty)
{ {
mat.material->getDescriptorLayout()->reset(); updateBuffers();
dirty = false;
} }
}
if (dirty)
{
updateBuffers();
dirty = false;
}
} }
void VertexData::updateMesh(PMesh mesh, Component::Transform &transform) void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform &transform)
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
PMaterial mat = referencedInstance->getBaseMaterial(); PMaterial mat = referencedInstance->getBaseMaterial();
if (materialData.size() <= mat->getId()) if (materialData.size() <= mat->getId())
{ {
materialData.resize(mat->getId() + 1); materialData.resize(mat->getId() + 1);
} }
MaterialData &matData = materialData[mat->getId()]; MaterialData &matData = materialData[mat->getId()];
matData.material = mat; matData.material = mat;
if (matData.instances.size() <= referencedInstance->getId()) if (matData.instances.size() <= referencedInstance->getId())
{ {
matData.instances.resize(referencedInstance->getId() + 1); matData.instances.resize(referencedInstance->getId() + 1);
} }
BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()]; BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()];
matInstanceData.materialInstance = referencedInstance; matInstanceData.materialInstance = referencedInstance;
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform; Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
matInstanceData.instanceData.add(InstanceData{ matInstanceData.instanceData.add(InstanceData{
.transformMatrix = transformMatrix, .transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix), .inverseTransformMatrix = glm::inverse(transformMatrix),
}); });
const auto &data = meshData[mesh->id]; const auto &data = meshData[mesh->id];
matInstanceData.instanceMeshData.add(data); auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
referencedInstance->updateDescriptor(); matInstanceData.instanceMeshData.add(data);
for (size_t i = 0; i < 0; ++i) matInstanceData.cullingOffsets.add(meshletOffset);
{ referencedInstance->updateDescriptor();
auto bounding = meshlets[data.meshletOffset + i].bounding; for (size_t i = 0; i < 0; ++i)
StaticArray<Vector, 8> corners; {
Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1); auto bounding = meshlets[data.meshletOffset + i].bounding;
Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1); StaticArray<Vector, 8> corners;
corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1); Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1);
corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1); Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1);
corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1); corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1);
corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1); corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1);
corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1); corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1);
corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1); corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1);
corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1); corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1);
corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1); corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1);
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1);
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1);
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color}); addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
} addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
}
} }
void VertexData::createDescriptors() void VertexData::createDescriptors()
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
instanceData.clear(); instanceData.clear();
instanceMeshData.clear(); instanceMeshData.clear();
uint32 numMeshlets = 0; uint32 numMeshlets = 0;
Array<uint32> cullingOffsets; Array<uint32> cullingOffsets;
for (auto &mat : materialData) for (auto &mat : materialData)
{
for (auto &instance : mat.instances)
{ {
instance.offsets.instanceOffset = instanceData.size(); for (auto &instance : mat.instances)
// instance.offsets.cullingCounterOffset = cullingOffsets.size(); {
// instance.numMeshlets = 0; instance.offsets.instanceOffset = instanceData.size();
for (size_t i = 0; i < instance.instanceData.size(); ++i) // instance.offsets.cullingCounterOffset = cullingOffsets.size();
{ // instance.numMeshlets = 0;
cullingOffsets.add(numMeshlets); for (size_t i = 0; i < instance.instanceData.size(); ++i)
instanceData.add(instance.instanceData[i]); {
instanceMeshData.add(instance.instanceMeshData[i]); cullingOffsets.add(instance.cullingOffsets[i]);
// instance.numMeshlets += instance.instanceMeshData[i].numMeshlets; instanceData.add(instance.instanceData[i]);
// cullingOffsets.add(numMeshlets); instanceMeshData.add(instance.instanceMeshData[i]);
numMeshlets += instance.instanceMeshData[i].numMeshlets; // instance.numMeshlets += instance.instanceMeshData[i].numMeshlets;
} // cullingOffsets.add(numMeshlets);
numMeshlets += instance.instanceMeshData[i].numMeshlets;
}
}
} }
} cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
Array<MeshletCullingInfo> cullingData(numMeshlets); cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(MeshletCullingInfo)); .sourceData = {
cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); .size = cullingOffsets.size() * sizeof(uint32),
cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ .data = (uint8 *)cullingOffsets.data(),
.sourceData = { },
.size = cullingOffsets.size() * sizeof(uint32), .numElements = cullingOffsets.size()});
.data = (uint8 *)cullingOffsets.data(), cullingOffsetBuffer->pipelineBarrier(
}, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
.numElements = cullingOffsets.size()}); Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
cullingOffsetBuffer->pipelineBarrier( Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
cullingBuffer->rotateBuffer(cullingData.size() * sizeof(MeshletCullingInfo)); instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData));
cullingBuffer->updateContents(ShaderBufferCreateInfo{ instanceBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
.size = cullingData.size() * sizeof(MeshletCullingInfo), .size = instanceData.size() * sizeof(InstanceData),
.data = (uint8 *)cullingData.data(), .data = (uint8 *)instanceData.data(),
}, },
.numElements = cullingData.size()}); .numElements = instanceData.size()});
cullingBuffer->pipelineBarrier( instanceBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData)); instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size());
instanceBuffer->updateContents(ShaderBufferCreateInfo{ instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
.size = instanceData.size() * sizeof(InstanceData), .size = sizeof(MeshData) * instanceMeshData.size(),
.data = (uint8 *)instanceData.data(), .data = (uint8 *)instanceMeshData.data(),
}, },
.numElements = instanceData.size()}); .numElements = instanceMeshData.size()});
instanceBuffer->pipelineBarrier( instanceMeshDataBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceDataLayout->reset();
instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size()); descriptorSet = instanceDataLayout->allocateDescriptorSet();
instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{ descriptorSet->updateBuffer(0, instanceBuffer);
.sourceData = { descriptorSet->updateBuffer(1, instanceMeshDataBuffer);
.size = sizeof(MeshData) * instanceMeshData.size(), descriptorSet->updateBuffer(2, meshletBuffer);
.data = (uint8 *)instanceMeshData.data(), descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
}, descriptorSet->updateBuffer(4, vertexIndicesBuffer);
.numElements = instanceMeshData.size()}); descriptorSet->updateBuffer(5, cullingOffsetBuffer);
instanceMeshDataBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceDataLayout->reset();
descriptorSet = instanceDataLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, instanceBuffer);
descriptorSet->updateBuffer(1, instanceMeshDataBuffer);
descriptorSet->updateBuffer(2, meshletBuffer);
descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
descriptorSet->updateBuffer(4, vertexIndicesBuffer);
descriptorSet->updateBuffer(5, cullingBuffer);
descriptorSet->updateBuffer(6, cullingOffsetBuffer);
descriptorSet->writeChanges();
} }
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
{ {
assert(loadedMeshlets.size() < 2048); assert(loadedMeshlets.size() < 2048);
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
meshlets.reserve(meshlets.size() + loadedMeshlets.size()); meshlets.reserve(meshlets.size() + loadedMeshlets.size());
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet); vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3); primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
uint32 meshletOffset = meshlets.size(); uint32 meshletOffset = meshlets.size();
AABB meshAABB; AABB meshAABB;
for (uint32 i = 0; i < loadedMeshlets.size(); ++i) for (uint32 i = 0; i < loadedMeshlets.size(); ++i)
{ {
Meshlet &m = loadedMeshlets[i]; Meshlet &m = loadedMeshlets[i];
meshAABB = meshAABB.combine(m.boundingBox); meshAABB = meshAABB.combine(m.boundingBox);
uint32 vertexOffset = vertexIndices.size(); uint32 vertexOffset = vertexIndices.size();
vertexIndices.resize(vertexOffset + m.numVertices); vertexIndices.resize(vertexOffset + m.numVertices);
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
uint32 primitiveOffset = primitiveIndices.size(); uint32 primitiveOffset = primitiveIndices.size();
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
meshlets.add(MeshletDescription{ meshlets.add(MeshletDescription{
.bounding = m.boundingBox, //.toSphere(), .bounding = m.boundingBox, //.toSphere(),
.vertexCount = m.numVertices, .vertexCount = m.numVertices,
.primitiveCount = m.numPrimitives, .primitiveCount = m.numPrimitives,
.vertexOffset = vertexOffset, .vertexOffset = vertexOffset,
.primitiveOffset = primitiveOffset, .primitiveOffset = primitiveOffset,
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX), .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
.indicesOffset = (uint32)meshOffsets[id], .indicesOffset = (uint32)meshOffsets[id],
}); });
} }
meshData[id] = MeshData{ meshData[id] = MeshData{
.bounding = meshAABB, //.toSphere(), .bounding = meshAABB, //.toSphere(),
.numMeshlets = (uint32)loadedMeshlets.size(), .numMeshlets = (uint32)loadedMeshlets.size(),
.meshletOffset = meshletOffset, .meshletOffset = meshletOffset,
.firstIndex = (uint32)indices.size(), .firstIndex = (uint32)indices.size(),
.numIndices = (uint32)loadedIndices.size(), .numIndices = (uint32)loadedIndices.size(),
}; };
if (!graphics->supportMeshShading()) if (!graphics->supportMeshShading())
{ {
indices.resize(indices.size() + loadedIndices.size()); indices.resize(indices.size() + loadedIndices.size());
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{ indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
.sourceData = {
.size = sizeof(uint32) * indices.size(),
.data = (uint8 *)indices.data(),
},
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
.name = "IndexBuffer",
});
}
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
.size = sizeof(uint32) * indices.size(), .size = sizeof(MeshletDescription) * meshlets.size(),
.data = (uint8 *)indices.data(), .data = (uint8 *)meshlets.data()},
.numElements = meshlets.size(),
.dynamic = false,
.name = "MeshletBuffer"});
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint32) * vertexIndices.size(),
.data = (uint8 *)vertexIndices.data(),
}, },
.indexType = Gfx::SE_INDEX_TYPE_UINT32, .numElements = vertexIndices.size(),
.name = "IndexBuffer", .dynamic = false,
.name = "VertexIndicesBuffer"});
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint8) * primitiveIndices.size(),
.data = (uint8 *)primitiveIndices.data(),
},
.numElements = primitiveIndices.size(),
.dynamic = false,
.name = "PrimitiveIndicesBuffer",
}); });
}
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(MeshletDescription) * meshlets.size(),
.data = (uint8 *)meshlets.data()},
.numElements = meshlets.size(),
.dynamic = false,
.name = "MeshletBuffer"});
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint32) * vertexIndices.size(),
.data = (uint8 *)vertexIndices.data(),
},
.numElements = vertexIndices.size(),
.dynamic = false,
.name = "VertexIndicesBuffer"});
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint8) * primitiveIndices.size(),
.data = (uint8 *)primitiveIndices.data(),
},
.numElements = primitiveIndices.size(),
.dynamic = false,
.name = "PrimitiveIndicesBuffer",
});
} }
MeshId VertexData::allocateVertexData(uint64 numVertices) MeshId VertexData::allocateVertexData(uint64 numVertices)
{ {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
MeshId res{idCounter++}; MeshId res{idCounter++};
meshOffsets[res] = head; meshOffsets[res] = head;
meshVertexCounts[res] = numVertices; meshVertexCounts[res] = numVertices;
head += numVertices; head += numVertices;
if (head > verticesAllocated) if (head > verticesAllocated)
{ {
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS); verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
resizeBuffers(); resizeBuffers();
} }
return res; return res;
} }
uint64 VertexData::getMeshOffset(MeshId id) uint64 VertexData::getMeshOffset(MeshId id)
{ {
return meshOffsets[id]; return meshOffsets[id];
} }
uint64 VertexData::getMeshVertexCount(MeshId id) uint64 VertexData::getMeshVertexCount(MeshId id)
{ {
return meshVertexCounts[id]; return meshVertexCounts[id];
} }
List<VertexData *> vertexDataList; List<VertexData *> vertexDataList;
List<VertexData *> VertexData::getList() List<VertexData *> VertexData::getList()
{ {
return vertexDataList; return vertexDataList;
} }
VertexData *VertexData::findByTypeName(std::string name) VertexData *VertexData::findByTypeName(std::string name)
{ {
for (auto vd : vertexDataList) for (auto vd : vertexDataList)
{
if (vd->getTypeName() == name)
{ {
return vd; if (vd->getTypeName() == name)
{
return vd;
}
} }
} return nullptr;
return nullptr;
} }
void VertexData::init(Gfx::PGraphics _graphics) void VertexData::init(Gfx::PGraphics _graphics)
{ {
graphics = _graphics; graphics = _graphics;
verticesAllocated = NUM_DEFAULT_ELEMENTS; verticesAllocated = NUM_DEFAULT_ELEMENTS;
instanceDataLayout = graphics->createDescriptorLayout("pScene"); instanceDataLayout = graphics->createDescriptorLayout("pScene");
// instanceData // instanceData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 0, .binding = 0,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
}); });
// meshData // meshData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.binding = 1, .binding = 1,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
}); });
// meshletData // meshletData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// primitiveIndices // primitiveIndices
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// vertexIndices // vertexIndices
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingList // cullingOffset
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingOffset // cullingInfos
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER}); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ instanceDataLayout->create();
.dynamic = true,
.name = "MeshletOffset", cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
}); .dynamic = true,
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .name = "MeshletOffset",
.dynamic = true, });
.name = "MeshletCulling", instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
}); .dynamic = true,
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .name = "InstanceBuffer",
.dynamic = true, });
.name = "InstanceBuffer", instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
}); .dynamic = true,
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .name = "MeshDataBuffer",
.dynamic = true, });
.name = "MeshDataBuffer", resizeBuffers();
}); graphics->getShaderCompiler()->registerVertexData(this);
instanceDataLayout->create();
resizeBuffers();
graphics->getShaderCompiler()->registerVertexData(this);
} }
void VertexData::destroy() void VertexData::destroy()
{ {
instanceBuffer = nullptr; instanceBuffer = nullptr;
instanceMeshDataBuffer = nullptr; instanceMeshDataBuffer = nullptr;
instanceDataLayout = nullptr; instanceDataLayout = nullptr;
meshletBuffer = nullptr; meshletBuffer = nullptr;
vertexIndicesBuffer = nullptr; vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr; primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr; indexBuffer = nullptr;
meshData.clear(); meshData.clear();
materialData.clear(); materialData.clear();
}
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets)
{
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
if (!instanceIdMap.contains(key))
{
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
meshletCount += numMeshlets;
}
return instanceIdMap[key];
} }
VertexData::VertexData() VertexData::VertexData()
+23 -1
View File
@@ -7,6 +7,7 @@
#include "Graphics/Descriptor.h" #include "Graphics/Descriptor.h"
#include "Graphics/Buffer.h" #include "Graphics/Buffer.h"
#include "Meshlet.h" #include "Meshlet.h"
#include <entt/entt.hpp>
constexpr uint64 MAX_TEXCOORDS = 8; constexpr uint64 MAX_TEXCOORDS = 8;
@@ -56,6 +57,7 @@ namespace Seele
DrawCallOffsets offsets; DrawCallOffsets offsets;
Array<InstanceData> instanceData; Array<InstanceData> instanceData;
Array<MeshData> instanceMeshData; Array<MeshData> instanceMeshData;
Array<uint32> cullingOffsets;
}; };
struct MaterialData struct MaterialData
{ {
@@ -63,7 +65,7 @@ namespace Seele
Array<BatchedDrawCall> instances; Array<BatchedDrawCall> instances;
}; };
void resetMeshData(); void resetMeshData();
void updateMesh(PMesh mesh, Component::Transform &transform); void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform &transform);
void createDescriptors(); void createDescriptors();
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets); void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
MeshId allocateVertexData(uint64 numVertices); MeshId allocateVertexData(uint64 numVertices);
@@ -87,6 +89,15 @@ namespace Seele
virtual void init(Gfx::PGraphics graphics); virtual void init(Gfx::PGraphics graphics);
virtual void destroy(); virtual void destroy();
struct CullingMapping
{
uint64 instanceId;
uint32 cullingOffset;
};
static CullingMapping getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets);
static uint64 getInstanceCount() { return instanceCount; }
static uint64 getMeshletCount() { return meshletCount; }
protected: protected:
virtual void resizeBuffers() = 0; virtual void resizeBuffers() = 0;
virtual void updateBuffers() = 0; virtual void updateBuffers() = 0;
@@ -111,6 +122,17 @@ namespace Seele
Array<uint8> primitiveIndices; Array<uint8> primitiveIndices;
Array<uint32> vertexIndices; Array<uint32> vertexIndices;
Array<uint32> indices; Array<uint32> indices;
struct MeshMapping
{
entt::entity id;
uint32 meshId;
auto operator<=>(const MeshMapping& other) const = default;
};
static Map<MeshMapping, CullingMapping> instanceIdMap;
static uint64 instanceCount;
static uint64 meshletCount;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
Gfx::ODescriptorLayout instanceDataLayout; Gfx::ODescriptorLayout instanceDataLayout;
// for mesh shading // for mesh shading
+5
View File
@@ -389,6 +389,11 @@ void *ShaderBuffer::mapRegion(uint64 offset, uint64 size, bool writeOnly) {
void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); } void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); }
void ShaderBuffer::clear()
{
vkCmdFillBuffer(graphics->getQueueCommands(owner)->getCommands()->getHandle(), Vulkan::Buffer::getHandle(), 0, VK_WHOLE_SIZE, 0);
}
void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) {
Gfx::QueueOwnedResource::transferOwnership(newOwner); Gfx::QueueOwnedResource::transferOwnership(newOwner);
} }
+2
View File
@@ -133,6 +133,8 @@ public:
virtual void *mapRegion(uint64 offset, uint64 size, bool writeOnly) override; virtual void *mapRegion(uint64 offset, uint64 size, bool writeOnly) override;
virtual void unmap() override; virtual void unmap() override;
virtual void clear() override;
protected: protected:
// Inherited via Vulkan::Buffer // Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override; virtual VkAccessFlags getSourceAccessMask() override;
+4 -2
View File
@@ -27,10 +27,11 @@ public:
void setupView(Dependencies<Deps...>) void setupView(Dependencies<Deps...>)
{ {
//List<std::function<void()>> work; //List<std::function<void()>> work;
registry.view<Components..., Deps...>().each([&](Components&... comp, Deps&... deps){ registry.view<Components..., Deps...>().each([&](entt::entity id, Components&... comp, Deps&... deps){
//work.add([&]() { //work.add([&]() {
(accessComponent(deps), ...); (accessComponent(deps), ...);
update(comp...); update(comp...);
update(id, comp...);
//}); //});
}); });
//getThreadPool().runAndWait(std::move(work)); //getThreadPool().runAndWait(std::move(work));
@@ -41,7 +42,8 @@ public:
setupView((getDependencies<Components>() | ...)); setupView((getDependencies<Components>() | ...));
} }
virtual void update() override {} virtual void update() override {}
virtual void update(Components&... components) = 0; virtual void update(Components&... components) {}
virtual void update(entt::entity id, Components&... components) {}
}; };
} // namespace System } // namespace System
} // namespace Seele } // namespace Seele
+3 -3
View File
@@ -14,10 +14,10 @@ MeshUpdater::~MeshUpdater()
{ {
} }
void MeshUpdater::update(Component::Transform& transform, Component::Mesh& comp) void MeshUpdater::update(entt::entity id, Component::Transform& transform, Component::Mesh& comp)
{ {
for (auto& mesh : comp.asset->meshes) for (uint32 i = 0; i < comp.asset->meshes.size(); ++i)
{ {
mesh->vertexData->updateMesh(mesh, transform); comp.asset->meshes[i]->vertexData->updateMesh(id, i, comp.asset->meshes[i], transform);
} }
} }
+1 -1
View File
@@ -12,7 +12,7 @@ class MeshUpdater : public ComponentSystem<Component::Transform, Component::Mesh
public: public:
MeshUpdater(PScene scene); MeshUpdater(PScene scene);
virtual ~MeshUpdater(); virtual ~MeshUpdater();
virtual void update(Component::Transform& transform, Component::Mesh& mesh) override; virtual void update(entt::entity id, Component::Transform& transform, Component::Mesh& mesh) override;
private: private:
}; };
} // namespace System } // namespace System
+2
View File
@@ -9,6 +9,7 @@
#include "System/CameraUpdater.h" #include "System/CameraUpdater.h"
#include "Graphics/RenderPass/CachedDepthPass.h" #include "Graphics/RenderPass/CachedDepthPass.h"
#include "Graphics/RenderPass/DepthPrepass.h" #include "Graphics/RenderPass/DepthPrepass.h"
#include "Graphics/RenderPass/VisibilityPass.h"
#include "Graphics/RenderPass/LightCullingPass.h" #include "Graphics/RenderPass/LightCullingPass.h"
#include "Graphics/RenderPass/BasePass.h" #include "Graphics/RenderPass/BasePass.h"
#include "Graphics/RenderPass/SkyboxRenderPass.h" #include "Graphics/RenderPass/SkyboxRenderPass.h"
@@ -28,6 +29,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
reloadGame(); reloadGame();
renderGraph.addPass(new CachedDepthPass(graphics, scene)); renderGraph.addPass(new CachedDepthPass(graphics, scene));
renderGraph.addPass(new DepthPrepass(graphics, scene)); renderGraph.addPass(new DepthPrepass(graphics, scene));
renderGraph.addPass(new VisibilityPass(graphics, scene));
renderGraph.addPass(new LightCullingPass(graphics, scene)); renderGraph.addPass(new LightCullingPass(graphics, scene));
renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene));
renderGraph.addPass(new DebugPass(graphics, scene)); renderGraph.addPass(new DebugPass(graphics, scene));