Adding simple visibility pass
This commit is contained in:
Vendored
+1
-1
Submodule external/slang updated: febbeb140b...4b8ceed9d6
@@ -5,7 +5,6 @@ import LightEnv;
|
|||||||
struct ComputeShaderInput
|
struct ComputeShaderInput
|
||||||
{
|
{
|
||||||
uint3 groupID : SV_GroupID;
|
uint3 groupID : SV_GroupID;
|
||||||
uint3 groupThreadID : SV_GroupThreadID;
|
|
||||||
uint3 dispatchThreadID : SV_DispatchThreadID;
|
uint3 dispatchThreadID : SV_DispatchThreadID;
|
||||||
uint groupIndex : SV_GroupIndex;
|
uint groupIndex : SV_GroupIndex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ void meshMain(
|
|||||||
out indices uint3 indices[MAX_PRIMITIVES],
|
out indices uint3 indices[MAX_PRIMITIVES],
|
||||||
out primitives PrimitiveAttributes prim[MAX_PRIMITIVES]
|
out primitives PrimitiveAttributes prim[MAX_PRIMITIVES]
|
||||||
) {
|
) {
|
||||||
uint instanceId = meshPayload.instanceId;
|
|
||||||
// meshlet number relative to start for this instance
|
// meshlet number relative to start for this instance
|
||||||
uint meshletNumber = meshPayload.culledMeshlets[groupID];
|
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];
|
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
|
||||||
MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber];
|
MeshletCullingInfo cull = pScene.culledMeshlets[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)
|
||||||
@@ -40,7 +40,7 @@ void meshMain(
|
|||||||
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
|
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
|
||||||
prim[p].cull = cull.triangleCulled(p);
|
prim[p].cull = cull.triangleCulled(p);
|
||||||
#ifdef VISIBILITY
|
#ifdef VISIBILITY
|
||||||
prim[p].prim = encodePrimitive(p, meshletNumber, instanceId);
|
prim[p].prim = encodePrimitive(p, meshletId);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -20,11 +20,11 @@ struct MeshData
|
|||||||
uint32_t numIndices;
|
uint32_t numIndices;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint64_t MAX_VERTICES = 256;
|
static const uint32_t MAX_VERTICES = 256;
|
||||||
static const uint64_t MAX_PRIMITIVES = 256;
|
static const uint32_t MAX_PRIMITIVES = 256;
|
||||||
static const uint64_t TASK_GROUP_SIZE = 128;
|
static const uint32_t TASK_GROUP_SIZE = 128;
|
||||||
static const uint64_t MESH_GROUP_SIZE = 32;
|
static const uint32_t MESH_GROUP_SIZE = 32;
|
||||||
static const uint64_t MAX_MESHLETS_PER_INSTANCE = 2048;
|
static const uint32_t MAX_MESHLETS_PER_INSTANCE = 2048;
|
||||||
|
|
||||||
struct InstanceData
|
struct InstanceData
|
||||||
{
|
{
|
||||||
@@ -34,12 +34,12 @@ struct InstanceData
|
|||||||
|
|
||||||
struct MeshletCullingInfo
|
struct MeshletCullingInfo
|
||||||
{
|
{
|
||||||
uint64_t visible[MAX_PRIMITIVES / 64];
|
uint32_t visible[MAX_PRIMITIVES / 32];
|
||||||
// lookup if a specific triangle is visible
|
// lookup if a specific triangle is visible
|
||||||
bool triangleVisible(uint32_t primIndex)
|
bool triangleVisible(uint32_t primIndex)
|
||||||
{
|
{
|
||||||
uint32_t arrIdx = primIndex / 64;
|
uint32_t arrIdx = primIndex / 32;
|
||||||
uint32_t cullIdx = primIndex % 64;
|
uint32_t cullIdx = primIndex % 32;
|
||||||
return (visible[arrIdx] & (1 << cullIdx)) != 0;
|
return (visible[arrIdx] & (1 << cullIdx)) != 0;
|
||||||
}
|
}
|
||||||
bool triangleCulled(uint32_t primIndex)
|
bool triangleCulled(uint32_t primIndex)
|
||||||
@@ -72,19 +72,17 @@ struct Scene
|
|||||||
layout(set = 2)
|
layout(set = 2)
|
||||||
ParameterBlock<Scene> pScene;
|
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);
|
uint prim = uint(encoded % MAX_PRIMITIVES);
|
||||||
encoded = encoded / MAX_PRIMITIVES;
|
encoded = encoded / MAX_PRIMITIVES;
|
||||||
uint meshletId = uint(encoded % MAX_MESHLETS_PER_INSTANCE);
|
uint meshletId = uint(encoded);
|
||||||
encoded = encoded / MAX_MESHLETS_PER_INSTANCE;
|
return uint2(prim, meshletId);
|
||||||
uint instanceId = uint(encoded);
|
|
||||||
return uint3(prim, meshletId, instanceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MeshPayload
|
struct MeshPayload
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ target_sources(Engine
|
|||||||
TextPass.h
|
TextPass.h
|
||||||
TextPass.cpp
|
TextPass.cpp
|
||||||
UIPass.h
|
UIPass.h
|
||||||
UIPass.cpp)
|
UIPass.cpp
|
||||||
|
VisibilityPass.h
|
||||||
|
VisibilityPass.cpp)
|
||||||
|
|
||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
@@ -35,4 +37,5 @@ target_sources(Engine
|
|||||||
RenderPass.h
|
RenderPass.h
|
||||||
SkyboxRenderPass.h
|
SkyboxRenderPass.h
|
||||||
TextPass.h
|
TextPass.h
|
||||||
UIPass.h)
|
UIPass.h
|
||||||
|
VisibilityPass.h)
|
||||||
@@ -40,7 +40,9 @@ void LightCullingPass::beginFrame(const Component::Camera& cam)
|
|||||||
.owner = Gfx::QueueType::COMPUTE
|
.owner = Gfx::QueueType::COMPUTE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
oLightIndexCounter->rotateBuffer(sizeof(uint32));
|
||||||
oLightIndexCounter->updateContents(counterReset);
|
oLightIndexCounter->updateContents(counterReset);
|
||||||
|
tLightIndexCounter->rotateBuffer(sizeof(uint32));
|
||||||
tLightIndexCounter->updateContents(counterReset);
|
tLightIndexCounter->updateContents(counterReset);
|
||||||
oLightIndexCounter->pipelineBarrier(
|
oLightIndexCounter->pipelineBarrier(
|
||||||
Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
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)
|
||||||
|
}
|
||||||
@@ -117,8 +117,6 @@ namespace Seele
|
|||||||
Gfx::OShaderBuffer meshletBuffer;
|
Gfx::OShaderBuffer meshletBuffer;
|
||||||
Gfx::OShaderBuffer vertexIndicesBuffer;
|
Gfx::OShaderBuffer vertexIndicesBuffer;
|
||||||
Gfx::OShaderBuffer primitiveIndicesBuffer;
|
Gfx::OShaderBuffer primitiveIndicesBuffer;
|
||||||
// Holds culling information for every meshlet for each instance
|
|
||||||
Gfx::OShaderBuffer cullingBuffer;
|
|
||||||
Gfx::OShaderBuffer cullingOffsetBuffer;
|
Gfx::OShaderBuffer cullingOffsetBuffer;
|
||||||
// for legacy pipeline
|
// for legacy pipeline
|
||||||
Gfx::OIndexBuffer indexBuffer;
|
Gfx::OIndexBuffer indexBuffer;
|
||||||
|
|||||||
Reference in New Issue
Block a user