Adding cached depth renderpass

This commit is contained in:
Dynamitos
2024-05-30 16:56:22 +02:00
parent 4b6022237b
commit f278afad66
20 changed files with 908 additions and 677 deletions
+13 -1
View File
@@ -6,12 +6,24 @@
"configurations": [ "configurations": [
{ {
"name": "Editor", "name": "Editor",
"type": "lldb", "type": "cppvsdbg",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/build/Editor.exe", "program": "${workspaceRoot}/build/Editor.exe",
"args": [], "args": [],
"cwd": "${workspaceRoot}/build", "cwd": "${workspaceRoot}/build",
"console": "internalConsole", "console": "internalConsole",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}, },
{ {
"name": "Editor (Mac)", "name": "Editor (Mac)",
+5
View File
@@ -22,6 +22,11 @@
"short": "RelWithDebInfo", "short": "RelWithDebInfo",
"long": "Release with debug symbols", "long": "Release with debug symbols",
"buildType": "RelWithDebInfo" "buildType": "RelWithDebInfo"
},
"minsizerel": {
"short": "MinSizeRel",
"long": "Minimal size Release",
"buildType": "MinSizeRel"
} }
} }
}, },
+18 -36
View File
@@ -3,47 +3,29 @@ import Scene;
groupshared MeshPayload p; groupshared MeshPayload p;
groupshared uint head; groupshared uint head;
groupshared Frustum viewFrustum;
[numthreads(TASK_GROUP_SIZE, 1, 1)] [numthreads(TASK_GROUP_SIZE, 1, 1)]
[outputtopology("triangle")]
[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]; 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)
float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz; //{
const float offset = 0.0f; // uint m = mesh.meshletOffset + i;
float3 corners[4] = { // MeshletDescription meshlet = pScene.meshletInfos[m];
screenToModel(instance.inverseTransformMatrix, float4(offset, offset, -1.0f, 1.0f)).xyz, // MeshletCullingInfo culling = pScene.culledMeshlets[instance.meshletCullingOffset];
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions.x - offset, offset, -1.0f, 1.0f)).xyz, // if(culling.anyVisible())
screenToModel(instance.inverseTransformMatrix, float4(offset, pViewParams.screenDimensions.y - offset, -1.0f, 1.0f)).xyz, // {
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions - float2(offset, offset), -1.0f, 1.0f)).xyz // uint index;
}; // InterlockedAdd(head, 1, index);
viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]); // p.culledMeshlets[index] = m;
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]); // }
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]); //}
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]); //GroupMemoryBarrierWithGroupSync();
p.instanceId = pOffsets.instanceOffset + groupID; //DispatchMesh(head, 1, 1, p);
p.cullingOffset = pScene.cullingOffsets[pOffsets.cullingCounterOffset + groupID]; }
}
GroupMemoryBarrierWithGroupSync();
for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
{
uint m = mesh.meshletOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m];
if(meshlet.bounding.insideFrustum(viewFrustum))
{
uint index;
InterlockedAdd(head, 1, index);
pScene.culledMeshlets[p.cullingOffset + index] = m;
}
}
GroupMemoryBarrierWithGroupSync();
DispatchMesh(head, 1, 1, p);
}
+34
View File
@@ -0,0 +1,34 @@
import Common;
import Scene;
groupshared MeshPayload p;
groupshared uint head;
[numthreads(TASK_GROUP_SIZE, 1, 1)]
[shader("amplification")]
void taskMain(
uint threadID: SV_GroupIndex,
uint groupID: SV_GroupID, )
{
if (threadID == 0)
{
head = 0;
p.instanceId = pOffsets.instanceOffset + groupID;
}
GroupMemoryBarrierWithGroupSync();
MeshData mesh = pScene.meshData[p.instanceId];
for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
{
uint m = mesh.meshletOffset + i;
//MeshletDescription meshlet = pScene.meshletInfos[m];
//MeshletCullingInfo culling = pScene.culledMeshlets[pScene.cullingOffsets[p.instanceId] + i];
//if(culling.anyVisible())
{
uint index;
InterlockedAdd(head, 1, index);
p.culledMeshlets[i] = m;
}
}
GroupMemoryBarrierWithGroupSync();
DispatchMesh(mesh.numMeshlets, 1, 1, p);
}
-51
View File
@@ -1,51 +0,0 @@
import Common;
import BRDF;
import Scene;
import VertexData;
import MaterialParameter;
struct PrimitiveAttributes
{
uint cull: SV_CullPrimitive;
};
struct CulledMeshletList
{
StructuredBuffer<uint> meshletIndices;
};
ParameterBlock<CulledMeshletList> pCullingList;
[numthreads(MESH_GROUP_SIZE, 1, 1)]
[outputtopology("triangle")]
[shader("mesh")]
void meshMain(
in uint threadID: SV_GroupIndex,
in uint groupID: SV_GroupID,
out vertices FragmentParameter vertices[MAX_VERTICES],
out indices uint3 indices[MAX_PRIMITIVES]
){
uint meshletIndex = pCullingList.meshletIndices[groupID];
MeshletDescription m = pScene.meshletInfos[meshletIndex];
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);
}
}
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];
VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex);
attr.meshletId = meshletIndex;
vertices[v] = attr.getParameter(float4x4(1.0));
}
}
}
-2
View File
@@ -29,7 +29,6 @@ void taskMain(
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]); viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]); viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
p.instanceId = pOffsets.instanceOffset + groupID; p.instanceId = pOffsets.instanceOffset + groupID;
//p.cullingOffset = pScene.cullingOffsets[pOffsets.cullingCounterOffset + groupID];
} }
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE) for(uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
@@ -43,7 +42,6 @@ void taskMain(
uint index; uint index;
InterlockedAdd(head, 1, index); InterlockedAdd(head, 1, index);
p.culledMeshlets[index] = m; p.culledMeshlets[index] = m;
//pScene.culledMeshlets[p.cullingOffset + index] = m;
} }
} }
GroupMemoryBarrierWithGroupSync(); GroupMemoryBarrierWithGroupSync();
+19 -3
View File
@@ -31,9 +31,25 @@ struct InstanceData
float4x4 inverseTransformMatrix; float4x4 inverseTransformMatrix;
}; };
struct MeshletCullingInfo
{
uint64_t cull[MAX_PRIMITIVES / 64];
// lookup if a specific triangle is visible
bool triangleVisible(uint32_t primIndex)
{
uint32_t arrIdx = primIndex / 64;
uint32_t cullIdx = primIndex % 64;
return (cull[arrIdx] & (1 << cullIdx)) != 0;
}
bool anyVisible()
{
return (cull[0] | cull[1] | cull[2] | cull[3]) != 0;
}
};
struct DrawCallOffsets struct DrawCallOffsets
{ {
uint32_t instanceOffset; uint32_t instanceOffset;
}; };
layout(push_constant) layout(push_constant)
ConstantBuffer<DrawCallOffsets> pOffsets; ConstantBuffer<DrawCallOffsets> pOffsets;
@@ -45,8 +61,8 @@ struct Scene
StructuredBuffer<MeshletDescription> meshletInfos; StructuredBuffer<MeshletDescription> meshletInfos;
StructuredBuffer<uint8_t> primitiveIndices; StructuredBuffer<uint8_t> primitiveIndices;
StructuredBuffer<uint32_t> vertexIndices; StructuredBuffer<uint32_t> vertexIndices;
// StructuredBuffer<uint32_t> cullingOffsets; StructuredBuffer<MeshletCullingInfo> culledMeshlets;
// RWStructuredBuffer<uint32_t> culledMeshlets; StructuredBuffer<uint32_t> cullingOffsets;
}; };
layout(set=2) layout(set=2)
ParameterBlock<Scene> pScene; ParameterBlock<Scene> pScene;
+8 -20
View File
@@ -42,7 +42,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene)
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "ViewCullingTask"); graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "DrawListTask");
} }
else else
{ {
@@ -91,7 +91,7 @@ void BasePass::render()
Gfx::ShaderPermutation permutation; Gfx::ShaderPermutation permutation;
if (graphics->supportMeshShading()) if (graphics->supportMeshShading())
{ {
permutation.setTaskFile("ViewCullingTask"); permutation.setTaskFile("DrawListTask");
permutation.setMeshFile("MeshletPass"); permutation.setMeshFile("MeshletPass");
} }
else else
@@ -140,7 +140,7 @@ void BasePass::render()
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL, .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
}, },
.colorBlend = { .colorBlend = {
.attachmentCount = 2, .attachmentCount = 1,
}, },
}; };
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
@@ -160,7 +160,7 @@ void BasePass::render()
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL, .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
}, },
.colorBlend = { .colorBlend = {
.attachmentCount = 2, .attachmentCount = 1,
}, },
}; };
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo)); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
@@ -182,11 +182,10 @@ void BasePass::render()
else else
{ {
command->bindIndexBuffer(vertexData->getIndexBuffer()); command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) for (const auto& meshData : drawCall.instanceMeshData)
{ {
// all meshlets of a mesh share the same indices offset // all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), inst++); command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset), 0);
} }
} }
} }
@@ -208,17 +207,6 @@ void BasePass::publishOutputs()
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("BASEPASS_COLOR", colorAttachment); resources->registerRenderPassOutput("BASEPASS_COLOR", colorAttachment);
meshletIdTexture = graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_R32_UINT,
.width = viewport->getWidth(),
.height = viewport->getHeight(),
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_STORAGE_BIT,
});
meshletIdAttachment = Gfx::RenderTargetAttachment(meshletIdTexture,
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("BASEPASS_MESHLETID", meshletIdAttachment);
} }
void BasePass::createRenderPass() void BasePass::createRenderPass()
@@ -228,7 +216,7 @@ void BasePass::createRenderPass()
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = { colorAttachment, meshletIdAttachment }, .colorAttachments = { colorAttachment },
.depthAttachment = depthAttachment, .depthAttachment = depthAttachment,
}; };
Array<Gfx::SubPassDependency> dependency = { Array<Gfx::SubPassDependency> dependency = {
@@ -245,7 +233,7 @@ void BasePass::createRenderPass()
.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_NONE, .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}, },
{ {
@@ -262,7 +250,7 @@ void BasePass::createRenderPass()
.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_NONE, .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);
+1 -2
View File
@@ -20,12 +20,11 @@ public:
private: private:
Gfx::RenderTargetAttachment colorAttachment; Gfx::RenderTargetAttachment colorAttachment;
Gfx::RenderTargetAttachment depthAttachment; Gfx::RenderTargetAttachment depthAttachment;
Gfx::RenderTargetAttachment meshletIdAttachment; Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::PShaderBuffer oLightIndexList; Gfx::PShaderBuffer oLightIndexList;
Gfx::PShaderBuffer tLightIndexList; Gfx::PShaderBuffer tLightIndexList;
Gfx::PTexture2D oLightGrid; Gfx::PTexture2D oLightGrid;
Gfx::PTexture2D tLightGrid; Gfx::PTexture2D tLightGrid;
Gfx::OTexture2D meshletIdTexture;
Gfx::PDescriptorSet opaqueCulling; Gfx::PDescriptorSet opaqueCulling;
Gfx::PDescriptorSet transparentCulling; Gfx::PDescriptorSet transparentCulling;
@@ -2,6 +2,8 @@ target_sources(Engine
PRIVATE PRIVATE
BasePass.h BasePass.h
BasePass.cpp BasePass.cpp
CachedDepthPass.h
CachedDepthPass.cpp
DebugPass.h DebugPass.h
DebugPass.cpp DebugPass.cpp
DepthPrepass.h DepthPrepass.h
@@ -15,10 +17,6 @@ target_sources(Engine
RenderPass.cpp RenderPass.cpp
SkyboxRenderPass.h SkyboxRenderPass.h
SkyboxRenderPass.cpp SkyboxRenderPass.cpp
#StaticDepthPrepass.h
#StaticDepthPrepass.cpp
#StaticBasePass.h
#StaticBasePass.cpp
TextPass.h TextPass.h
TextPass.cpp TextPass.cpp
UIPass.h UIPass.h
@@ -28,6 +26,7 @@ target_sources(Engine
PUBLIC FILE_SET HEADERS PUBLIC FILE_SET HEADERS
FILES FILES
BasePass.h BasePass.h
CachedDepthPass.h
DebugPass.h DebugPass.h
DepthPrepass.h DepthPrepass.h
LightCullingPass.h LightCullingPass.h
@@ -35,7 +34,5 @@ target_sources(Engine
RenderGraphResources.h RenderGraphResources.h
RenderPass.h RenderPass.h
SkyboxRenderPass.h SkyboxRenderPass.h
#StaticDepthPrepass.h
#StaticBasePass.h
TextPass.h TextPass.h
UIPass.h) UIPass.h)
@@ -0,0 +1,222 @@
#include "CachedDepthPass.h"
#include "Graphics/Shader.h"
using namespace Seele;
extern bool usePositionOnly;
extern bool useViewCulling;
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene)
{
depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout");
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VertexData::DrawCallOffsets),
});
if (graphics->supportMeshShading())
{
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "MeshletPass", false, false, "", true, true, "DrawListTask");
}
else
{
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "CachedDepthPass", "LegacyPass");
}
}
CachedDepthPass::~CachedDepthPass()
{
}
void CachedDepthPass::beginFrame(const Component::Camera &cam)
{
RenderPass::beginFrame(cam);
}
void CachedDepthPass::render()
{
graphics->beginRenderPass(renderPass);
Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation;
permutation.setPositionOnly(usePositionOnly);
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())
{
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.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
{
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));
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
}
void CachedDepthPass::endFrame()
{
}
void CachedDepthPass::publishOutputs()
{
// 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
TextureCreateInfo depthBufferInfo = {
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = viewport->getOwner()->getFramebufferWidth(),
.height = viewport->getOwner()->getFramebufferHeight(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
};
depthBuffer = graphics->createTexture2D(depthBufferInfo);
depthAttachment =
Gfx::RenderTargetAttachment(depthBuffer,
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);
resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment);
TextureCreateInfo visibilityInfo = {
.format = Gfx::SE_FORMAT_R32G32_UINT,
.width = viewport->getOwner()->getFramebufferWidth(),
.height = viewport->getOwner()->getFramebufferHeight(),
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
};
visibilityBuffer = graphics->createTexture2D(visibilityInfo);
visibilityAttachment =
Gfx::RenderTargetAttachment(visibilityBuffer,
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("VISIBILITY", visibilityAttachment);
}
void CachedDepthPass::createRenderPass()
{
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.depthAttachment = depthAttachment,
};
Array<Gfx::SubPassDependency> dependency = {
{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_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,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_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,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_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,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_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);
}
@@ -0,0 +1,26 @@
#pragma once
#include "RenderPass.h"
namespace Seele
{
class CachedDepthPass : public RenderPass
{
public:
CachedDepthPass(Gfx::PGraphics graphics, PScene scene);
CachedDepthPass(CachedDepthPass&&) = default;
CachedDepthPass& operator=(CachedDepthPass&&) = default;
virtual ~CachedDepthPass();
virtual void beginFrame(const Component::Camera& cam) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
Gfx::RenderTargetAttachment depthAttachment;
Gfx::RenderTargetAttachment visibilityAttachment;
Gfx::OTexture2D depthBuffer;
Gfx::OTexture2D visibilityBuffer;
Gfx::OPipelineLayout depthPrepassLayout;
};
DEFINE_REF(CachedDepthPass)
}
+167 -164
View File
@@ -1,15 +1,5 @@
#include "DepthPrepass.h" #include "DepthPrepass.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Shader.h" #include "Graphics/Shader.h"
#include "Window/Window.h"
#include "Component/Camera.h"
#include "Component/Mesh.h"
#include "Actor/CameraActor.h"
#include "Math/Vector.h"
#include "RenderGraph.h"
#include "Graphics/Command.h"
#include "Graphics/StaticMeshVertexData.h"
using namespace Seele; using namespace Seele;
@@ -19,137 +9,139 @@ 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", "MeshletPass", false, false, "", true, true, "ViewCullingTask");
} }
else else
{ {
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass"); graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass");
} }
} }
DepthPrepass::~DepthPrepass() 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())
{ {
permutation.setTaskFile("ViewCullingTask"); Gfx::MeshPipelineCreateInfo pipelineInfo = {
permutation.setMeshFile("MeshletPass"); .taskShader = collection->taskShader,
.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
{ {
permutation.setVertexFile("LegacyPass"); 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);
} }
for (VertexData* vertexData : VertexData::getList()) 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())
{ {
permutation.setVertexData(vertexData->getTypeName()); command->drawMesh(vertexData->getNumInstances(), 1, 1);
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials)
{
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
// 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())
{
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.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
{
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());
for (const auto& drawCall : materialData.instances)
{
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
if (graphics->supportMeshShading())
{
command->drawMesh(drawCall.instanceMeshData.size(), 1, 1);
}
else
{
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));
}
} }
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));
}
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
graphics->endRenderPass(); graphics->endRenderPass();
} }
void DepthPrepass::endFrame() void DepthPrepass::endFrame()
@@ -158,52 +150,63 @@ void DepthPrepass::endFrame()
void DepthPrepass::publishOutputs() void DepthPrepass::publishOutputs()
{ {
// 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
TextureCreateInfo depthBufferInfo = {
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = viewport->getOwner()->getFramebufferWidth(),
.height = viewport->getOwner()->getFramebufferHeight(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
};
depthBuffer = graphics->createTexture2D(depthBufferInfo);
depthAttachment =
Gfx::RenderTargetAttachment(depthBuffer,
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment);
} }
void DepthPrepass::createRenderPass() void DepthPrepass::createRenderPass()
{ {
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ auto depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
.depthAttachment = depthAttachment, depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}; depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
Array<Gfx::SubPassDependency> dependency = { depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
{ auto visibilityAttachment = resources->requestRenderTarget("VISIBILITY");
.srcSubpass = ~0U, visibilityAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
.dstSubpass = 0, visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, visibilityAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .colorAttachments = {visibilityAttachment},
}, .depthAttachment = depthAttachment,
{ };
.srcSubpass = 0, Array<Gfx::SubPassDependency> dependency = {
.dstSubpass = ~0U, {
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, .srcSubpass = ~0U,
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, .dstSubpass = 0,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT, .dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_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,
.srcSubpass = 0, },
.dstSubpass = ~0U, {
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, .srcSubpass = ~0U,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, .dstSubpass = 0,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_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); },
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_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,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_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,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
}};
renderPass = graphics->createRenderPass(std::move(layout), std::move(dependency), viewport);
} }
@@ -18,9 +18,6 @@ public:
virtual void createRenderPass() override; virtual void createRenderPass() override;
private: private:
Gfx::RenderTargetAttachment depthAttachment; Gfx::RenderTargetAttachment depthAttachment;
Gfx::OTexture2D depthBuffer;
Gfx::OPipelineLayout depthPrepassLayout; Gfx::OPipelineLayout depthPrepassLayout;
}; };
DEFINE_REF(DepthPrepass) DEFINE_REF(DepthPrepass)
+306 -309
View File
@@ -15,372 +15,369 @@ constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024;
void VertexData::resetMeshData() void VertexData::resetMeshData()
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
for (auto& mat : materialData) for (auto &mat : materialData)
{
for (auto &inst : mat.instances)
{ {
for (auto& inst : mat.instances) inst.instanceData.clear();
{ inst.instanceMeshData.clear();
inst.instanceData.clear();
inst.instanceMeshData.clear();
}
if (mat.material != nullptr)
{
mat.material->getDescriptorLayout()->reset();
}
} }
if (dirty) if (mat.material != nullptr)
{ {
updateBuffers(); mat.material->getDescriptorLayout()->reset();
dirty = false;
} }
}
if (dirty)
{
updateBuffers();
dirty = false;
}
} }
void VertexData::updateMesh(PMesh mesh, Component::Transform& transform) void VertexData::updateMesh(PMesh mesh, Component::Transform &transform)
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle(); PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
PMaterial mat = referencedInstance->getBaseMaterial(); PMaterial mat = referencedInstance->getBaseMaterial();
if (materialData.size() <= mat->getId()) if (materialData.size() <= mat->getId())
{ {
materialData.resize(mat->getId() + 1); materialData.resize(mat->getId() + 1);
} }
MaterialData& matData = materialData[mat->getId()]; MaterialData &matData = materialData[mat->getId()];
matData.material = mat; matData.material = mat;
if (matData.instances.size() <= referencedInstance->getId()) if (matData.instances.size() <= referencedInstance->getId())
{ {
matData.instances.resize(referencedInstance->getId() + 1); matData.instances.resize(referencedInstance->getId() + 1);
} }
BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()]; BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()];
matInstanceData.materialInstance = referencedInstance; matInstanceData.materialInstance = referencedInstance;
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
matInstanceData.instanceData.add(InstanceData{
.transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix),
});
const auto& data = meshData[mesh->id];
matInstanceData.instanceMeshData.add(data);
referencedInstance->updateDescriptor();
for (size_t i = 0; i < 0; ++i)
{
auto bounding = meshlets[data.meshletOffset + i].bounding;
StaticArray<Vector, 8> corners;
Vector min = bounding.min;//bounding.center - bounding.radius * Vector(1, 1, 1);
Vector max = bounding.max;//bounding.center + bounding.radius * Vector(1, 1, 1);
corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1);
corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1);
corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1);
corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1);
corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1);
corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1);
corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1);
corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1);
addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[0], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[1], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[2], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[3], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[4], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[6], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[5], .color = meshlets[data.meshletOffset + i].color });
addDebugVertex(DebugVertex{ .position = corners[7], .color = meshlets[data.meshletOffset + i].color });
}
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
matInstanceData.instanceData.add(InstanceData{
.transformMatrix = transformMatrix,
.inverseTransformMatrix = glm::inverse(transformMatrix),
});
const auto &data = meshData[mesh->id];
matInstanceData.instanceMeshData.add(data);
referencedInstance->updateDescriptor();
for (size_t i = 0; i < 0; ++i)
{
auto bounding = meshlets[data.meshletOffset + i].bounding;
StaticArray<Vector, 8> corners;
Vector min = bounding.min; // bounding.center - bounding.radius * Vector(1, 1, 1);
Vector max = bounding.max; // bounding.center + bounding.radius * Vector(1, 1, 1);
corners[0] = transformMatrix * Vector4(min.x, min.y, min.z, 1);
corners[1] = transformMatrix * Vector4(min.x, min.y, max.z, 1);
corners[2] = transformMatrix * Vector4(min.x, max.y, min.z, 1);
corners[3] = transformMatrix * Vector4(min.x, max.y, max.z, 1);
corners[4] = transformMatrix * Vector4(max.x, min.y, min.z, 1);
corners[5] = transformMatrix * Vector4(max.x, min.y, max.z, 1);
corners[6] = transformMatrix * Vector4(max.x, max.y, min.z, 1);
corners[7] = transformMatrix * Vector4(max.x, max.y, max.z, 1);
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[0], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[1], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[2], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[3], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[4], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[6], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[5], .color = meshlets[data.meshletOffset + i].color});
addDebugVertex(DebugVertex{.position = corners[7], .color = meshlets[data.meshletOffset + i].color});
}
} }
void VertexData::createDescriptors() void VertexData::createDescriptors()
{ {
std::unique_lock l(materialDataLock); std::unique_lock l(materialDataLock);
instanceData.clear(); instanceData.clear();
instanceMeshData.clear(); instanceMeshData.clear();
//uint32 numMeshlets = 0; uint32 numMeshlets = 0;
//Array<uint32> cullingOffsets; Array<uint32> cullingOffsets;
for (auto& mat : materialData) for (auto &mat : materialData)
{
for (auto &instance : mat.instances)
{ {
for (auto& instance : mat.instances) instance.offsets.instanceOffset = instanceData.size();
{ // instance.offsets.cullingCounterOffset = cullingOffsets.size();
instance.offsets.instanceOffset = instanceData.size(); // instance.numMeshlets = 0;
//instance.offsets.cullingCounterOffset = cullingOffsets.size(); for (size_t i = 0; i < instance.instanceData.size(); ++i)
//instance.numMeshlets = 0; {
for (size_t i = 0; i < instance.instanceData.size(); ++i) cullingOffsets.add(numMeshlets);
{ instanceData.add(instance.instanceData[i]);
instanceData.add(instance.instanceData[i]); instanceMeshData.add(instance.instanceMeshData[i]);
instanceMeshData.add(instance.instanceMeshData[i]); // instance.numMeshlets += instance.instanceMeshData[i].numMeshlets;
//instance.numMeshlets += instance.instanceMeshData[i].numMeshlets; // cullingOffsets.add(numMeshlets);
//cullingOffsets.add(numMeshlets); numMeshlets += instance.instanceMeshData[i].numMeshlets;
//numMeshlets += instance.numMeshlets; }
}
}
} }
//cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); }
//cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ Array<MeshletCullingInfo> cullingData(numMeshlets);
// .sourceData = { std::memset(cullingData.data(), 0xff, cullingData.size());
// .size = cullingOffsets.size() * sizeof(uint32), cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
// .data = (uint8*)cullingOffsets.data(), cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
// }, .sourceData = {
// .numElements = cullingOffsets.size() .size = cullingOffsets.size() * sizeof(uint32),
// }); .data = (uint8 *)cullingOffsets.data(),
//cullingOffsetBuffer->pipelineBarrier( },
// Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, .numElements = cullingOffsets.size()});
// Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, cullingOffsetBuffer->pipelineBarrier(
// Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
// Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
//); Gfx::SE_ACCESS_MEMORY_READ_BIT,
//cullingBuffer->rotateBuffer(numMeshlets * sizeof(uint32)); Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
//cullingBuffer->updateContents(ShaderBufferCreateInfo{
// .sourceData = {
// .size = numMeshlets * sizeof(uint32),
// },
// .numElements = numMeshlets
// });
//cullingBuffer->pipelineBarrier(
// Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
// Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
// Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
// Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT
//);
instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData));
instanceBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = instanceData.size() * sizeof(InstanceData),
.data = (uint8*)instanceData.data(),
},
.numElements = instanceData.size()
});
instanceBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT
);
instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size()); cullingBuffer->rotateBuffer(numMeshlets * sizeof(MeshletCullingInfo));
instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{ cullingBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = { .sourceData = {
.size = sizeof(MeshData) * instanceMeshData.size(), .size = numMeshlets * sizeof(MeshletCullingInfo),
.data = (uint8*)instanceMeshData.data(), .data = (uint8 *)cullingData.data(),
}, },
.numElements = instanceMeshData.size() .numElements = numMeshlets});
}); cullingBuffer->pipelineBarrier(
instanceMeshDataBuffer->pipelineBarrier( Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData));
); instanceBuffer->updateContents(ShaderBufferCreateInfo{
instanceDataLayout->reset(); .sourceData = {
descriptorSet = instanceDataLayout->allocateDescriptorSet(); .size = instanceData.size() * sizeof(InstanceData),
descriptorSet->updateBuffer(0, instanceBuffer); .data = (uint8 *)instanceData.data(),
descriptorSet->updateBuffer(1, instanceMeshDataBuffer); },
descriptorSet->updateBuffer(2, meshletBuffer); .numElements = instanceData.size()});
descriptorSet->updateBuffer(3, primitiveIndicesBuffer); instanceBuffer->pipelineBarrier(
descriptorSet->updateBuffer(4, vertexIndicesBuffer); Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
//descriptorSet->updateBuffer(5, cullingOffsetBuffer); Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
//descriptorSet->updateBuffer(6, cullingBuffer); Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
descriptorSet->writeChanges(); instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size());
instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(MeshData) * instanceMeshData.size(),
.data = (uint8 *)instanceMeshData.data(),
},
.numElements = instanceMeshData.size()});
instanceMeshDataBuffer->pipelineBarrier(
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
instanceDataLayout->reset();
descriptorSet = instanceDataLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, instanceBuffer);
descriptorSet->updateBuffer(1, instanceMeshDataBuffer);
descriptorSet->updateBuffer(2, meshletBuffer);
descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
descriptorSet->updateBuffer(4, vertexIndicesBuffer);
descriptorSet->updateBuffer(5, cullingBuffer);
descriptorSet->updateBuffer(6, cullingOffsetBuffer);
descriptorSet->writeChanges();
} }
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
{ {
assert(loadedMeshlets.size() < 2048); assert(loadedMeshlets.size() < 2048);
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
meshlets.reserve(meshlets.size() + loadedMeshlets.size()); meshlets.reserve(meshlets.size() + loadedMeshlets.size());
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet); vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3); primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
uint32 meshletOffset = meshlets.size(); uint32 meshletOffset = meshlets.size();
AABB meshAABB; AABB meshAABB;
for (uint32 i = 0; i < loadedMeshlets.size(); ++i) for (uint32 i = 0; i < loadedMeshlets.size(); ++i)
{ {
Meshlet& m = loadedMeshlets[i]; Meshlet &m = loadedMeshlets[i];
meshAABB = meshAABB.combine(m.boundingBox); meshAABB = meshAABB.combine(m.boundingBox);
uint32 vertexOffset = vertexIndices.size(); uint32 vertexOffset = vertexIndices.size();
vertexIndices.resize(vertexOffset + m.numVertices); vertexIndices.resize(vertexOffset + m.numVertices);
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32)); std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
uint32 primitiveOffset = primitiveIndices.size(); uint32 primitiveOffset = primitiveIndices.size();
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3)); primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8)); std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
meshlets.add(MeshletDescription{ meshlets.add(MeshletDescription{
.bounding = m.boundingBox,//.toSphere(), .bounding = m.boundingBox, //.toSphere(),
.vertexCount = m.numVertices, .vertexCount = m.numVertices,
.primitiveCount = m.numPrimitives, .primitiveCount = m.numPrimitives,
.vertexOffset = vertexOffset, .vertexOffset = vertexOffset,
.primitiveOffset = primitiveOffset, .primitiveOffset = primitiveOffset,
.color = Vector((float)rand() / RAND_MAX,(float)rand() / RAND_MAX,(float)rand() / RAND_MAX), .color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
.indicesOffset = (uint32)meshOffsets[id], .indicesOffset = (uint32)meshOffsets[id],
}); });
} }
meshData[id] = MeshData{ meshData[id] = MeshData{
.bounding = meshAABB,//.toSphere(), .bounding = meshAABB, //.toSphere(),
.numMeshlets = (uint32)loadedMeshlets.size(), .numMeshlets = (uint32)loadedMeshlets.size(),
.meshletOffset = meshletOffset, .meshletOffset = meshletOffset,
.firstIndex = (uint32)indices.size(), .firstIndex = (uint32)indices.size(),
.numIndices = (uint32)loadedIndices.size(), .numIndices = (uint32)loadedIndices.size(),
}; };
if (!graphics->supportMeshShading()) if (!graphics->supportMeshShading())
{ {
indices.resize(indices.size() + loadedIndices.size()); indices.resize(indices.size() + loadedIndices.size());
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32)); std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{ indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
.sourceData = { .sourceData = {
.size = sizeof(uint32) * indices.size(), .size = sizeof(uint32) * indices.size(),
.data = (uint8*)indices.data(), .data = (uint8 *)indices.data(),
}, },
.indexType = Gfx::SE_INDEX_TYPE_UINT32, .indexType = Gfx::SE_INDEX_TYPE_UINT32,
.name = "IndexBuffer", .name = "IndexBuffer",
}); });
}
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(MeshletDescription) * meshlets.size(),
.data = (uint8 *)meshlets.data()},
.numElements = meshlets.size(),
.dynamic = false,
.name = "MeshletBuffer"});
} vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = {
.sourceData = { .size = sizeof(uint32) * vertexIndices.size(),
.size = sizeof(MeshletDescription) * meshlets.size(), .data = (uint8 *)vertexIndices.data(),
.data = (uint8*)meshlets.data() },
}, .numElements = vertexIndices.size(),
.numElements = meshlets.size(), .dynamic = false,
.dynamic = false, .name = "VertexIndicesBuffer"});
.name = "MeshletBuffer"
}); primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = {
.sourceData = { .size = sizeof(uint8) * primitiveIndices.size(),
.size = sizeof(uint32) * vertexIndices.size(), .data = (uint8 *)primitiveIndices.data(),
.data = (uint8*)vertexIndices.data(), },
}, .numElements = primitiveIndices.size(),
.numElements = vertexIndices.size(), .dynamic = false,
.dynamic = false, .name = "PrimitiveIndicesBuffer",
.name = "VertexIndicesBuffer" });
});
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = sizeof(uint8) * primitiveIndices.size(),
.data = (uint8*)primitiveIndices.data(),
},
.numElements = primitiveIndices.size(),
.dynamic = false,
.name = "PrimitiveIndicesBuffer",
});
} }
MeshId VertexData::allocateVertexData(uint64 numVertices) MeshId VertexData::allocateVertexData(uint64 numVertices)
{ {
std::unique_lock l(vertexDataLock); std::unique_lock l(vertexDataLock);
MeshId res{ idCounter++ }; MeshId res{idCounter++};
meshOffsets[res] = head; meshOffsets[res] = head;
meshVertexCounts[res] = numVertices; meshVertexCounts[res] = numVertices;
head += numVertices; head += numVertices;
if (head > verticesAllocated) if (head > verticesAllocated)
{ {
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS); verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
resizeBuffers(); resizeBuffers();
} }
return res; return res;
} }
uint64 VertexData::getMeshOffset(MeshId id) uint64 VertexData::getMeshOffset(MeshId id)
{ {
return meshOffsets[id]; return meshOffsets[id];
} }
uint64 VertexData::getMeshVertexCount(MeshId id) uint64 VertexData::getMeshVertexCount(MeshId id)
{ {
return meshVertexCounts[id]; return meshVertexCounts[id];
} }
List<VertexData*> vertexDataList; List<VertexData *> vertexDataList;
List<VertexData*> VertexData::getList() List<VertexData *> VertexData::getList()
{ {
return vertexDataList; return vertexDataList;
} }
VertexData* VertexData::findByTypeName(std::string name) VertexData *VertexData::findByTypeName(std::string name)
{ {
for (auto vd : vertexDataList) for (auto vd : vertexDataList)
{
if (vd->getTypeName() == name)
{ {
if (vd->getTypeName() == name) return vd;
{
return vd;
}
} }
return nullptr; }
return nullptr;
} }
void VertexData::init(Gfx::PGraphics _graphics) void VertexData::init(Gfx::PGraphics _graphics)
{ {
graphics = _graphics; graphics = _graphics;
verticesAllocated = NUM_DEFAULT_ELEMENTS; verticesAllocated = NUM_DEFAULT_ELEMENTS;
instanceDataLayout = graphics->createDescriptorLayout("pScene"); instanceDataLayout = graphics->createDescriptorLayout("pScene");
// instanceData // instanceData
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
// meshData .binding = 0,
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, }); .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
// meshletData });
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); // meshData
// primitiveIndices instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); .binding = 1,
// vertexIndices .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); });
// cullingList // meshletData
//instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingOffset // primitiveIndices
//instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// vertexIndices
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingList
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
// cullingOffset
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
//cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
// .dynamic = true, .dynamic = true,
// .name = "MeshletOffset", .name = "MeshletOffset",
// }); });
//cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
// .dynamic = true, .dynamic = true,
// .name = "MeshletCulling", .name = "MeshletCulling",
// }); });
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true, .dynamic = true,
.name = "InstanceBuffer", .name = "InstanceBuffer",
}); });
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.dynamic = true, .dynamic = true,
.name = "MeshDataBuffer", .name = "MeshDataBuffer",
}); });
instanceDataLayout->create(); instanceDataLayout->create();
resizeBuffers(); resizeBuffers();
graphics->getShaderCompiler()->registerVertexData(this); graphics->getShaderCompiler()->registerVertexData(this);
} }
void VertexData::destroy() void VertexData::destroy()
{ {
instanceBuffer = nullptr; instanceBuffer = nullptr;
instanceMeshDataBuffer = nullptr; instanceMeshDataBuffer = nullptr;
instanceDataLayout = nullptr; instanceDataLayout = nullptr;
meshletBuffer = nullptr; meshletBuffer = nullptr;
vertexIndicesBuffer = nullptr; vertexIndicesBuffer = nullptr;
primitiveIndicesBuffer = nullptr; primitiveIndicesBuffer = nullptr;
indexBuffer = nullptr; indexBuffer = nullptr;
meshData.clear(); meshData.clear();
materialData.clear(); materialData.clear();
} }
VertexData::VertexData() VertexData::VertexData()
: idCounter(0) : idCounter(0), head(0), verticesAllocated(0), dirty(false)
, head(0)
, verticesAllocated(0)
, dirty(false)
{ {
} }
+53 -46
View File
@@ -12,60 +12,65 @@ constexpr uint64 MAX_TEXCOORDS = 8;
namespace Seele namespace Seele
{ {
DECLARE_REF(Mesh) DECLARE_REF(Mesh)
struct MeshId struct MeshId
{ {
uint64 id; uint64 id;
std::strong_ordering operator<=>(const MeshId& other) const std::strong_ordering operator<=>(const MeshId &other) const
{ {
return id <=> other.id; return id <=> other.id;
} }
bool operator==(const MeshId& other) const bool operator==(const MeshId &other) const
{ {
return id == other.id; return id == other.id;
} }
}; };
class VertexData class VertexData
{ {
public: public:
struct InstanceData struct InstanceData
{ {
Matrix4 transformMatrix; Matrix4 transformMatrix;
Matrix4 inverseTransformMatrix; Matrix4 inverseTransformMatrix;
}; };
struct MeshData struct MeshData
{ {
AABB bounding; AABB bounding;
uint32 numMeshlets = 0; uint32 numMeshlets = 0;
uint32 meshletOffset = 0; uint32 meshletOffset = 0;
uint32 firstIndex = 0; uint32 firstIndex = 0;
uint32 numIndices = 0; uint32 numIndices = 0;
}; };
struct DrawCallOffsets struct DrawCallOffsets
{ {
uint32 instanceOffset = 0; uint32 instanceOffset = 0;
};
struct MeshletCullingInfo
{
uint64_t cull[256 / 64];
}; };
struct BatchedDrawCall struct BatchedDrawCall
{ {
PMaterialInstance materialInstance; PMaterialInstance materialInstance;
DrawCallOffsets offsets; DrawCallOffsets offsets;
Array<InstanceData> instanceData; Array<InstanceData> instanceData;
Array<MeshData> instanceMeshData; Array<MeshData> instanceMeshData;
}; };
struct MaterialData struct MaterialData
{ {
PMaterial material; PMaterial material;
Array<BatchedDrawCall> instances; Array<BatchedDrawCall> instances;
}; };
void resetMeshData(); void resetMeshData();
void updateMesh(PMesh mesh, Component::Transform& transform); void updateMesh(PMesh mesh, Component::Transform &transform);
void createDescriptors(); void createDescriptors();
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets); void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
MeshId allocateVertexData(uint64 numVertices); MeshId allocateVertexData(uint64 numVertices);
uint64 getMeshOffset(MeshId id); uint64 getMeshOffset(MeshId id);
uint64 getMeshVertexCount(MeshId id); uint64 getMeshVertexCount(MeshId id);
virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) = 0; virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer &buffer) = 0;
virtual void deserializeMesh(MeshId id, ArchiveBuffer& buffer) = 0; virtual void deserializeMesh(MeshId id, ArchiveBuffer &buffer) = 0;
virtual void bindBuffers(Gfx::PRenderCommand command) = 0; virtual void bindBuffers(Gfx::PRenderCommand command) = 0;
virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0; virtual Gfx::PDescriptorLayout getVertexDataLayout() = 0;
virtual Gfx::PDescriptorSet getVertexDataSet() = 0; virtual Gfx::PDescriptorSet getVertexDataSet() = 0;
@@ -73,26 +78,28 @@ public:
Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; } Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; }
Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; } Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; }
Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; } Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; }
const Array<MaterialData>& getMaterialData() const { return materialData; } const Array<MaterialData> &getMaterialData() const { return materialData; }
const MeshData& getMeshData(MeshId id) { return meshData[id]; } const MeshData &getMeshData(MeshId id) { return meshData[id]; }
uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; } uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; }
static List<VertexData*> getList(); uint64 getNumInstances() const { return instanceData.size(); }
static VertexData* findByTypeName(std::string name); static List<VertexData *> getList();
static VertexData *findByTypeName(std::string name);
virtual void init(Gfx::PGraphics graphics); virtual void init(Gfx::PGraphics graphics);
virtual void destroy(); virtual void destroy();
protected:
protected:
virtual void resizeBuffers() = 0; virtual void resizeBuffers() = 0;
virtual void updateBuffers() = 0; virtual void updateBuffers() = 0;
VertexData(); VertexData();
struct MeshletDescription struct MeshletDescription
{ {
AABB bounding; AABB bounding;
uint32 vertexCount; uint32 vertexCount;
uint32 primitiveCount; uint32 primitiveCount;
uint32 vertexOffset; uint32 vertexOffset;
uint32 primitiveOffset; uint32 primitiveOffset;
Vector color; Vector color;
uint32 indicesOffset = 0; uint32 indicesOffset = 0;
}; };
std::mutex materialDataLock; std::mutex materialDataLock;
Array<MaterialData> materialData; Array<MaterialData> materialData;
@@ -110,9 +117,9 @@ protected:
Gfx::OShaderBuffer meshletBuffer; Gfx::OShaderBuffer meshletBuffer;
Gfx::OShaderBuffer vertexIndicesBuffer; Gfx::OShaderBuffer vertexIndicesBuffer;
Gfx::OShaderBuffer primitiveIndicesBuffer; Gfx::OShaderBuffer primitiveIndicesBuffer;
// temporary meshlet culling buffer, passed from task to mesh shader // Holds culling information for every meshlet for each instance
//Gfx::OShaderBuffer cullingBuffer; Gfx::OShaderBuffer cullingBuffer;
//Gfx::OShaderBuffer cullingOffsetBuffer; Gfx::OShaderBuffer cullingOffsetBuffer;
// for legacy pipeline // for legacy pipeline
Gfx::OIndexBuffer indexBuffer; Gfx::OIndexBuffer indexBuffer;
// Material data // Material data
@@ -122,8 +129,8 @@ protected:
Gfx::OShaderBuffer instanceMeshDataBuffer; Gfx::OShaderBuffer instanceMeshDataBuffer;
Gfx::PDescriptorSet descriptorSet; Gfx::PDescriptorSet descriptorSet;
uint64 idCounter; uint64 idCounter;
uint64 head; uint64 head;
uint64 verticesAllocated; uint64 verticesAllocated;
bool dirty; bool dirty;
}; };
} }
+1 -1
View File
@@ -75,7 +75,7 @@ void Fence::reset()
} }
} }
void Fence::wait(uint32 timeout) void Fence::wait(uint64 timeout)
{ {
VkFence fences[] = {fence}; VkFence fences[] = {fence};
VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout); VkResult r = vkWaitForFences(graphics->getDevice(), 1, fences, true, timeout);
+1 -1
View File
@@ -38,7 +38,7 @@ public:
{ {
return fence; return fence;
} }
void wait(uint32 timeout); void wait(uint64 timeout);
bool operator<(const Fence &other) const bool operator<(const Fence &other) const
{ {
return fence < other.fence; return fence < other.fence;
+7 -4
View File
@@ -7,8 +7,12 @@
#include "System/LightGather.h" #include "System/LightGather.h"
#include "System/MeshUpdater.h" #include "System/MeshUpdater.h"
#include "System/CameraUpdater.h" #include "System/CameraUpdater.h"
#include "Graphics/Vulkan/Graphics.h" #include "Graphics/RenderPass/CachedDepthPass.h"
#include "Graphics/Vulkan/Allocator.h" #include "Graphics/RenderPass/DepthPrepass.h"
#include "Graphics/RenderPass/LightCullingPass.h"
#include "Graphics/RenderPass/BasePass.h"
#include "Graphics/RenderPass/SkyboxRenderPass.h"
#include "Graphics/RenderPass/DebugPass.h"
using namespace Seele; using namespace Seele;
@@ -22,10 +26,9 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
, gameInterface(dllPath) , gameInterface(dllPath)
{ {
reloadGame(); reloadGame();
//renderGraph.addPass(new StaticDepthPrepass(graphics, scene)); renderGraph.addPass(new CachedDepthPass(graphics, scene));
renderGraph.addPass(new DepthPrepass(graphics, scene)); renderGraph.addPass(new DepthPrepass(graphics, scene));
renderGraph.addPass(new LightCullingPass(graphics, scene)); renderGraph.addPass(new LightCullingPass(graphics, scene));
//renderGraph.addPass(new StaticBasePass(graphics, scene));
renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene));
renderGraph.addPass(new DebugPass(graphics, scene)); renderGraph.addPass(new DebugPass(graphics, scene));
//renderGraph.addPass(new SkyboxRenderPass(graphics, scene)); //renderGraph.addPass(new SkyboxRenderPass(graphics, scene));
+24 -28
View File
@@ -1,11 +1,6 @@
#pragma once #pragma once
#include "Window/View.h" #include "Window/View.h"
#include "Scene/Scene.h" #include "Scene/Scene.h"
#include "Graphics/RenderPass/DepthPrepass.h"
#include "Graphics/RenderPass/LightCullingPass.h"
#include "Graphics/RenderPass/BasePass.h"
#include "Graphics/RenderPass/SkyboxRenderPass.h"
#include "Graphics/RenderPass/DebugPass.h"
#include "System/KeyboardInput.h" #include "System/KeyboardInput.h"
#ifdef WIN32 #ifdef WIN32
#include "Platform/Windows/GameInterface.h" // TODO #include "Platform/Windows/GameInterface.h" // TODO
@@ -15,34 +10,35 @@
namespace Seele namespace Seele
{ {
class GameView : public View class GameView : public View
{ {
public: public:
GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo, std::string dllPath); GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo, std::string dllPath);
virtual ~GameView(); virtual ~GameView();
virtual void beginUpdate() override; virtual void beginUpdate() override;
virtual void update() override; virtual void update() override;
virtual void commitUpdate() override; virtual void commitUpdate() override;
virtual void prepareRender() override; virtual void prepareRender() override;
virtual void render() override; virtual void render() override;
void reloadGame(); void reloadGame();
protected:
virtual void applyArea(URect rect) override; protected:
OScene scene; virtual void applyArea(URect rect) override;
GameInterface gameInterface; OScene scene;
GameInterface gameInterface;
RenderGraph renderGraph; RenderGraph renderGraph;
PSystemGraph systemGraph; PSystemGraph systemGraph;
System::PKeyboardInput keyboardSystem; System::PKeyboardInput keyboardSystem;
float updateTime = 0; float updateTime = 0;
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override; virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override;
virtual void mouseMoveCallback(double xPos, double yPos) override; virtual void mouseMoveCallback(double xPos, double yPos) override;
virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifier modifier) override; virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifier modifier) override;
virtual void scrollCallback(double xOffset, double yOffset) override; virtual void scrollCallback(double xOffset, double yOffset) override;
virtual void fileCallback(int count, const char** paths) override; virtual void fileCallback(int count, const char **paths) override;
}; };
DEFINE_REF(GameView) DEFINE_REF(GameView)
} // namespace Seele } // namespace Seele