Working on visibility pass
This commit is contained in:
@@ -3,17 +3,18 @@ import Scene;
|
||||
|
||||
groupshared MeshPayload p;
|
||||
groupshared uint head;
|
||||
groupshared MeshData mesh;
|
||||
|
||||
[numthreads(TASK_GROUP_SIZE, 1, 1)]
|
||||
[shader("amplification")]
|
||||
void taskMain(
|
||||
uint threadID: SV_GroupIndex,
|
||||
uint threadID: SV_GroupThreadID,
|
||||
uint groupID: SV_GroupID, )
|
||||
{
|
||||
MeshData mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
|
||||
if (threadID == 0)
|
||||
{
|
||||
head = 0;
|
||||
mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
|
||||
p.instanceId = pOffsets.instanceOffset + groupID;
|
||||
p.meshletOffset = mesh.meshletOffset;
|
||||
p.cullingOffset = pScene.cullingOffsets[p.instanceId];
|
||||
@@ -24,8 +25,8 @@ void taskMain(
|
||||
uint m = p.meshletOffset + i;
|
||||
uint cull = p.cullingOffset + i;
|
||||
MeshletDescription meshlet = pScene.meshletInfos[m];
|
||||
MeshletCullingInfo culling = pScene.culledMeshlets[cull];
|
||||
if(false)
|
||||
MeshletCullingInfo culling = pScene.cullingInfos[cull];
|
||||
//if(!culling.anyVisible())
|
||||
{
|
||||
uint index;
|
||||
InterlockedAdd(head, 1, index);
|
||||
|
||||
@@ -8,7 +8,7 @@ groupshared MeshData mesh;
|
||||
[numthreads(TASK_GROUP_SIZE, 1, 1)]
|
||||
[shader("amplification")]
|
||||
void taskMain(
|
||||
uint threadID: SV_GroupIndex,
|
||||
uint threadID: SV_GroupThreadID,
|
||||
uint groupID: SV_GroupID, )
|
||||
{
|
||||
if (threadID == 0)
|
||||
@@ -25,7 +25,7 @@ void taskMain(
|
||||
uint m = p.meshletOffset + i;
|
||||
uint cull = p.cullingOffset + i;
|
||||
MeshletDescription meshlet = pScene.meshletInfos[m];
|
||||
MeshletCullingInfo culling = pScene.culledMeshlets[cull];
|
||||
MeshletCullingInfo culling = pScene.cullingInfos[cull];
|
||||
if(culling.anyVisible())
|
||||
{
|
||||
uint index;
|
||||
|
||||
@@ -15,7 +15,7 @@ struct PrimitiveAttributes
|
||||
[outputtopology("triangle")]
|
||||
[shader("mesh")]
|
||||
void meshMain(
|
||||
in uint threadID: SV_GroupIndex,
|
||||
in uint threadID: SV_GroupThreadID,
|
||||
in uint groupID: SV_GroupID,
|
||||
in payload MeshPayload meshPayload,
|
||||
out vertices FragmentParameter vertices[MAX_VERTICES],
|
||||
@@ -27,7 +27,7 @@ void meshMain(
|
||||
uint meshletId = meshPayload.cullingOffset + meshletNumber;
|
||||
InstanceData inst = pScene.instances[meshPayload.instanceId];
|
||||
MeshletDescription m = pScene.meshletInfos[meshPayload.meshletOffset + meshletNumber];
|
||||
MeshletCullingInfo cull = pScene.culledMeshlets[meshletId];
|
||||
MeshletCullingInfo cull = pScene.cullingInfos[meshletId];
|
||||
SetMeshOutputCounts(m.vertexCount, m.primitiveCount);
|
||||
|
||||
for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE)
|
||||
|
||||
@@ -8,35 +8,15 @@ struct VisibilityCullingData
|
||||
};
|
||||
ParameterBlock<VisibilityCullingData> pVisibilityParams;
|
||||
|
||||
groupshared MeshletCullingInfo cullInfo;
|
||||
|
||||
[numthreads(BLOCK_SIZE, 1, 1)]
|
||||
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||
[shader("compute")]
|
||||
void computeMain(
|
||||
uint threadID: SV_GroupIndex,
|
||||
uint groupID: SV_GroupID,
|
||||
uint3 dispatchThreadID: SV_DispatchThreadID,
|
||||
){
|
||||
if (threadID < MAX_PRIMITIVES / 32)
|
||||
{
|
||||
cullInfo.visible[threadID] = 0;
|
||||
}
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
for (uint y = 0; y < pViewParams.screenDimensions.y; y++)
|
||||
{
|
||||
for (uint x = threadID; x < pViewParams.screenDimensions.x; x += BLOCK_SIZE)
|
||||
{
|
||||
int3 texCoords = int3(x, y, 0);
|
||||
uint encoded = pVisibilityParams.visibilityTexture.Load(texCoords).r;
|
||||
uint2 decoded = decodePrimitive(encoded);
|
||||
uint base = decoded.y == groupID ? 1 : 0;
|
||||
uint arrIdx = decoded.x / 32;
|
||||
uint bit = decoded.x % 32;
|
||||
cullInfo.visible[arrIdx] |= (base << bit);
|
||||
}
|
||||
}
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
if (threadID < MAX_PRIMITIVES / 32)
|
||||
{
|
||||
pVisibilityParams.cullingInfos[groupID].visible[threadID] = cullInfo.visible[threadID];
|
||||
}
|
||||
int3 texCoords = int3(dispatchThreadID.xy, 0);
|
||||
uint encoded = pVisibilityParams.visibilityTexture.Load(texCoords).r;
|
||||
uint2 decoded = decodePrimitive(encoded);
|
||||
uint arrIdx = decoded.x / 32;
|
||||
uint bit = decoded.x % 32;
|
||||
pVisibilityParams.cullingInfos[decoded.y].visible[arrIdx] |= (1 << bit);
|
||||
}
|
||||
@@ -66,10 +66,10 @@ struct Scene
|
||||
StructuredBuffer<MeshletDescription> meshletInfos;
|
||||
StructuredBuffer<uint8_t> primitiveIndices;
|
||||
StructuredBuffer<uint32_t> vertexIndices;
|
||||
StructuredBuffer<MeshletCullingInfo> culledMeshlets;
|
||||
StructuredBuffer<uint32_t> cullingOffsets;
|
||||
StructuredBuffer<MeshletCullingInfo> cullingInfos;
|
||||
};
|
||||
layout(set = 2)
|
||||
layout(set=2)
|
||||
ParameterBlock<Scene> pScene;
|
||||
|
||||
uint32_t encodePrimitive(uint32_t primitiveId, uint32_t meshletId)
|
||||
|
||||
@@ -89,6 +89,8 @@ public:
|
||||
bool writeOnly = true) = 0;
|
||||
virtual void unmap() = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
|
||||
@@ -85,19 +85,6 @@ void BasePass::beginFrame(const Component::Camera& cam)
|
||||
|
||||
void BasePass::render()
|
||||
{
|
||||
oLightIndexList->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
tLightIndexList->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
oLightGrid->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
tLightGrid->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
opaqueCulling->updateBuffer(0, oLightIndexList);
|
||||
opaqueCulling->updateTexture(1, oLightGrid);
|
||||
transparentCulling->updateBuffer(0, tLightIndexList);
|
||||
@@ -112,6 +99,8 @@ void BasePass::render()
|
||||
permutation.setViewCulling(useViewCulling);
|
||||
for (VertexData* vertexData : VertexData::getList())
|
||||
{
|
||||
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
|
||||
vertexData->getInstanceDataSet()->writeChanges();
|
||||
permutation.setVertexData(vertexData->getTypeName());
|
||||
const auto& materials = vertexData->getMaterialData();
|
||||
for (const auto& materialData : materials)
|
||||
@@ -176,11 +165,11 @@ void BasePass::render()
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet());
|
||||
command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet());
|
||||
command->bindDescriptor(opaqueCulling);
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet());
|
||||
for (const auto& drawCall : materialData.instances)
|
||||
{
|
||||
command->bindDescriptor(drawCall.materialInstance->getDescriptorSet());
|
||||
@@ -221,6 +210,8 @@ void BasePass::publishOutputs()
|
||||
|
||||
void BasePass::createRenderPass()
|
||||
{
|
||||
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
|
||||
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
@@ -32,6 +32,8 @@ private:
|
||||
PCameraActor source;
|
||||
Gfx::OPipelineLayout basePassLayout;
|
||||
Gfx::ODescriptorLayout lightCullingLayout;
|
||||
|
||||
Gfx::PShaderBuffer cullingBuffer;
|
||||
};
|
||||
DEFINE_REF(BasePass)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -66,6 +66,8 @@ void CachedDepthPass::render()
|
||||
for (VertexData *vertexData : VertexData::getList())
|
||||
{
|
||||
permutation.setVertexData(vertexData->getTypeName());
|
||||
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
|
||||
vertexData->getInstanceDataSet()->writeChanges();
|
||||
|
||||
// Create Pipeline(VertexData)
|
||||
// Descriptors:
|
||||
@@ -120,8 +122,8 @@ void CachedDepthPass::render()
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
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);
|
||||
@@ -205,6 +207,8 @@ void CachedDepthPass::publishOutputs()
|
||||
|
||||
void CachedDepthPass::createRenderPass()
|
||||
{
|
||||
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
|
||||
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
.colorAttachments = {visibilityAttachment},
|
||||
.depthAttachment = depthAttachment,
|
||||
|
||||
@@ -21,6 +21,8 @@ private:
|
||||
Gfx::OTexture2D depthBuffer;
|
||||
Gfx::OTexture2D visibilityBuffer;
|
||||
Gfx::OPipelineLayout depthPrepassLayout;
|
||||
|
||||
Gfx::PShaderBuffer cullingBuffer;
|
||||
};
|
||||
DEFINE_REF(CachedDepthPass)
|
||||
}
|
||||
@@ -66,6 +66,8 @@ void DepthPrepass::render()
|
||||
for (VertexData *vertexData : VertexData::getList())
|
||||
{
|
||||
permutation.setVertexData(vertexData->getTypeName());
|
||||
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
|
||||
vertexData->getInstanceDataSet()->writeChanges();
|
||||
// Create Pipeline(VertexData)
|
||||
// Descriptors:
|
||||
// ViewData => global, static
|
||||
@@ -119,14 +121,14 @@ void DepthPrepass::render()
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
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);
|
||||
command->drawMesh(vertexData->getNumInstances(), 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -174,6 +176,13 @@ void DepthPrepass::render()
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
);
|
||||
// Sync culling reads to compute write
|
||||
cullingBuffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT,
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
);
|
||||
}
|
||||
|
||||
void DepthPrepass::endFrame()
|
||||
@@ -186,13 +195,15 @@ void DepthPrepass::publishOutputs()
|
||||
|
||||
void DepthPrepass::createRenderPass()
|
||||
{
|
||||
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
|
||||
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
visibilityAttachment = resources->requestRenderTarget("VISIBILITY");
|
||||
visibilityAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
visibilityAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
visibilityAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
|
||||
@@ -20,6 +20,8 @@ private:
|
||||
Gfx::RenderTargetAttachment depthAttachment;
|
||||
Gfx::RenderTargetAttachment visibilityAttachment;
|
||||
Gfx::OPipelineLayout depthPrepassLayout;
|
||||
|
||||
Gfx::PShaderBuffer cullingBuffer;
|
||||
};
|
||||
DEFINE_REF(DepthPrepass)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -81,6 +81,19 @@ void LightCullingPass::render()
|
||||
commands.add(std::move(computeCommand));
|
||||
//std::cout << "Execute" << std::endl;
|
||||
graphics->executeCommands(std::move(commands));
|
||||
|
||||
oLightIndexList->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
tLightIndexList->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
oLightGrid->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
tLightGrid->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void LightCullingPass::endFrame()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "VisibilityPass.h"
|
||||
#include "Graphics/Shader.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -15,15 +16,46 @@ VisibilityPass::~VisibilityPass()
|
||||
void VisibilityPass::beginFrame(const Component::Camera& cam)
|
||||
{
|
||||
RenderPass::beginFrame(cam);
|
||||
visibilityDescriptor->reset();
|
||||
visibilitySet = visibilityDescriptor->allocateDescriptorSet();
|
||||
visibilitySet->updateTexture(0, visibilityAttachment->getTexture());
|
||||
visibliitySet->updateBuffer(StaticMeshVertexData::getInstance()->get)
|
||||
|
||||
//Array<VertexData::MeshletCullingInfo> cullingData(VertexData::getMeshletCount());
|
||||
//std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(VertexData::MeshletCullingInfo));
|
||||
|
||||
//cullingBuffer->updateContents(ShaderBufferCreateInfo{
|
||||
// .sourceData = {
|
||||
// .size = VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo),
|
||||
// .data = (uint8 *)cullingData.data(),
|
||||
// },
|
||||
// .numElements = VertexData::getMeshletCount()});
|
||||
//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);
|
||||
|
||||
}
|
||||
|
||||
void VisibilityPass::render()
|
||||
{
|
||||
cullingBuffer->rotateBuffer(VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo));
|
||||
cullingBuffer->clear();
|
||||
|
||||
visibilityDescriptor->reset();
|
||||
visibilitySet = visibilityDescriptor->allocateDescriptorSet();
|
||||
visibilitySet->updateTexture(0, visibilityAttachment.getTexture());
|
||||
visibilitySet->updateBuffer(1, cullingBuffer);
|
||||
visibilitySet->writeChanges();
|
||||
|
||||
Gfx::OComputeCommand command = graphics->createComputeCommand("VisibilityCommand");
|
||||
command->bindPipeline(visibilityPipeline);
|
||||
command->bindDescriptor({viewParamsSet, visibilitySet});
|
||||
command->dispatch(threadGroupSize.x, threadGroupSize.y, threadGroupSize.z);
|
||||
Array<Gfx::OComputeCommand> commands;
|
||||
commands.add(std::move(command));
|
||||
graphics->executeCommands(std::move(commands));
|
||||
|
||||
cullingBuffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
||||
}
|
||||
|
||||
void VisibilityPass::endFrame()
|
||||
@@ -32,8 +64,11 @@ void VisibilityPass::endFrame()
|
||||
}
|
||||
|
||||
void VisibilityPass::publishOutputs()
|
||||
{
|
||||
visibilityDescriptor = graphcis->createDescriptorLayout("pVisibilityParams");
|
||||
{
|
||||
uint32_t viewportWidth = viewport->getWidth();
|
||||
uint32_t viewportHeight = viewport->getHeight();
|
||||
threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
|
||||
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
|
||||
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, });
|
||||
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT, });
|
||||
visibilityDescriptor->create();
|
||||
@@ -55,6 +90,9 @@ void VisibilityPass::publishOutputs()
|
||||
pipelineInfo.computeShader = visibilityShader;
|
||||
pipelineInfo.pipelineLayout = std::move(visibilityLayout);
|
||||
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
||||
|
||||
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.dynamic = true, .name = "CullingBuffer"});
|
||||
resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer);
|
||||
}
|
||||
|
||||
void VisibilityPass::createRenderPass()
|
||||
|
||||
@@ -15,16 +15,18 @@ public:
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
uint64 allocate
|
||||
private:
|
||||
static constexpr uint32 BLOCK_SIZE = 32;
|
||||
Gfx::RenderTargetAttachment visibilityAttachment;
|
||||
Gfx::PDescriptorSet visibilitySet;
|
||||
Gfx::ODescriptorLayout visibilityDescriptor;
|
||||
Gfx::OPipelineLayout visibilityLayout;
|
||||
Gfx::OComputeShader visibilityShader;
|
||||
Gfx::PComputePipeline visibilityPipeline;
|
||||
|
||||
// Holds culling information for every meshlet for each instance
|
||||
Gfx::OShaderBuffer cullingBuffer;
|
||||
glm::uvec3 threadGroupSize;
|
||||
};
|
||||
DEFINE_REF(VisibilityPass)
|
||||
}
|
||||
@@ -36,12 +36,13 @@ void ShaderCompiler::registerVertexData(VertexData *vd)
|
||||
|
||||
void ShaderCompiler::registerRenderPass(std::string name, PassConfig config)
|
||||
{
|
||||
passes[name] = config;
|
||||
passes[name] = std::move(config);
|
||||
compile();
|
||||
}
|
||||
|
||||
ShaderPermutation ShaderCompiler::getTemplate(std::string name)
|
||||
{
|
||||
std::scoped_lock lock(shadersLock);
|
||||
ShaderPermutation permutation;
|
||||
PassConfig &pass = passes[name];
|
||||
if (pass.useMeshShading)
|
||||
|
||||
+296
-301
@@ -12,370 +12,365 @@
|
||||
using namespace Seele;
|
||||
|
||||
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 1024 * 1024;
|
||||
Map<VertexData::MeshMapping, VertexData::CullingMapping> VertexData::instanceIdMap;
|
||||
uint64 VertexData::instanceCount = 0;
|
||||
uint64 VertexData::meshletCount = 0;
|
||||
|
||||
void VertexData::resetMeshData()
|
||||
{
|
||||
std::unique_lock l(materialDataLock);
|
||||
for (auto &mat : materialData)
|
||||
{
|
||||
for (auto &inst : mat.instances)
|
||||
std::unique_lock l(materialDataLock);
|
||||
for (auto &mat : materialData)
|
||||
{
|
||||
inst.instanceData.clear();
|
||||
inst.instanceMeshData.clear();
|
||||
for (auto &inst : mat.instances)
|
||||
{
|
||||
inst.instanceData.clear();
|
||||
inst.instanceMeshData.clear();
|
||||
}
|
||||
if (mat.material != nullptr)
|
||||
{
|
||||
mat.material->getDescriptorLayout()->reset();
|
||||
}
|
||||
}
|
||||
if (mat.material != nullptr)
|
||||
if (dirty)
|
||||
{
|
||||
mat.material->getDescriptorLayout()->reset();
|
||||
updateBuffers();
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
if (dirty)
|
||||
{
|
||||
updateBuffers();
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexData::updateMesh(PMesh mesh, Component::Transform &transform)
|
||||
void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform &transform)
|
||||
{
|
||||
std::unique_lock l(materialDataLock);
|
||||
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
||||
PMaterial mat = referencedInstance->getBaseMaterial();
|
||||
if (materialData.size() <= mat->getId())
|
||||
{
|
||||
materialData.resize(mat->getId() + 1);
|
||||
}
|
||||
MaterialData &matData = materialData[mat->getId()];
|
||||
matData.material = mat;
|
||||
if (matData.instances.size() <= referencedInstance->getId())
|
||||
{
|
||||
matData.instances.resize(referencedInstance->getId() + 1);
|
||||
}
|
||||
BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()];
|
||||
matInstanceData.materialInstance = referencedInstance;
|
||||
std::unique_lock l(materialDataLock);
|
||||
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
||||
PMaterial mat = referencedInstance->getBaseMaterial();
|
||||
if (materialData.size() <= mat->getId())
|
||||
{
|
||||
materialData.resize(mat->getId() + 1);
|
||||
}
|
||||
MaterialData &matData = materialData[mat->getId()];
|
||||
matData.material = mat;
|
||||
if (matData.instances.size() <= referencedInstance->getId())
|
||||
{
|
||||
matData.instances.resize(referencedInstance->getId() + 1);
|
||||
}
|
||||
BatchedDrawCall &matInstanceData = matData.instances[referencedInstance->getId()];
|
||||
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];
|
||||
auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
|
||||
matInstanceData.instanceMeshData.add(data);
|
||||
matInstanceData.cullingOffsets.add(meshletOffset);
|
||||
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()
|
||||
{
|
||||
std::unique_lock l(materialDataLock);
|
||||
std::unique_lock l(materialDataLock);
|
||||
|
||||
instanceData.clear();
|
||||
instanceMeshData.clear();
|
||||
instanceData.clear();
|
||||
instanceMeshData.clear();
|
||||
|
||||
uint32 numMeshlets = 0;
|
||||
Array<uint32> cullingOffsets;
|
||||
for (auto &mat : materialData)
|
||||
{
|
||||
for (auto &instance : mat.instances)
|
||||
uint32 numMeshlets = 0;
|
||||
Array<uint32> cullingOffsets;
|
||||
for (auto &mat : materialData)
|
||||
{
|
||||
instance.offsets.instanceOffset = instanceData.size();
|
||||
// instance.offsets.cullingCounterOffset = cullingOffsets.size();
|
||||
// instance.numMeshlets = 0;
|
||||
for (size_t i = 0; i < instance.instanceData.size(); ++i)
|
||||
{
|
||||
cullingOffsets.add(numMeshlets);
|
||||
instanceData.add(instance.instanceData[i]);
|
||||
instanceMeshData.add(instance.instanceMeshData[i]);
|
||||
// instance.numMeshlets += instance.instanceMeshData[i].numMeshlets;
|
||||
// cullingOffsets.add(numMeshlets);
|
||||
numMeshlets += instance.instanceMeshData[i].numMeshlets;
|
||||
}
|
||||
for (auto &instance : mat.instances)
|
||||
{
|
||||
instance.offsets.instanceOffset = instanceData.size();
|
||||
// instance.offsets.cullingCounterOffset = cullingOffsets.size();
|
||||
// instance.numMeshlets = 0;
|
||||
for (size_t i = 0; i < instance.instanceData.size(); ++i)
|
||||
{
|
||||
cullingOffsets.add(instance.cullingOffsets[i]);
|
||||
instanceData.add(instance.instanceData[i]);
|
||||
instanceMeshData.add(instance.instanceMeshData[i]);
|
||||
// instance.numMeshlets += instance.instanceMeshData[i].numMeshlets;
|
||||
// cullingOffsets.add(numMeshlets);
|
||||
numMeshlets += instance.instanceMeshData[i].numMeshlets;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Array<MeshletCullingInfo> cullingData(numMeshlets);
|
||||
std::memset(cullingData.data(), 0xffff, cullingData.size() * sizeof(MeshletCullingInfo));
|
||||
cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
|
||||
cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = cullingOffsets.size() * sizeof(uint32),
|
||||
.data = (uint8 *)cullingOffsets.data(),
|
||||
},
|
||||
.numElements = cullingOffsets.size()});
|
||||
cullingOffsetBuffer->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);
|
||||
cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32));
|
||||
cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = cullingOffsets.size() * sizeof(uint32),
|
||||
.data = (uint8 *)cullingOffsets.data(),
|
||||
},
|
||||
.numElements = cullingOffsets.size()});
|
||||
cullingOffsetBuffer->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);
|
||||
|
||||
cullingBuffer->rotateBuffer(cullingData.size() * sizeof(MeshletCullingInfo));
|
||||
cullingBuffer->updateContents(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = cullingData.size() * sizeof(MeshletCullingInfo),
|
||||
.data = (uint8 *)cullingData.data(),
|
||||
},
|
||||
.numElements = cullingData.size()});
|
||||
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);
|
||||
|
||||
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());
|
||||
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();
|
||||
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, cullingOffsetBuffer);
|
||||
}
|
||||
|
||||
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
|
||||
{
|
||||
assert(loadedMeshlets.size() < 2048);
|
||||
std::unique_lock l(vertexDataLock);
|
||||
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
||||
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
||||
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
||||
uint32 meshletOffset = meshlets.size();
|
||||
AABB meshAABB;
|
||||
for (uint32 i = 0; i < loadedMeshlets.size(); ++i)
|
||||
{
|
||||
Meshlet &m = loadedMeshlets[i];
|
||||
meshAABB = meshAABB.combine(m.boundingBox);
|
||||
uint32 vertexOffset = vertexIndices.size();
|
||||
vertexIndices.resize(vertexOffset + m.numVertices);
|
||||
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
|
||||
uint32 primitiveOffset = primitiveIndices.size();
|
||||
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
||||
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
||||
meshlets.add(MeshletDescription{
|
||||
.bounding = m.boundingBox, //.toSphere(),
|
||||
.vertexCount = m.numVertices,
|
||||
.primitiveCount = m.numPrimitives,
|
||||
.vertexOffset = vertexOffset,
|
||||
.primitiveOffset = primitiveOffset,
|
||||
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
|
||||
.indicesOffset = (uint32)meshOffsets[id],
|
||||
});
|
||||
}
|
||||
meshData[id] = MeshData{
|
||||
.bounding = meshAABB, //.toSphere(),
|
||||
.numMeshlets = (uint32)loadedMeshlets.size(),
|
||||
.meshletOffset = meshletOffset,
|
||||
.firstIndex = (uint32)indices.size(),
|
||||
.numIndices = (uint32)loadedIndices.size(),
|
||||
};
|
||||
assert(loadedMeshlets.size() < 2048);
|
||||
std::unique_lock l(vertexDataLock);
|
||||
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
||||
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
||||
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
||||
uint32 meshletOffset = meshlets.size();
|
||||
AABB meshAABB;
|
||||
for (uint32 i = 0; i < loadedMeshlets.size(); ++i)
|
||||
{
|
||||
Meshlet &m = loadedMeshlets[i];
|
||||
meshAABB = meshAABB.combine(m.boundingBox);
|
||||
uint32 vertexOffset = vertexIndices.size();
|
||||
vertexIndices.resize(vertexOffset + m.numVertices);
|
||||
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
|
||||
uint32 primitiveOffset = primitiveIndices.size();
|
||||
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
||||
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
||||
meshlets.add(MeshletDescription{
|
||||
.bounding = m.boundingBox, //.toSphere(),
|
||||
.vertexCount = m.numVertices,
|
||||
.primitiveCount = m.numPrimitives,
|
||||
.vertexOffset = vertexOffset,
|
||||
.primitiveOffset = primitiveOffset,
|
||||
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
|
||||
.indicesOffset = (uint32)meshOffsets[id],
|
||||
});
|
||||
}
|
||||
meshData[id] = MeshData{
|
||||
.bounding = meshAABB, //.toSphere(),
|
||||
.numMeshlets = (uint32)loadedMeshlets.size(),
|
||||
.meshletOffset = meshletOffset,
|
||||
.firstIndex = (uint32)indices.size(),
|
||||
.numIndices = (uint32)loadedIndices.size(),
|
||||
};
|
||||
|
||||
if (!graphics->supportMeshShading())
|
||||
{
|
||||
indices.resize(indices.size() + loadedIndices.size());
|
||||
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
|
||||
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
|
||||
if (!graphics->supportMeshShading())
|
||||
{
|
||||
indices.resize(indices.size() + loadedIndices.size());
|
||||
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
|
||||
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(uint32) * indices.size(),
|
||||
.data = (uint8 *)indices.data(),
|
||||
},
|
||||
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
|
||||
.name = "IndexBuffer",
|
||||
});
|
||||
}
|
||||
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(uint32) * indices.size(),
|
||||
.data = (uint8 *)indices.data(),
|
||||
.size = sizeof(MeshletDescription) * meshlets.size(),
|
||||
.data = (uint8 *)meshlets.data()},
|
||||
.numElements = meshlets.size(),
|
||||
.dynamic = false,
|
||||
.name = "MeshletBuffer"});
|
||||
|
||||
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(uint32) * vertexIndices.size(),
|
||||
.data = (uint8 *)vertexIndices.data(),
|
||||
},
|
||||
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
|
||||
.name = "IndexBuffer",
|
||||
.numElements = vertexIndices.size(),
|
||||
.dynamic = false,
|
||||
.name = "VertexIndicesBuffer"});
|
||||
|
||||
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(uint8) * primitiveIndices.size(),
|
||||
.data = (uint8 *)primitiveIndices.data(),
|
||||
},
|
||||
.numElements = primitiveIndices.size(),
|
||||
.dynamic = false,
|
||||
.name = "PrimitiveIndicesBuffer",
|
||||
});
|
||||
}
|
||||
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{
|
||||
.sourceData = {
|
||||
.size = sizeof(uint32) * vertexIndices.size(),
|
||||
.data = (uint8 *)vertexIndices.data(),
|
||||
},
|
||||
.numElements = vertexIndices.size(),
|
||||
.dynamic = false,
|
||||
.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)
|
||||
{
|
||||
std::unique_lock l(vertexDataLock);
|
||||
MeshId res{idCounter++};
|
||||
meshOffsets[res] = head;
|
||||
meshVertexCounts[res] = numVertices;
|
||||
head += numVertices;
|
||||
if (head > verticesAllocated)
|
||||
{
|
||||
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
|
||||
resizeBuffers();
|
||||
}
|
||||
return res;
|
||||
std::unique_lock l(vertexDataLock);
|
||||
MeshId res{idCounter++};
|
||||
meshOffsets[res] = head;
|
||||
meshVertexCounts[res] = numVertices;
|
||||
head += numVertices;
|
||||
if (head > verticesAllocated)
|
||||
{
|
||||
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
|
||||
resizeBuffers();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64 VertexData::getMeshOffset(MeshId id)
|
||||
{
|
||||
return meshOffsets[id];
|
||||
return meshOffsets[id];
|
||||
}
|
||||
|
||||
uint64 VertexData::getMeshVertexCount(MeshId id)
|
||||
{
|
||||
return meshVertexCounts[id];
|
||||
return meshVertexCounts[id];
|
||||
}
|
||||
|
||||
List<VertexData *> vertexDataList;
|
||||
|
||||
List<VertexData *> VertexData::getList()
|
||||
{
|
||||
return vertexDataList;
|
||||
return vertexDataList;
|
||||
}
|
||||
|
||||
VertexData *VertexData::findByTypeName(std::string name)
|
||||
{
|
||||
for (auto vd : vertexDataList)
|
||||
{
|
||||
if (vd->getTypeName() == name)
|
||||
for (auto vd : vertexDataList)
|
||||
{
|
||||
return vd;
|
||||
if (vd->getTypeName() == name)
|
||||
{
|
||||
return vd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VertexData::init(Gfx::PGraphics _graphics)
|
||||
{
|
||||
graphics = _graphics;
|
||||
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
||||
instanceDataLayout = graphics->createDescriptorLayout("pScene");
|
||||
graphics = _graphics;
|
||||
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
||||
instanceDataLayout = graphics->createDescriptorLayout("pScene");
|
||||
|
||||
// instanceData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
// meshData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
// meshletData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||
// primitiveIndices
|
||||
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});
|
||||
// instanceData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
// meshData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
// meshletData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||
// primitiveIndices
|
||||
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});
|
||||
// cullingOffset
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||
// cullingInfos
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||
|
||||
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MeshletOffset",
|
||||
});
|
||||
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MeshletCulling",
|
||||
});
|
||||
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "InstanceBuffer",
|
||||
});
|
||||
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MeshDataBuffer",
|
||||
});
|
||||
instanceDataLayout->create();
|
||||
resizeBuffers();
|
||||
graphics->getShaderCompiler()->registerVertexData(this);
|
||||
instanceDataLayout->create();
|
||||
|
||||
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MeshletOffset",
|
||||
});
|
||||
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "InstanceBuffer",
|
||||
});
|
||||
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MeshDataBuffer",
|
||||
});
|
||||
resizeBuffers();
|
||||
graphics->getShaderCompiler()->registerVertexData(this);
|
||||
}
|
||||
|
||||
void VertexData::destroy()
|
||||
{
|
||||
instanceBuffer = nullptr;
|
||||
instanceMeshDataBuffer = nullptr;
|
||||
instanceDataLayout = nullptr;
|
||||
meshletBuffer = nullptr;
|
||||
vertexIndicesBuffer = nullptr;
|
||||
primitiveIndicesBuffer = nullptr;
|
||||
indexBuffer = nullptr;
|
||||
meshData.clear();
|
||||
materialData.clear();
|
||||
instanceBuffer = nullptr;
|
||||
instanceMeshDataBuffer = nullptr;
|
||||
instanceDataLayout = nullptr;
|
||||
meshletBuffer = nullptr;
|
||||
vertexIndicesBuffer = nullptr;
|
||||
primitiveIndicesBuffer = nullptr;
|
||||
indexBuffer = nullptr;
|
||||
meshData.clear();
|
||||
materialData.clear();
|
||||
}
|
||||
|
||||
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets)
|
||||
{
|
||||
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
|
||||
if (!instanceIdMap.contains(key))
|
||||
{
|
||||
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
|
||||
meshletCount += numMeshlets;
|
||||
}
|
||||
return instanceIdMap[key];
|
||||
}
|
||||
|
||||
VertexData::VertexData()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Buffer.h"
|
||||
#include "Meshlet.h"
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
constexpr uint64 MAX_TEXCOORDS = 8;
|
||||
|
||||
@@ -56,6 +57,7 @@ namespace Seele
|
||||
DrawCallOffsets offsets;
|
||||
Array<InstanceData> instanceData;
|
||||
Array<MeshData> instanceMeshData;
|
||||
Array<uint32> cullingOffsets;
|
||||
};
|
||||
struct MaterialData
|
||||
{
|
||||
@@ -63,7 +65,7 @@ namespace Seele
|
||||
Array<BatchedDrawCall> instances;
|
||||
};
|
||||
void resetMeshData();
|
||||
void updateMesh(PMesh mesh, Component::Transform &transform);
|
||||
void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform &transform);
|
||||
void createDescriptors();
|
||||
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
|
||||
MeshId allocateVertexData(uint64 numVertices);
|
||||
@@ -87,6 +89,15 @@ namespace Seele
|
||||
virtual void init(Gfx::PGraphics graphics);
|
||||
virtual void destroy();
|
||||
|
||||
struct CullingMapping
|
||||
{
|
||||
uint64 instanceId;
|
||||
uint32 cullingOffset;
|
||||
};
|
||||
static CullingMapping getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets);
|
||||
static uint64 getInstanceCount() { return instanceCount; }
|
||||
static uint64 getMeshletCount() { return meshletCount; }
|
||||
|
||||
protected:
|
||||
virtual void resizeBuffers() = 0;
|
||||
virtual void updateBuffers() = 0;
|
||||
@@ -111,6 +122,17 @@ namespace Seele
|
||||
Array<uint8> primitiveIndices;
|
||||
Array<uint32> vertexIndices;
|
||||
Array<uint32> indices;
|
||||
|
||||
struct MeshMapping
|
||||
{
|
||||
entt::entity id;
|
||||
uint32 meshId;
|
||||
auto operator<=>(const MeshMapping& other) const = default;
|
||||
};
|
||||
static Map<MeshMapping, CullingMapping> instanceIdMap;
|
||||
static uint64 instanceCount;
|
||||
static uint64 meshletCount;
|
||||
|
||||
Gfx::PGraphics graphics;
|
||||
Gfx::ODescriptorLayout instanceDataLayout;
|
||||
// for mesh shading
|
||||
|
||||
@@ -389,6 +389,11 @@ void *ShaderBuffer::mapRegion(uint64 offset, uint64 size, bool writeOnly) {
|
||||
|
||||
void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); }
|
||||
|
||||
void ShaderBuffer::clear()
|
||||
{
|
||||
vkCmdFillBuffer(graphics->getQueueCommands(owner)->getCommands()->getHandle(), Vulkan::Buffer::getHandle(), 0, VK_WHOLE_SIZE, 0);
|
||||
}
|
||||
|
||||
void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) {
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
}
|
||||
|
||||
@@ -133,6 +133,8 @@ public:
|
||||
virtual void *mapRegion(uint64 offset, uint64 size, bool writeOnly) override;
|
||||
virtual void unmap() override;
|
||||
|
||||
virtual void clear() override;
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask() override;
|
||||
|
||||
@@ -27,10 +27,11 @@ public:
|
||||
void setupView(Dependencies<Deps...>)
|
||||
{
|
||||
//List<std::function<void()>> work;
|
||||
registry.view<Components..., Deps...>().each([&](Components&... comp, Deps&... deps){
|
||||
registry.view<Components..., Deps...>().each([&](entt::entity id, Components&... comp, Deps&... deps){
|
||||
//work.add([&]() {
|
||||
(accessComponent(deps), ...);
|
||||
update(comp...);
|
||||
update(id, comp...);
|
||||
//});
|
||||
});
|
||||
//getThreadPool().runAndWait(std::move(work));
|
||||
@@ -41,7 +42,8 @@ public:
|
||||
setupView((getDependencies<Components>() | ...));
|
||||
}
|
||||
virtual void update() override {}
|
||||
virtual void update(Components&... components) = 0;
|
||||
virtual void update(Components&... components) {}
|
||||
virtual void update(entt::entity id, Components&... components) {}
|
||||
};
|
||||
} // namespace System
|
||||
} // namespace Seele
|
||||
|
||||
@@ -14,10 +14,10 @@ MeshUpdater::~MeshUpdater()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshUpdater::update(Component::Transform& transform, Component::Mesh& comp)
|
||||
void MeshUpdater::update(entt::entity id, Component::Transform& transform, Component::Mesh& comp)
|
||||
{
|
||||
for (auto& mesh : comp.asset->meshes)
|
||||
for (uint32 i = 0; i < comp.asset->meshes.size(); ++i)
|
||||
{
|
||||
mesh->vertexData->updateMesh(mesh, transform);
|
||||
comp.asset->meshes[i]->vertexData->updateMesh(id, i, comp.asset->meshes[i], transform);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class MeshUpdater : public ComponentSystem<Component::Transform, Component::Mesh
|
||||
public:
|
||||
MeshUpdater(PScene scene);
|
||||
virtual ~MeshUpdater();
|
||||
virtual void update(Component::Transform& transform, Component::Mesh& mesh) override;
|
||||
virtual void update(entt::entity id, Component::Transform& transform, Component::Mesh& mesh) override;
|
||||
private:
|
||||
};
|
||||
} // namespace System
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "System/CameraUpdater.h"
|
||||
#include "Graphics/RenderPass/CachedDepthPass.h"
|
||||
#include "Graphics/RenderPass/DepthPrepass.h"
|
||||
#include "Graphics/RenderPass/VisibilityPass.h"
|
||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||
#include "Graphics/RenderPass/BasePass.h"
|
||||
#include "Graphics/RenderPass/SkyboxRenderPass.h"
|
||||
@@ -28,6 +29,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
||||
reloadGame();
|
||||
renderGraph.addPass(new CachedDepthPass(graphics, scene));
|
||||
renderGraph.addPass(new DepthPrepass(graphics, scene));
|
||||
renderGraph.addPass(new VisibilityPass(graphics, scene));
|
||||
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||
renderGraph.addPass(new BasePass(graphics, scene));
|
||||
renderGraph.addPass(new DebugPass(graphics, scene));
|
||||
|
||||
Reference in New Issue
Block a user