Adding simple visibility pass

This commit is contained in:
Dynamitos
2024-06-04 21:34:14 +02:00
parent 157368a241
commit ad00e16cf9
10 changed files with 160 additions and 25 deletions
+1 -1
-1
View File
@@ -5,7 +5,6 @@ import LightEnv;
struct ComputeShaderInput
{
uint3 groupID : SV_GroupID;
uint3 groupThreadID : SV_GroupThreadID;
uint3 dispatchThreadID : SV_DispatchThreadID;
uint groupIndex : SV_GroupIndex;
};
+4 -4
View File
@@ -22,12 +22,12 @@ void meshMain(
out indices uint3 indices[MAX_PRIMITIVES],
out primitives PrimitiveAttributes prim[MAX_PRIMITIVES]
) {
uint instanceId = meshPayload.instanceId;
// meshlet number relative to start for this instance
uint meshletNumber = meshPayload.culledMeshlets[groupID];
InstanceData inst = pScene.instances[instanceId];
uint meshletId = meshPayload.cullingOffset + meshletNumber;
InstanceData inst = pScene.instances[meshPayload.instanceId];
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber];
MeshletCullingInfo cull = pScene.culledMeshlets[meshletId];
SetMeshOutputCounts(m.vertexCount, m.primitiveCount);
for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE)
@@ -40,7 +40,7 @@ void meshMain(
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
prim[p].cull = cull.triangleCulled(p);
#ifdef VISIBILITY
prim[p].prim = encodePrimitive(p, meshletNumber, instanceId);
prim[p].prim = encodePrimitive(p, meshletId);
#endif
}
}
+42
View File
@@ -0,0 +1,42 @@
import Common;
import Scene;
struct VisibilityCullingData
{
Texture2D<uint> visibilityTexture;
RWStructuredBuffer<MeshletCullingInfo> cullingInfos;
};
ParameterBlock<VisibilityCullingData> pVisibilityParams;
groupshared MeshletCullingInfo cullInfo;
[numthreads(BLOCK_SIZE, 1, 1)]
[shader("compute")]
void computeMain(
uint threadID: SV_GroupIndex,
uint groupID: SV_GroupID,
){
if (threadID < MAX_PRIMITIVES / 32)
{
cullInfo.visible[threadID] = 0;
}
GroupMemoryBarrierWithGroupSync();
for (uint y = 0; y < pViewParams.screenDimensions.y; y++)
{
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];
}
}
+13 -15
View File
@@ -20,11 +20,11 @@ struct MeshData
uint32_t numIndices;
};
static const uint64_t MAX_VERTICES = 256;
static const uint64_t MAX_PRIMITIVES = 256;
static const uint64_t TASK_GROUP_SIZE = 128;
static const uint64_t MESH_GROUP_SIZE = 32;
static const uint64_t MAX_MESHLETS_PER_INSTANCE = 2048;
static const uint32_t MAX_VERTICES = 256;
static const uint32_t MAX_PRIMITIVES = 256;
static const uint32_t TASK_GROUP_SIZE = 128;
static const uint32_t MESH_GROUP_SIZE = 32;
static const uint32_t MAX_MESHLETS_PER_INSTANCE = 2048;
struct InstanceData
{
@@ -34,12 +34,12 @@ struct InstanceData
struct MeshletCullingInfo
{
uint64_t visible[MAX_PRIMITIVES / 64];
uint32_t visible[MAX_PRIMITIVES / 32];
// lookup if a specific triangle is visible
bool triangleVisible(uint32_t primIndex)
{
uint32_t arrIdx = primIndex / 64;
uint32_t cullIdx = primIndex % 64;
uint32_t arrIdx = primIndex / 32;
uint32_t cullIdx = primIndex % 32;
return (visible[arrIdx] & (1 << cullIdx)) != 0;
}
bool triangleCulled(uint32_t primIndex)
@@ -72,19 +72,17 @@ struct Scene
layout(set = 2)
ParameterBlock<Scene> pScene;
uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId, uint32_t instanceId)
uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId)
{
return primitiveId + (meshletId * uint(MAX_PRIMITIVES)) + (instanceId * uint(MAX_MESHLETS_PER_INSTANCE * MAX_PRIMITIVES));
return primitiveId + (meshletId * uint(MAX_PRIMITIVES));
}
uint3 decodePrimitive(uint64_t encoded)
uint2 decodePrimitive(uint32_t encoded)
{
uint prim = uint(encoded % MAX_PRIMITIVES);
encoded = encoded / MAX_PRIMITIVES;
uint meshletId = uint(encoded % MAX_MESHLETS_PER_INSTANCE);
encoded = encoded / MAX_MESHLETS_PER_INSTANCE;
uint instanceId = uint(encoded);
return uint3(prim, meshletId, instanceId);
uint meshletId = uint(encoded);
return uint2(prim, meshletId);
}
struct MeshPayload
@@ -20,7 +20,9 @@ target_sources(Engine
TextPass.h
TextPass.cpp
UIPass.h
UIPass.cpp)
UIPass.cpp
VisibilityPass.h
VisibilityPass.cpp)
target_sources(Engine
PUBLIC FILE_SET HEADERS
@@ -35,4 +37,5 @@ target_sources(Engine
RenderPass.h
SkyboxRenderPass.h
TextPass.h
UIPass.h)
UIPass.h
VisibilityPass.h)
@@ -40,7 +40,9 @@ void LightCullingPass::beginFrame(const Component::Camera& cam)
.owner = Gfx::QueueType::COMPUTE
}
};
oLightIndexCounter->rotateBuffer(sizeof(uint32));
oLightIndexCounter->updateContents(counterReset);
tLightIndexCounter->rotateBuffer(sizeof(uint32));
tLightIndexCounter->updateContents(counterReset);
oLightIndexCounter->pipelineBarrier(
Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
@@ -0,0 +1,63 @@
#include "VisibilityPass.h"
using namespace Seele;
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene)
{
}
VisibilityPass::~VisibilityPass()
{
}
void VisibilityPass::beginFrame(const Component::Camera& cam)
{
RenderPass::beginFrame(cam);
visibilityDescriptor->reset();
visibilitySet = visibilityDescriptor->allocateDescriptorSet();
visibilitySet->updateTexture(0, visibilityAttachment->getTexture());
visibliitySet->updateBuffer(StaticMeshVertexData::getInstance()->get)
}
void VisibilityPass::render()
{
}
void VisibilityPass::endFrame()
{
}
void VisibilityPass::publishOutputs()
{
visibilityDescriptor = graphcis->createDescriptorLayout("pVisibilityParams");
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->create();
visibilityLayout = graphics->createPipelineLayout("VisibilityLayout");
visibilityLayout->addDescriptorLayout(viewParamsLayout);
visibilityLayout->addDescriptorLayout(visibilityDescriptor);
ShaderCreateInfo createInfo = {
.name = "Visibility",
.mainModule = "VisibilityCompute",
.entryPoint = "computeMain",
.rootSignature = visibilityLayout,
};
visibilityShader = graphics->createComputeShader(createInfo);
visibilityLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = visibilityShader;
pipelineInfo.pipelineLayout = std::move(visibilityLayout);
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
void VisibilityPass::createRenderPass()
{
visibilityAttachment = resources->requestRenderTarget("VISIBILITY");
}
@@ -0,0 +1,30 @@
#pragma once
#include "RenderPass.h"
namespace Seele
{
class VisibilityPass : public RenderPass
{
public:
VisibilityPass(Gfx::PGraphics graphics, PScene scene);
VisibilityPass(VisibilityPass&&) = default;
VisibilityPass& operator=(VisibilityPass&&) = default;
virtual ~VisibilityPass();
virtual void beginFrame(const Component::Camera& cam) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
uint64 allocate
private:
Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::PDescriptorSet visibilitySet;
Gfx::ODescriptorLayout visibilityDescriptor;
Gfx::OPipelineLayout visibilityLayout;
Gfx::PComputePipeline visibilityPipeline;
// Holds culling information for every meshlet for each instance
Gfx::OShaderBuffer cullingBuffer;
};
DEFINE_REF(VisibilityPass)
}
-2
View File
@@ -117,8 +117,6 @@ namespace Seele
Gfx::OShaderBuffer meshletBuffer;
Gfx::OShaderBuffer vertexIndicesBuffer;
Gfx::OShaderBuffer primitiveIndicesBuffer;
// Holds culling information for every meshlet for each instance
Gfx::OShaderBuffer cullingBuffer;
Gfx::OShaderBuffer cullingOffsetBuffer;
// for legacy pipeline
Gfx::OIndexBuffer indexBuffer;