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;
} }
+25 -19
View File
@@ -8,24 +8,30 @@ groupshared uint head;
[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];
//head = 0; if (threadID == 0)
//GroupMemoryBarrierWithGroupSync(); {
//for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) head = 0;
//{ p.instanceId = pOffsets.instanceOffset + groupID;
// uint m = mesh.meshletOffset + i; p.meshletOffset = mesh.meshletOffset;
// MeshletDescription meshlet = pScene.meshletInfos[m]; p.cullingOffset = pScene.cullingOffsets[p.instanceId];
// MeshletCullingInfo culling = pScene.culledMeshlets[instance.meshletCullingOffset]; }
// if(culling.anyVisible()) GroupMemoryBarrierWithGroupSync();
// { for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
// uint index; {
// InterlockedAdd(head, 1, index); uint m = p.meshletOffset + i;
// p.culledMeshlets[index] = m; uint cull = p.cullingOffset + i;
// } MeshletDescription meshlet = pScene.meshletInfos[m];
//} MeshletCullingInfo culling = pScene.culledMeshlets[cull];
//GroupMemoryBarrierWithGroupSync(); if(false)
//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);
} }
+9 -6
View File
@@ -5,7 +5,7 @@ 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)]
@@ -16,10 +16,14 @@ void meshMain(
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]
) {
// meshlet number relative to start for this instance
uint meshletNumber = meshPayload.culledMeshlets[groupID];
InstanceData inst = pScene.instances[meshPayload.instanceId]; InstanceData inst = pScene.instances[meshPayload.instanceId];
MeshletDescription m = pScene.meshletInfos[meshPayload.culledMeshlets[groupID]]; 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)
@@ -30,6 +34,7 @@ void meshMain(
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];
+36 -9
View File
@@ -20,10 +20,11 @@ struct MeshData
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
{ {
@@ -33,17 +34,21 @@ struct InstanceData
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 triangleCulled(uint32_t primIndex)
{
return !triangleVisible(primIndex);
} }
bool anyVisible() bool anyVisible()
{ {
return (cull[0] | cull[1] | cull[2] | cull[3]) != 0; return (visible[0] + visible[1] + visible[2] + visible[3]) != 0;
} }
}; };
@@ -64,12 +69,34 @@ struct Scene
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;
@@ -18,7 +18,7 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene)
}); });
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
{ {
@@ -46,12 +46,13 @@ void CachedDepthPass::render()
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
permutation.setTaskFile("DrawListTask"); permutation.setTaskFile("DrawListTask");
permutation.setMeshFile("MeshletPass"); permutation.setMeshFile("VisibilityMeshletPass");
} }
else else
{ {
permutation.setVertexFile("LegacyPass"); permutation.setVertexFile("LegacyPass");
} }
permutation.setFragmentFile("VisibilityPass");
for (VertexData *vertexData : VertexData::getList()) for (VertexData *vertexData : VertexData::getList())
{ {
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
@@ -143,6 +144,18 @@ void CachedDepthPass::render()
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()
@@ -167,7 +180,7 @@ void CachedDepthPass::publishOutputs()
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,
@@ -183,40 +196,34 @@ void CachedDepthPass::publishOutputs()
void CachedDepthPass::createRenderPass() void CachedDepthPass::createRenderPass()
{ {
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {visibilityAttachment},
.depthAttachment = depthAttachment, .depthAttachment = depthAttachment,
}; };
Array<Gfx::SubPassDependency> dependency = { Array<Gfx::SubPassDependency> dependency = {
{ // {
.srcSubpass = ~0U, // .srcSubpass = 0,
.dstSubpass = 0, // .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_COMPUTE_SHADER_BIT,
.srcAccess = 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 | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_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_COMPUTE_SHADER_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_SHADER_READ_BIT, // .dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
}, // },
{ // {
.srcSubpass = 0, // .srcSubpass = 0,
.dstSubpass = ~0U, // .dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // .dstStage = 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, // .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, // .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}, // }
{ };
.srcSubpass = 0,
.dstSubpass = ~0U,
.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); renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport);
} }
+68 -45
View File
@@ -18,7 +18,7 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene)
}); });
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
{ {
@@ -45,13 +45,14 @@ void DepthPrepass::render()
permutation.setViewCulling(useViewCulling); permutation.setViewCulling(useViewCulling);
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
permutation.setTaskFile("ViewCullingTask"); permutation.setTaskFile("DepthCullingTask");
permutation.setMeshFile("MeshletPass"); permutation.setMeshFile("VisibilityMeshletPass");
} }
else else
{ {
permutation.setVertexFile("LegacyPass"); permutation.setVertexFile("LegacyPass");
} }
permutation.setFragmentFile("VisibilityPass");
for (VertexData *vertexData : VertexData::getList()) for (VertexData *vertexData : VertexData::getList())
{ {
permutation.setVertexData(vertexData->getTypeName()); permutation.setVertexData(vertexData->getTypeName());
@@ -142,6 +143,27 @@ void DepthPrepass::render()
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,11 +176,11 @@ 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);
@@ -168,45 +190,46 @@ void DepthPrepass::createRenderPass()
.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]);
} }