Lots of shader changes, basic primitive writing

This commit is contained in:
Dynamitos
2024-05-30 21:24:21 +02:00
parent f278afad66
commit 953c90f2de
18 changed files with 599 additions and 464 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
"**/external": true, "**/external": true,
"**/res": true, "**/res": true,
}, },
"editor.tabSize": 2, "editor.tabSize": 4,
"editor.detectIndentation": false, "editor.detectIndentation": false,
"lldb.displayFormat": "auto", "lldb.displayFormat": "auto",
"lldb.showDisassembly": "auto", "lldb.showDisassembly": "auto",
+2 -11
View File
@@ -12,14 +12,8 @@ struct LightCullingData
layout(set=5) layout(set=5)
ParameterBlock<LightCullingData> pLightCullingData; ParameterBlock<LightCullingData> pLightCullingData;
struct FragmentOutput
{
float4 color : SV_Target0;
uint meshletId : SV_Target1;
};
[shader("pixel")] [shader("pixel")]
FragmentOutput fragmentMain(in FragmentParameter params) float4 fragmentMain(in FragmentParameter params) : SV_Target
{ {
LightingParameter lightingParams = params.getLightingParameter(); LightingParameter lightingParams = params.getLightingParameter();
MaterialParameter materialParams = params.getMaterialParameter(); MaterialParameter materialParams = params.getMaterialParameter();
@@ -41,9 +35,6 @@ FragmentOutput fragmentMain(in FragmentParameter params)
// gamma correction // gamma correction
result = result / (result + float3(1.0)); result = result / (result + float3(1.0));
result = pow(result, float3(1.0/2.2)); result = pow(result, float3(1.0/2.2));
FragmentOutput output; return float4(result, 1.0f);
output.color = float4(result, 1.0f);
output.meshletId = params.meshletId;
return output;
} }
+27 -21
View File
@@ -7,25 +7,31 @@ groupshared uint head;
[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_GroupIndex,
uint groupID: SV_GroupID, uint groupID: SV_GroupID, )
){ {
InstanceData instance = pScene.instances[pOffsets.instanceOffset + groupID]; MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID]; if (threadID == 0)
//head = 0; {
//GroupMemoryBarrierWithGroupSync(); head = 0;
//for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) p.instanceId = pOffsets.instanceOffset + groupID;
//{ p.meshletOffset = mesh.meshletOffset;
// uint m = mesh.meshletOffset + i; p.cullingOffset = pScene.cullingOffsets[p.instanceId];
// MeshletDescription meshlet = pScene.meshletInfos[m]; }
// MeshletCullingInfo culling = pScene.culledMeshlets[instance.meshletCullingOffset]; GroupMemoryBarrierWithGroupSync();
// if(culling.anyVisible()) for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
// { {
// uint index; uint m = p.meshletOffset + i;
// InterlockedAdd(head, 1, index); uint cull = p.cullingOffset + i;
// p.culledMeshlets[index] = m; MeshletDescription meshlet = pScene.meshletInfos[m];
// } MeshletCullingInfo culling = pScene.culledMeshlets[cull];
//} if(false)
//GroupMemoryBarrierWithGroupSync(); {
//DispatchMesh(head, 1, 1, p); uint index;
InterlockedAdd(head, 1, index);
p.culledMeshlets[index] = i;
}
}
GroupMemoryBarrierWithGroupSync();
DispatchMesh(head, 1, 1, p);
} }
+11 -7
View File
@@ -3,6 +3,7 @@ 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")]
@@ -13,22 +14,25 @@ void taskMain(
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.cullingOffset = pScene.cullingOffsets[p.instanceId];
} }
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
MeshData mesh = pScene.meshData[p.instanceId];
for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
{ {
uint m = mesh.meshletOffset + i; uint m = p.meshletOffset + i;
//MeshletDescription meshlet = pScene.meshletInfos[m]; uint cull = p.cullingOffset + i;
//MeshletCullingInfo culling = pScene.culledMeshlets[pScene.cullingOffsets[p.instanceId] + i]; MeshletDescription meshlet = pScene.meshletInfos[m];
//if(culling.anyVisible()) MeshletCullingInfo culling = pScene.culledMeshlets[cull];
if(culling.anyVisible())
{ {
uint index; uint index;
InterlockedAdd(head, 1, index); InterlockedAdd(head, 1, index);
p.culledMeshlets[i] = m; p.culledMeshlets[index] = i;
} }
} }
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
DispatchMesh(mesh.numMeshlets, 1, 1, p); DispatchMesh(head, 1, 1, p);
} }
+15 -12
View File
@@ -5,21 +5,25 @@ import MaterialParameter;
struct PrimitiveAttributes struct PrimitiveAttributes
{ {
uint cull: SV_CullPrimitive; bool cull: SV_CullPrimitive;
}; };
[numthreads(MESH_GROUP_SIZE, 1, 1)] [numthreads(MESH_GROUP_SIZE, 1, 1)]
[outputtopology("triangle")] [outputtopology("triangle")]
[shader("mesh")] [shader("mesh")]
void meshMain( void meshMain(
in uint threadID: SV_GroupIndex, in uint threadID: SV_GroupIndex,
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],
out indices uint3 indices[MAX_PRIMITIVES] out indices uint3 indices[MAX_PRIMITIVES],
){ out primitives PrimitiveAttributes prim[MAX_PRIMITIVES]
InstanceData inst = pScene.instances[meshPayload.instanceId]; ) {
MeshletDescription m = pScene.meshletInfos[meshPayload.culledMeshlets[groupID]]; // meshlet number relative to start for this instance
uint meshletNumber = meshPayload.culledMeshlets[groupID];
InstanceData inst = pScene.instances[meshPayload.instanceId];
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber];
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)
@@ -29,7 +33,8 @@ void meshMain(
uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0]; uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0];
uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1]; uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1];
uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2]; uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2];
indices[p] = uint3(local_idx0, local_idx1, local_idx2); indices[p] = uint3(local_idx0, local_idx1, local_idx2);
prim[p].cull = cull.triangleCulled(p);
} }
} }
for(uint i = threadID; i < MAX_VERTICES; i += MESH_GROUP_SIZE) for(uint i = threadID; i < MAX_VERTICES; i += MESH_GROUP_SIZE)
@@ -42,8 +47,6 @@ void meshMain(
#else #else
VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex); VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex);
#endif #endif
attr.meshletId = -1;
vertices[v] = attr.getParameter(inst.transformMatrix); vertices[v] = attr.getParameter(inst.transformMatrix);
} }
} }
+55
View File
@@ -0,0 +1,55 @@
import Common;
import Scene;
import VertexData;
import MaterialParameter;
struct PrimitiveAttributes
{
uint32_t prim : SV_PrimitiveID;
bool cull: SV_CullPrimitive;
};
[numthreads(MESH_GROUP_SIZE, 1, 1)]
[outputtopology("triangle")]
[shader("mesh")]
void meshMain(
in uint threadID: SV_GroupIndex,
in uint groupID: SV_GroupID,
in payload MeshPayload meshPayload,
out vertices FragmentParameter vertices[MAX_VERTICES],
out indices uint3 indices[MAX_PRIMITIVES],
out primitives PrimitiveAttributes prim[MAX_PRIMITIVES]
) {
// meshlet number relative to start for this instance
uint meshletNumber = meshPayload.culledMeshlets[groupID];
InstanceData inst = pScene.instances[meshPayload.instanceId];
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
MeshletCullingInfo cull = pScene.culledMeshlets[meshPayload.cullingOffset + meshletNumber];
SetMeshOutputCounts(m.vertexCount, m.primitiveCount);
for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE)
{
uint p = min(i, m.primitiveCount - 1);
{
uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0];
uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1];
uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2];
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
prim[p].cull = cull.triangleCulled(p);
//prim[p].prim = encodePrimitive(p, meshletNumber, meshPayload.instanceId);
}
}
for(uint i = threadID; i < MAX_VERTICES; i += MESH_GROUP_SIZE)
{
uint v = min(i, m.vertexCount - 1);
{
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
#ifdef POS_ONLY
VertexAttributes attr = pVertexData.getPosition(m.indicesOffset + vertexIndex);
#else
VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex);
#endif
vertices[v] = attr.getParameter(inst.transformMatrix);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
import Scene;
import MaterialParameter;
[shader("pixel")]
uint fragmentMain(in uint32_t encoded : SV_PrimitiveID) : SV_Target
{
return encoded;
}
+9 -5
View File
@@ -26,7 +26,6 @@ struct FragmentParameter
float3 biTangent_WS : TANGENT1; float3 biTangent_WS : TANGENT1;
float3 position_WS : POSITION2; float3 position_WS : POSITION2;
float3 vertexColor : COLOR0; float3 vertexColor : COLOR0;
uint meshletId : POSITION3;
float2 texCoords[MAX_TEXCOORDS] : TEXCOORD0; float2 texCoords[MAX_TEXCOORDS] : TEXCOORD0;
MaterialParameter getMaterialParameter() MaterialParameter getMaterialParameter()
{ {
@@ -50,6 +49,13 @@ struct FragmentParameter
} }
}; };
// data passed to visibility render
struct VisibilityParameter
{
uint32_t triangleIndex : POSITION5;
uint32_t meshletId : POSITION6;
};
// data retrieved from VertexData // data retrieved from VertexData
struct VertexAttributes struct VertexAttributes
{ {
@@ -58,7 +64,6 @@ struct VertexAttributes
float3 tangent_MS; float3 tangent_MS;
float3 biTangent_MS; float3 biTangent_MS;
float3 vertexColor; float3 vertexColor;
uint meshletId;
float2 texCoords[MAX_TEXCOORDS]; float2 texCoords[MAX_TEXCOORDS];
FragmentParameter getParameter(float4x4 transformMatrix) FragmentParameter getParameter(float4x4 transformMatrix)
{ {
@@ -66,19 +71,18 @@ struct VertexAttributes
float4 worldPos = mul(transformMatrix, modelPos); float4 worldPos = mul(transformMatrix, modelPos);
float4 viewPos = mul(pViewParams.viewMatrix, worldPos); float4 viewPos = mul(pViewParams.viewMatrix, worldPos);
float4 clipPos = mul(pViewParams.projectionMatrix, viewPos); float4 clipPos = mul(pViewParams.projectionMatrix, viewPos);
FragmentParameter result;
result.position_CS = clipPos;
float3x3 normalMatrix = float3x3(transformMatrix); float3x3 normalMatrix = float3x3(transformMatrix);
float3 T = mul(normalMatrix, tangent_MS); float3 T = mul(normalMatrix, tangent_MS);
float3 N = mul(normalMatrix, normal_MS); float3 N = mul(normalMatrix, normal_MS);
float3 B = mul(normalMatrix, biTangent_MS); float3 B = mul(normalMatrix, biTangent_MS);
FragmentParameter result;
result.position_CS = clipPos;
result.cameraPos_WS = pViewParams.cameraPos_WS.xyz; result.cameraPos_WS = pViewParams.cameraPos_WS.xyz;
result.normal_WS = N; result.normal_WS = N;
result.tangent_WS = T; result.tangent_WS = T;
result.biTangent_WS = B; result.biTangent_WS = B;
result.position_WS = worldPos.xyz; result.position_WS = worldPos.xyz;
result.vertexColor = vertexColor; result.vertexColor = vertexColor;
result.meshletId = meshletId;
for(uint i = 0; i < MAX_TEXCOORDS; ++i) for(uint i = 0; i < MAX_TEXCOORDS; ++i)
{ {
result.texCoords[i] = texCoords[i]; result.texCoords[i] = texCoords[i];
+67 -40
View File
@@ -2,49 +2,54 @@ import Bounding;
struct MeshletDescription struct MeshletDescription
{ {
AABB bounding; AABB bounding;
uint32_t vertexCount; uint32_t vertexCount;
uint32_t primitiveCount; uint32_t primitiveCount;
uint32_t vertexOffset; uint32_t vertexOffset;
uint32_t primitiveOffset; uint32_t primitiveOffset;
float3 color; float3 color;
uint32_t indicesOffset; uint32_t indicesOffset;
}; };
struct MeshData struct MeshData
{ {
AABB bounding; AABB bounding;
uint32_t numMeshlets; uint32_t numMeshlets;
uint32_t meshletOffset; uint32_t meshletOffset;
uint32_t firstIndex; uint32_t firstIndex;
uint32_t numIndices; uint32_t numIndices;
}; };
static const uint MAX_VERTICES = 256; static const uint64_t MAX_VERTICES = 256;
static const uint MAX_PRIMITIVES = 256; static const uint64_t MAX_PRIMITIVES = 256;
static const uint TASK_GROUP_SIZE = 128; static const uint64_t TASK_GROUP_SIZE = 128;
static const uint MESH_GROUP_SIZE = 32; static const uint64_t MESH_GROUP_SIZE = 32;
static const uint64_t MAX_MESHLETS_PER_INSTANCE = 2048;
struct InstanceData struct InstanceData
{ {
float4x4 transformMatrix; float4x4 transformMatrix;
float4x4 inverseTransformMatrix; float4x4 inverseTransformMatrix;
}; };
struct MeshletCullingInfo struct MeshletCullingInfo
{ {
uint64_t cull[MAX_PRIMITIVES / 64]; uint64_t visible[MAX_PRIMITIVES / 64];
// 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 / 64;
uint32_t cullIdx = primIndex % 64; uint32_t cullIdx = primIndex % 64;
return (cull[arrIdx] & (1 << cullIdx)) != 0; return (visible[arrIdx] & (1 << cullIdx)) != 0;
} }
bool anyVisible() bool triangleCulled(uint32_t primIndex)
{ {
return (cull[0] | cull[1] | cull[2] | cull[3]) != 0; return !triangleVisible(primIndex);
} }
bool anyVisible()
{
return (visible[0] + visible[1] + visible[2] + visible[3]) != 0;
}
}; };
struct DrawCallOffsets struct DrawCallOffsets
@@ -56,20 +61,42 @@ ConstantBuffer<DrawCallOffsets> pOffsets;
struct Scene struct Scene
{ {
StructuredBuffer<InstanceData> instances; StructuredBuffer<InstanceData> instances;
StructuredBuffer<MeshData> meshData; StructuredBuffer<MeshData> meshData;
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<MeshletCullingInfo> culledMeshlets;
StructuredBuffer<uint32_t> cullingOffsets; StructuredBuffer<uint32_t> cullingOffsets;
}; };
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 encoded = instanceId;
encoded *= MAX_MESHLETS_PER_INSTANCE;
encoded += meshletId;
encoded *= MAX_PRIMITIVES;
encoded += primitiveId;
return encoded;
}
uint3 decodePrimitive(uint64_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);
}
struct MeshPayload struct MeshPayload
{ {
uint instanceId; uint instanceId;
uint culledMeshlets[2048]; uint meshletOffset;
uint cullingOffset;
uint culledMeshlets[MAX_MESHLETS_PER_INSTANCE];
}; };
@@ -22,14 +22,6 @@ struct StaticMeshVertexData : IVertexData
{ {
VertexAttributes attributes; VertexAttributes attributes;
attributes.position_MS = float3(positions[3 * index + 0], positions[3 * index + 1], positions[3 * index + 2]); attributes.position_MS = float3(positions[3 * index + 0], positions[3 * index + 1], positions[3 * index + 2]);
attributes.normal_MS = float3(0, 0, 0);
attributes.tangent_MS = float3(0, 0, 0);
attributes.biTangent_MS = float3(0, 0, 0);
for (uint i = 0; i < MAX_TEXCOORDS; ++i)
{
attributes.texCoords[i] = float2(0, 0);
}
attributes.vertexColor = float3(0, 0, 0);
return attributes; return attributes;
} }
StructuredBuffer<float> positions; StructuredBuffer<float> positions;
+180 -173
View File
@@ -9,21 +9,21 @@ extern bool useViewCulling;
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene) : RenderPass(graphics, scene)
{ {
depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout"); depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout");
depthPrepassLayout->addDescriptorLayout(viewParamsLayout); depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{ depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0, .offset = 0,
.size = sizeof(VertexData::DrawCallOffsets), .size = sizeof(VertexData::DrawCallOffsets),
}); });
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "MeshletPass", false, false, "", true, true, "DrawListTask"); graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "VisibilityMeshletPass", false, true, "VisibilityPass", true, true, "DrawListTask");
} }
else else
{ {
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "LegacyPass"); graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "LegacyPass");
} }
} }
CachedDepthPass::~CachedDepthPass() CachedDepthPass::~CachedDepthPass()
@@ -32,117 +32,130 @@ CachedDepthPass::~CachedDepthPass()
void CachedDepthPass::beginFrame(const Component::Camera &cam) void CachedDepthPass::beginFrame(const Component::Camera &cam)
{ {
RenderPass::beginFrame(cam); RenderPass::beginFrame(cam);
} }
void CachedDepthPass::render() void CachedDepthPass::render()
{ {
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands; Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation; Gfx::ShaderPermutation permutation;
permutation.setPositionOnly(usePositionOnly); permutation.setPositionOnly(usePositionOnly);
permutation.setViewCulling(useViewCulling); permutation.setViewCulling(useViewCulling);
if (graphics->supportMeshShading())
{
permutation.setTaskFile("DrawListTask");
permutation.setMeshFile("MeshletPass");
}
else
{
permutation.setVertexFile("LegacyPass");
}
for (VertexData *vertexData : VertexData::getList())
{
permutation.setVertexData(vertexData->getTypeName());
// Create Pipeline(VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per meshtype
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
command->setViewport(viewport);
const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
Gfx::MeshPipelineCreateInfo pipelineInfo = { permutation.setTaskFile("DrawListTask");
.taskShader = collection->taskShader, permutation.setMeshFile("VisibilityMeshletPass");
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
else else
{ {
Gfx::LegacyPipelineCreateInfo pipelineInfo = { permutation.setVertexFile("LegacyPass");
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
command->bindDescriptor(vertexData->getVertexDataSet()); permutation.setFragmentFile("VisibilityPass");
command->bindDescriptor(viewParamsSet); for (VertexData *vertexData : VertexData::getList())
command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
if (graphics->supportMeshShading())
{ {
command->drawMesh(vertexData->getNumInstances(), 1, 1); permutation.setVertexData(vertexData->getTypeName());
}
else // Create Pipeline(VertexData)
{ // Descriptors:
const auto &materials = vertexData->getMaterialData(); // ViewData => global, static
for (const auto &materialData : materials) // VertexData => per meshtype
{ // SceneData => per meshtype
// material not used for any active meshes, skip Gfx::PermutationId id(permutation);
if (materialData.instances.size() == 0)
continue; Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
for (const auto &drawCall : materialData.instances) command->setViewport(viewport);
const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading())
{ {
command->bindIndexBuffer(vertexData->getIndexBuffer()); Gfx::MeshPipelineCreateInfo pipelineInfo = {
uint32 inst = drawCall.offsets.instanceOffset; .taskShader = collection->taskShader,
for (const auto &meshData : drawCall.instanceMeshData) .meshShader = collection->meshShader,
{ .fragmentShader = collection->fragmentShader,
// all meshlets of a mesh share the same indices offset .renderPass = renderPass,
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); .pipelineLayout = collection->pipelineLayout,
} .multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
} else
{
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(viewParamsSet);
command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
if (graphics->supportMeshShading())
{
command->drawMesh(vertexData->getNumInstances(), 1, 1);
}
else
{
const auto &materials = vertexData->getMaterialData();
for (const auto &materialData : materials)
{
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
for (const auto &drawCall : materialData.instances)
{
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto &meshData : drawCall.instanceMeshData)
{
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++);
}
}
}
}
commands.add(std::move(command));
} }
commands.add(std::move(command));
}
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
// Sync depth read/write with depth pass depth read
depthBuffer->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
// sync visibility write with depth pass visibility write
visibilityBuffer->pipelineBarrier(
Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
} }
void CachedDepthPass::endFrame() void CachedDepthPass::endFrame()
@@ -151,72 +164,66 @@ void CachedDepthPass::endFrame()
void CachedDepthPass::publishOutputs() void CachedDepthPass::publishOutputs()
{ {
// If we render to a part of an image, the depth buffer itself must // If we render to a part of an image, the depth buffer itself must
// still match the size of the whole image or their coordinate systems go out of sync // still match the size of the whole image or their coordinate systems go out of sync
TextureCreateInfo depthBufferInfo = { TextureCreateInfo depthBufferInfo = {
.format = Gfx::SE_FORMAT_D32_SFLOAT, .format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = viewport->getOwner()->getFramebufferWidth(), .width = viewport->getOwner()->getFramebufferWidth(),
.height = viewport->getOwner()->getFramebufferHeight(), .height = viewport->getOwner()->getFramebufferHeight(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
}; };
depthBuffer = graphics->createTexture2D(depthBufferInfo); depthBuffer = graphics->createTexture2D(depthBufferInfo);
depthAttachment = depthAttachment =
Gfx::RenderTargetAttachment(depthBuffer, Gfx::RenderTargetAttachment(depthBuffer,
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment); resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment);
TextureCreateInfo visibilityInfo = { TextureCreateInfo visibilityInfo = {
.format = Gfx::SE_FORMAT_R32G32_UINT, .format = Gfx::SE_FORMAT_R32_UINT,
.width = viewport->getOwner()->getFramebufferWidth(), .width = viewport->getOwner()->getFramebufferWidth(),
.height = viewport->getOwner()->getFramebufferHeight(), .height = viewport->getOwner()->getFramebufferHeight(),
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
}; };
visibilityBuffer = graphics->createTexture2D(visibilityInfo); visibilityBuffer = graphics->createTexture2D(visibilityInfo);
visibilityAttachment = visibilityAttachment =
Gfx::RenderTargetAttachment(visibilityBuffer, Gfx::RenderTargetAttachment(visibilityBuffer,
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE); Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("VISIBILITY", visibilityAttachment); resources->registerRenderPassOutput("VISIBILITY", visibilityAttachment);
} }
void CachedDepthPass::createRenderPass() void CachedDepthPass::createRenderPass()
{ {
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.depthAttachment = depthAttachment, .colorAttachments = {visibilityAttachment},
}; .depthAttachment = depthAttachment,
Array<Gfx::SubPassDependency> dependency = { };
{ Array<Gfx::SubPassDependency> dependency = {
.srcSubpass = ~0U, // {
.dstSubpass = 0, // .srcSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .dstSubpass = ~0U,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
}, // .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
{ // },
.srcSubpass = 0, // {
.dstSubpass = ~0U, // .srcSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .dstSubpass = ~0U,
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, // .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
}, // .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
{ // },
.srcSubpass = 0, // {
.dstSubpass = ~0U, // .srcSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .dstSubpass = ~0U,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}, // .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ // }
.srcSubpass = 0, };
.dstSubpass = ~0U, renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport);
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}};
renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport);
} }
+186 -163
View File
@@ -9,21 +9,21 @@ extern bool useViewCulling;
DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene) DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene) : RenderPass(graphics, scene)
{ {
depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout"); depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout");
depthPrepassLayout->addDescriptorLayout(viewParamsLayout); depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{ depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, .stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0, .offset = 0,
.size = sizeof(VertexData::DrawCallOffsets), .size = sizeof(VertexData::DrawCallOffsets),
}); });
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "ViewCullingTask"); graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "VisibilityMeshletPass", false, true, "VisibilityPass", true, true, "DepthCullingTask");
} }
else else
{ {
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass");
} }
} }
DepthPrepass::~DepthPrepass() DepthPrepass::~DepthPrepass()
@@ -32,116 +32,138 @@ DepthPrepass::~DepthPrepass()
void DepthPrepass::beginFrame(const Component::Camera &cam) void DepthPrepass::beginFrame(const Component::Camera &cam)
{ {
RenderPass::beginFrame(cam); RenderPass::beginFrame(cam);
} }
void DepthPrepass::render() void DepthPrepass::render()
{ {
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands; Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation; Gfx::ShaderPermutation permutation;
permutation.setPositionOnly(usePositionOnly); permutation.setPositionOnly(usePositionOnly);
permutation.setViewCulling(useViewCulling); permutation.setViewCulling(useViewCulling);
if (graphics->supportMeshShading())
{
permutation.setTaskFile("ViewCullingTask");
permutation.setMeshFile("MeshletPass");
}
else
{
permutation.setVertexFile("LegacyPass");
}
for (VertexData *vertexData : VertexData::getList())
{
permutation.setVertexData(vertexData->getTypeName());
// Create Pipeline(VertexData)
// Descriptors:
// ViewData => global, static
// VertexData => per meshtype
// SceneData => per meshtype
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
command->setViewport(viewport);
const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
Gfx::MeshPipelineCreateInfo pipelineInfo = { permutation.setTaskFile("DepthCullingTask");
.taskShader = collection->taskShader, permutation.setMeshFile("VisibilityMeshletPass");
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
else else
{ {
Gfx::LegacyPipelineCreateInfo pipelineInfo = { permutation.setVertexFile("LegacyPass");
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
command->bindDescriptor(vertexData->getVertexDataSet()); permutation.setFragmentFile("VisibilityPass");
command->bindDescriptor(viewParamsSet); for (VertexData *vertexData : VertexData::getList())
command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
if (graphics->supportMeshShading())
{ {
command->drawMesh(vertexData->getNumInstances(), 1, 1); permutation.setVertexData(vertexData->getTypeName());
} // Create Pipeline(VertexData)
else // Descriptors:
{ // ViewData => global, static
const auto &materials = vertexData->getMaterialData(); // VertexData => per meshtype
for (const auto &materialData : materials) // SceneData => per meshtype
{ Gfx::PermutationId id(permutation);
for (const auto &drawCall : materialData.instances)
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
command->setViewport(viewport);
const Gfx::ShaderCollection *collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
if (graphics->supportMeshShading())
{ {
// material not used for any active meshes, skip Gfx::MeshPipelineCreateInfo pipelineInfo = {
if (materialData.instances.size() == 0) .taskShader = collection->taskShader,
continue; .meshShader = collection->meshShader,
command->bindIndexBuffer(vertexData->getIndexBuffer()); .fragmentShader = collection->fragmentShader,
uint32 inst = drawCall.offsets.instanceOffset; .renderPass = renderPass,
for (const auto &meshData : drawCall.instanceMeshData) .pipelineLayout = collection->pipelineLayout,
{ .multisampleState = {
// all meshlets of a mesh share the same indices offset .samples = viewport->getSamples(),
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); },
} .depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} }
} else
{
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.multisampleState = {
.samples = viewport->getSamples(),
},
.depthStencilState = {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = {
.attachmentCount = 1,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor(vertexData->getVertexDataSet());
command->bindDescriptor(viewParamsSet);
command->bindDescriptor(vertexData->getInstanceDataSet());
uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &offset);
if (graphics->supportMeshShading())
{
command->drawMesh(vertexData->getNumInstances(), 1, 1);
}
else
{
const auto &materials = vertexData->getMaterialData();
for (const auto &materialData : materials)
{
for (const auto &drawCall : materialData.instances)
{
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto &meshData : drawCall.instanceMeshData)
{
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++);
}
}
}
}
commands.add(std::move(command));
} }
commands.add(std::move(command));
}
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
// Sync depth read/write with compute read
depthAttachment.getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
);
// Sync depth read/write with base pass read
depthAttachment.getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
);
// Sync visibility write with compute read
visibilityAttachment.getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
);
} }
void DepthPrepass::endFrame() void DepthPrepass::endFrame()
@@ -154,59 +176,60 @@ void DepthPrepass::publishOutputs()
void DepthPrepass::createRenderPass() void DepthPrepass::createRenderPass()
{ {
auto 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);
auto 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_COLOR_ATTACHMENT_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{
.colorAttachments = {visibilityAttachment}, .colorAttachments = {visibilityAttachment},
.depthAttachment = depthAttachment, .depthAttachment = depthAttachment,
}; };
Array<Gfx::SubPassDependency> dependency = { Array<Gfx::SubPassDependency> dependency = {
{ // {
.srcSubpass = ~0U, // .srcSubpass = ~0U,
.dstSubpass = 0, // .dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
}, // },
{ // {
.srcSubpass = ~0U, // .srcSubpass = ~0U,
.dstSubpass = 0, // .dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}, // },
{ // {
.srcSubpass = 0, // .srcSubpass = 0,
.dstSubpass = ~0U, // .dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, // .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
}, // },
{ // {
.srcSubpass = 0, // .srcSubpass = 0,
.dstSubpass = ~0U, // .dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
}, // },
{ // {
.srcSubpass = 0, // .srcSubpass = 0,
.dstSubpass = ~0U, // .dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // .dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, // .dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
}}; // }
renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport); };
renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport);
} }
@@ -18,6 +18,7 @@ public:
virtual void createRenderPass() override; virtual void createRenderPass() override;
private: private:
Gfx::RenderTargetAttachment depthAttachment; Gfx::RenderTargetAttachment depthAttachment;
Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::OPipelineLayout depthPrepassLayout; Gfx::OPipelineLayout depthPrepassLayout;
}; };
DEFINE_REF(DepthPrepass) DEFINE_REF(DepthPrepass)
+5 -4
View File
@@ -130,7 +130,7 @@ void VertexData::createDescriptors()
} }
} }
Array<MeshletCullingInfo> cullingData(numMeshlets); Array<MeshletCullingInfo> cullingData(numMeshlets);
std::memset(cullingData.data(), 0xff, cullingData.size()); std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(MeshletCullingInfo));
cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
@@ -144,18 +144,19 @@ void VertexData::createDescriptors()
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);
cullingBuffer->rotateBuffer(numMeshlets * sizeof(MeshletCullingInfo)); cullingBuffer->rotateBuffer(cullingData.size() * sizeof(MeshletCullingInfo));
cullingBuffer->updateContents(ShaderBufferCreateInfo{ cullingBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
.size = numMeshlets * sizeof(MeshletCullingInfo), .size = cullingData.size() * sizeof(MeshletCullingInfo),
.data = (uint8 *)cullingData.data(), .data = (uint8 *)cullingData.data(),
}, },
.numElements = numMeshlets}); .numElements = cullingData.size()});
cullingBuffer->pipelineBarrier( cullingBuffer->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_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT); Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData)); instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData));
instanceBuffer->updateContents(ShaderBufferCreateInfo{ instanceBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
+1
View File
@@ -47,6 +47,7 @@ void Queue::submitCommandBuffer(PCommand command, const Array<VkSemaphore>& sign
}; };
VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle())); VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle()));
command->fence->submit();
command->state = Command::State::Submit; command->state = Command::State::Submit;
command->waitFlags.clear(); command->waitFlags.clear();
command->waitSemaphores.clear(); command->waitSemaphores.clear();
+22 -17
View File
@@ -20,38 +20,40 @@ Semaphore::Semaphore(PGraphics graphics)
Semaphore::~Semaphore() Semaphore::~Semaphore()
{ {
//graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); // graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle);
} }
Fence::Fence(PGraphics graphics) Fence::Fence(PGraphics graphics)
: graphics(graphics) : graphics(graphics), status(Status::Ready)
, signaled(false)
{ {
VkFenceCreateInfo info = { VkFenceCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0 .flags = 0};
};
VK_CHECK(vkCreateFence(graphics->getDevice(), &info, nullptr, &fence)); VK_CHECK(vkCreateFence(graphics->getDevice(), &info, nullptr, &fence));
} }
Fence::~Fence() Fence::~Fence()
{ {
vkWaitForFences(graphics->getDevice(), 1, &fence, true, 100000); vkWaitForFences(graphics->getDevice(), 1, &fence, true, 10000000);
vkDestroyFence(graphics->getDevice(), fence, nullptr); vkDestroyFence(graphics->getDevice(), fence, nullptr);
} }
void Fence::submit()
{
status = Status::InUse;
}
bool Fence::isSignaled() bool Fence::isSignaled()
{ {
if (signaled) if (status == Status::Signalled)
{ {
return true; return true;
} }
VkResult r = vkGetFenceStatus(graphics->getDevice(), fence); VkResult r = vkGetFenceStatus(graphics->getDevice(), fence);
if (r == VK_SUCCESS) if (r == VK_SUCCESS)
{ {
signaled = true; status = Status::Signalled;
return true; return true;
} }
if (r == VK_NOT_READY) if (r == VK_NOT_READY)
@@ -67,11 +69,14 @@ bool Fence::isSignaled()
void Fence::reset() void Fence::reset()
{ {
if (signaled) while (status == Status::InUse)
{
wait(1000000);
}
if (status == Status::Signalled)
{ {
VK_CHECK(vkResetFences(graphics->getDevice(), 1, &fence)); VK_CHECK(vkResetFences(graphics->getDevice(), 1, &fence));
//std::cout << vkGetFenceStatus(graphics->getDevice(), fence) << std::endl; status = Status::Ready;
signaled = false;
} }
} }
@@ -81,7 +86,7 @@ void Fence::wait(uint64 timeout)
VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout); VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout);
if (r == VK_SUCCESS) if (r == VK_SUCCESS)
{ {
signaled = true; status = Status::Signalled;
} }
else if (r == VK_TIMEOUT) else if (r == VK_TIMEOUT)
{ {
@@ -111,7 +116,7 @@ void DestructionManager::notifyCommandComplete()
{ {
for (size_t i = 0; i < resources.size(); ++i) for (size_t i = 0; i < resources.size(); ++i)
{ {
if(!resources[i]->isCurrentlyBound()) if (!resources[i]->isCurrentlyBound())
{ {
resources.removeAt(i, false); resources.removeAt(i, false);
i--; i--;
@@ -131,9 +136,9 @@ SamplerHandle::~SamplerHandle()
} }
Sampler::Sampler(PGraphics graphics, VkSamplerCreateInfo createInfo) Sampler::Sampler(PGraphics graphics, VkSamplerCreateInfo createInfo)
: graphics(graphics) : graphics(graphics), handle(new SamplerHandle(graphics, createInfo))
, handle(new SamplerHandle(graphics, createInfo)) {
{} }
Sampler::~Sampler() Sampler::~Sampler()
{ {
+8 -1
View File
@@ -32,6 +32,7 @@ class Fence
public: public:
Fence(PGraphics graphics); Fence(PGraphics graphics);
~Fence(); ~Fence();
void submit();
bool isSignaled(); bool isSignaled();
void reset(); void reset();
constexpr VkFence getHandle() const constexpr VkFence getHandle() const
@@ -46,7 +47,13 @@ public:
private: private:
PGraphics graphics; PGraphics graphics;
bool signaled; enum class Status
{
Ready,
InUse,
Signalled,
};
Status status;
VkFence fence; VkFence fence;
}; };
DEFINE_REF(Fence) DEFINE_REF(Fence)
+1 -1
View File
@@ -114,9 +114,9 @@ void Window::pollInput()
void Window::beginFrame() void Window::beginFrame()
{ {
imageAvailableFences[currentSemaphoreIndex]->wait(10000000000);
imageAvailableFences[currentSemaphoreIndex]->reset(); imageAvailableFences[currentSemaphoreIndex]->reset();
vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), &currentImageIndex); vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), &currentImageIndex);
imageAvailableFences[currentSemaphoreIndex]->submit();
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]); graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]);
} }