Working on visibility pass
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user