Adding view culling to non-depth culling variant

This commit is contained in:
Dynamitos
2024-06-25 11:21:56 +02:00
parent c352555b0b
commit 00bb6b3a96
10 changed files with 144 additions and 175 deletions
+4 -21
View File
@@ -24,27 +24,8 @@ bool isBoxVisible(AABB bounding)
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet // now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
uint2 screenCornerMin = mipDimensions; uint2 screenCornerMin = mipDimensions;
uint2 screenCornerMax = uint2(0, 0); uint2 screenCornerMax = uint2(0, 0);
// we use reverse depth, so higher values are closer // lower values are closer
float maxDepth = 0; float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax);
{
float4 corners[8];
corners[0] = float4(bounding.min.x, bounding.min.y, bounding.min.z, 1.0f);
corners[1] = float4(bounding.min.x, bounding.min.y, bounding.max.z, 1.0f);
corners[2] = float4(bounding.min.x, bounding.max.y, bounding.min.z, 1.0f);
corners[3] = float4(bounding.min.x, bounding.max.y, bounding.max.z, 1.0f);
corners[4] = float4(bounding.max.x, bounding.min.y, bounding.min.z, 1.0f);
corners[5] = float4(bounding.max.x, bounding.min.y, bounding.max.z, 1.0f);
corners[6] = float4(bounding.max.x, bounding.max.y, bounding.min.z, 1.0f);
corners[7] = float4(bounding.max.x, bounding.max.y, bounding.max.z, 1.0f);
for(uint i = 0; i < 8; ++i)
{
float4 clipCorner = mul(modelViewProjection, corners[i]);
float4 screenCorner = clipToScreen(clipCorner);
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
maxDepth = max(maxDepth, screenCorner.z);
}
}
uint mipOffset = 0; uint mipOffset = 0;
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling // in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1) while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
@@ -118,8 +99,10 @@ void taskMain(
// if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways // if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways
if(meshlet.bounding.insideFrustum(viewFrustum)) if(meshlet.bounding.insideFrustum(viewFrustum))
{ {
#ifdef DEPTH_CULLING
// if the meshlet bounding box is behind the cached depth buffer, we skip // if the meshlet bounding box is behind the cached depth buffer, we skip
if(isBoxVisible(meshlet.bounding)) if(isBoxVisible(meshlet.bounding))
#endif
{ {
uint index; uint index;
InterlockedAdd(head, 1, index); InterlockedAdd(head, 1, index);
-1
View File
@@ -62,5 +62,4 @@ void initialReduce(
int2 texCoord = groupOffset + threadID.xy; int2 texCoord = groupOffset + threadID.xy;
float fDepth = pDepthAttachment.texture.Load(int3(texCoord, 0)).r; float fDepth = pDepthAttachment.texture.Load(int3(texCoord, 0)).r;
pDepthAttachment.buffer[texCoord.x + (texCoord.y * width)] = fDepth; pDepthAttachment.buffer[texCoord.x + (texCoord.y * width)] = fDepth;
} }
-3
View File
@@ -26,10 +26,7 @@ void taskMain(
uint cull = p.cullingOffset + i; uint cull = p.cullingOffset + i;
MeshletDescription meshlet = pScene.meshletInfos[m]; MeshletDescription meshlet = pScene.meshletInfos[m];
MeshletCullingInfo culling = pScene.cullingInfos[cull]; MeshletCullingInfo culling = pScene.cullingInfos[cull];
#ifdef DEPTH_CULLING
// if depth culling is disabled, we draw the whole scene as if cached
if(culling.wasVisible()) if(culling.wasVisible())
#endif
{ {
uint index; uint index;
InterlockedAdd(head, 1, index); InterlockedAdd(head, 1, index);
+27 -5
View File
@@ -16,7 +16,7 @@ struct BoundingSphere
bool result = true; bool result = true;
for(int i = 0; i < 4 && result; ++i) for(int i = 0; i < 4 && result; ++i)
{ {
if(dot(frustum.sides[i].n, centerRadius.xyz) - frustum.sides[i].d < -getRadius()) if(dot(frustum.sides[i].n, getCenter()) - frustum.sides[i].d < -getRadius())
{ {
result = false; result = false;
} }
@@ -27,15 +27,15 @@ struct BoundingSphere
struct AABB struct AABB
{ {
float3 min; float3 minCorner;
float pad0; float pad0;
float3 max; float3 maxCorner;
float pad1; float pad1;
// modified version from https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling // modified version from https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling
bool insideFrustum(Frustum frustum) bool insideFrustum(Frustum frustum)
{ {
float3 center = (min + max) * 0.5; float3 center = (minCorner + maxCorner) * 0.5;
float3 extents = float3(max.x - center.x, max.y - center.y, max.z - center.z); float3 extents = float3(maxCorner.x - center.x, maxCorner.y - center.y, maxCorner.z - center.z);
bool result = true; bool result = true;
for(int i = 0; i < 4 && result; ++i) for(int i = 0; i < 4 && result; ++i)
{ {
@@ -51,4 +51,26 @@ struct AABB
} }
return result; return result;
} }
float projectScreenDepth(float4x4 mvp, inout uint2 screenCornerMin, inout uint2 screenCornerMax)
{
float maxDepth = 0;
float4 corners[8];
corners[0] = float4(minCorner.x, minCorner.y, minCorner.z, 1.0f);
corners[1] = float4(minCorner.x, minCorner.y, maxCorner.z, 1.0f);
corners[2] = float4(minCorner.x, maxCorner.y, minCorner.z, 1.0f);
corners[3] = float4(minCorner.x, maxCorner.y, maxCorner.z, 1.0f);
corners[4] = float4(maxCorner.x, minCorner.y, minCorner.z, 1.0f);
corners[5] = float4(maxCorner.x, minCorner.y, maxCorner.z, 1.0f);
corners[6] = float4(maxCorner.x, maxCorner.y, minCorner.z, 1.0f);
corners[7] = float4(maxCorner.x, maxCorner.y, maxCorner.z, 1.0f);
for(uint i = 0; i < 8; ++i)
{
float4 clipCorner = mul(mvp, corners[i]);
float4 screenCorner = clipToScreen(clipCorner);
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
maxDepth = max(maxDepth, screenCorner.z);
}
return maxDepth;
}
}; };
+5 -6
View File
@@ -404,19 +404,19 @@ void findMeshRoots(aiNode* node, List<aiNode*>& meshNodes) {
void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialInstanceAsset>& materials, Array<OMesh>& globalMeshes, void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialInstanceAsset>& materials, Array<OMesh>& globalMeshes,
Component::Collider& collider) { Component::Collider& collider) {
//List<std::function<void()>> work; List<std::function<void()>> work;
for (int32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) { for (int32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) {
aiMesh* mesh = scene->mMeshes[meshIndex]; aiMesh* mesh = scene->mMeshes[meshIndex];
if (!(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) if (!(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE))
continue; continue;
globalMeshes.add(nullptr); globalMeshes[meshIndex] = new Mesh();
StaticMeshVertexData* vertexData = StaticMeshVertexData::getInstance(); StaticMeshVertexData* vertexData = StaticMeshVertexData::getInstance();
MeshId id = vertexData->allocateVertexData(mesh->mNumVertices); MeshId id = vertexData->allocateVertexData(mesh->mNumVertices);
uint64 offset = vertexData->getMeshOffset(id); uint64 offset = vertexData->getMeshOffset(id);
collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z)); collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z));
collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z)); collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z));
//work.add([&]() { work.add([=, &globalMeshes]() {
// assume static mesh for now // assume static mesh for now
Array<Vector4> positions(mesh->mNumVertices); Array<Vector4> positions(mesh->mNumVertices);
StaticArray<Array<Vector2>, MAX_TEXCOORDS> texCoords; StaticArray<Array<Vector2>, MAX_TEXCOORDS> texCoords;
@@ -475,16 +475,15 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
// collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f)); // collider.physicsMesh.addCollider(positions, indices, Matrix4(1.0f));
globalMeshes[meshIndex] = new Mesh();
globalMeshes[meshIndex]->vertexData = vertexData; globalMeshes[meshIndex]->vertexData = vertexData;
globalMeshes[meshIndex]->id = id; globalMeshes[meshIndex]->id = id;
globalMeshes[meshIndex]->referencedMaterial = materials[mesh->mMaterialIndex]; globalMeshes[meshIndex]->referencedMaterial = materials[mesh->mMaterialIndex];
globalMeshes[meshIndex]->meshlets = std::move(meshlets); globalMeshes[meshIndex]->meshlets = std::move(meshlets);
globalMeshes[meshIndex]->indices = std::move(indices); globalMeshes[meshIndex]->indices = std::move(indices);
globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices; globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices;
//}); });
} }
//getThreadPool().runAndWait(std::move(work)); getThreadPool().runAndWait(std::move(work));
} }
Matrix4 convertMatrix(aiMatrix4x4 matrix) { Matrix4 convertMatrix(aiMatrix4x4 matrix) {
@@ -143,10 +143,6 @@ void BasePass::render() {
{ {
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), .cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -168,10 +164,6 @@ void BasePass::render() {
{ {
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT), .cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -81,10 +81,6 @@ void CachedDepthPass::render() {
{ {
.samples = viewport->getSamples(), .samples = viewport->getSamples(),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -102,10 +98,6 @@ void CachedDepthPass::render() {
{ {
.samples = viewport->getSamples(), .samples = viewport->getSamples(),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -118,8 +118,6 @@ void DepthCullingPass::render() {
query->beginQuery(); query->beginQuery();
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
if (useDepthCulling) {
Array<Gfx::ORenderCommand> commands; Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass"); Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("DepthPass");
@@ -152,10 +150,6 @@ void DepthCullingPass::render() {
{ {
.samples = viewport->getSamples(), .samples = viewport->getSamples(),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -173,10 +167,6 @@ void DepthCullingPass::render() {
{ {
.samples = viewport->getSamples(), .samples = viewport->getSamples(),
}, },
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -187,8 +177,8 @@ void DepthCullingPass::render() {
} }
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set}); command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), set});
uint32 offset = 0; uint32 offset = 0;
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VertexData::DrawCallOffsets),
sizeof(VertexData::DrawCallOffsets), &offset); &offset);
if (graphics->supportMeshShading()) { if (graphics->supportMeshShading()) {
command->drawMesh(vertexData->getNumInstances(), 1, 1); command->drawMesh(vertexData->getNumInstances(), 1, 1);
} else { } else {
@@ -212,7 +202,6 @@ void DepthCullingPass::render() {
} }
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
}
graphics->endRenderPass(); graphics->endRenderPass();
query->endQuery(); query->endQuery();
// Sync depth read/write with compute read // Sync depth read/write with compute read
@@ -9,16 +9,6 @@
namespace Seele { namespace Seele {
class StaticMeshVertexData : public VertexData { class StaticMeshVertexData : public VertexData {
public: public:
struct StaticMatInstance {
PMaterialInstance instance;
Array<uint32> meshletIds;
Gfx::OShaderBuffer culledMeshletBuffer;
// Gfx::OShaderBuffer indirectDrawBuffer;
};
struct StaticMatData {
PMaterial material;
Array<StaticMatInstance> staticInstance;
};
StaticMeshVertexData(); StaticMeshVertexData();
virtual ~StaticMeshVertexData(); virtual ~StaticMeshVertexData();
static StaticMeshVertexData* getInstance(); static StaticMeshVertexData* getInstance();
@@ -37,12 +27,10 @@ class StaticMeshVertexData : public VertexData {
virtual Gfx::PDescriptorSet getVertexDataSet() override; virtual Gfx::PDescriptorSet getVertexDataSet() override;
virtual std::string getTypeName() const override { return "StaticMeshVertexData"; } virtual std::string getTypeName() const override { return "StaticMeshVertexData"; }
virtual Gfx::PShaderBuffer getPositionBuffer() const override { return positions; } virtual Gfx::PShaderBuffer getPositionBuffer() const override { return positions; }
constexpr const Array<StaticMatData>& getStaticMeshes() const { return staticData; }
private: private:
virtual void resizeBuffers() override; virtual void resizeBuffers() override;
virtual void updateBuffers() override; virtual void updateBuffers() override;
Array<StaticMatData> staticData;
Gfx::OShaderBuffer positions; Gfx::OShaderBuffer positions;
Array<Vector4> positionData; Array<Vector4> positionData;
+11 -3
View File
@@ -184,10 +184,14 @@ Buffer::~Buffer() {
} }
void Buffer::updateContents(uint64 regionOffset, uint64 regionSize, void* buffer) { void Buffer::updateContents(uint64 regionOffset, uint64 regionSize, void* buffer) {
if (buffers.size() == 0)
return;
getAlloc()->updateContents(regionOffset, regionSize, buffer); getAlloc()->updateContents(regionOffset, regionSize, buffer);
} }
void Buffer::readContents(uint64 regionOffset, uint64 regionSize, void* buffer) { void Buffer::readContents(uint64 regionOffset, uint64 regionSize, void* buffer) {
if (buffers.size() == 0)
return;
getAlloc()->readContents(regionOffset, regionSize, buffer); getAlloc()->readContents(regionOffset, regionSize, buffer);
} }
@@ -218,7 +222,6 @@ void Buffer::rotateBuffer(uint64 size, bool preserveContents) {
} }
void Buffer::createBuffer(uint64 size, uint32 destIndex) { void Buffer::createBuffer(uint64 size, uint32 destIndex) {
if (size > 0) {
uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner); uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner);
VkBufferCreateInfo info = { VkBufferCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -241,7 +244,6 @@ void Buffer::createBuffer(uint64 size, uint32 destIndex) {
pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
} }
}
} }
void Buffer::copyBuffer(uint64 src, uint64 dst) { void Buffer::copyBuffer(uint64 src, uint64 dst) {
@@ -283,10 +285,16 @@ void Buffer::copyBuffer(uint64 src, uint64 dst) {
&dstBarrier, 0, nullptr); &dstBarrier, 0, nullptr);
} }
void Buffer::transferOwnership(Gfx::QueueType newOwner) { getAlloc()->transferOwnership(newOwner); } void Buffer::transferOwnership(Gfx::QueueType newOwner) {
if (buffers.size() == 0)
return;
getAlloc()->transferOwnership(newOwner);
}
void Buffer::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void Buffer::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
if (buffers.size() == 0)
return;
getAlloc()->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); getAlloc()->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }