View Frustum culling for mesh shading
This commit is contained in:
+7
-4
@@ -39,15 +39,18 @@
|
|||||||
<Item Name="[value]">value</Item>
|
<Item Name="[value]">value</Item>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
<Type Name="Seele::Map<*,*>">
|
<Type Name="Seele::Map<*>">
|
||||||
<DisplayString>{{ size={_size} }</DisplayString>
|
<DisplayString>{{ size={_size} }</DisplayString>
|
||||||
<Expand>
|
<Expand>
|
||||||
<Item Name="[size]">_size</Item>
|
<Item Name="[size]">_size</Item>
|
||||||
<Item Name="[comp]">comp</Item>
|
<Item Name="[comp]">comp</Item>
|
||||||
<ArrayItems>
|
<TreeItems>
|
||||||
<Size>_size</Size>
|
<Size>_size</Size>
|
||||||
<ValuePointer>nodeContainer._data</ValuePointer>
|
<HeadPointer>root</HeadPointer>
|
||||||
</ArrayItems>
|
<LeftPointer>left</LeftPointer>
|
||||||
|
<RightPointer>right</RightPointer>
|
||||||
|
<ValueNode Condition="!((bool)_Isnil)">pair</ValueNode>
|
||||||
|
</TreeItems>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
<Type Name="Seele::Map<*>::Node">
|
<Type Name="Seele::Map<*>::Node">
|
||||||
|
|||||||
Vendored
+1
-1
Submodule external/vcpkg updated: 5c7c15b964...50bffcc62d
@@ -18,8 +18,8 @@ ParameterBlock<LightCullingData> pLightCullingData;
|
|||||||
float4 fragmentMain(in FragmentParameter params) : SV_Target
|
float4 fragmentMain(in FragmentParameter params) : SV_Target
|
||||||
{
|
{
|
||||||
LightingParameter lightingParams = params.getLightingParameter();
|
LightingParameter lightingParams = params.getLightingParameter();
|
||||||
|
MaterialParameter materialParams = params.getMaterialParameter();
|
||||||
let brdf = pMaterial.prepare(params.getMaterialParameter());
|
let brdf = pMaterial.prepare(materialParams);
|
||||||
float3 result = float3(0, 0, 0);
|
float3 result = float3(0, 0, 0);
|
||||||
for(int i = 0; i < pLightEnv.numDirectionalLights; ++i)
|
for(int i = 0; i < pLightEnv.numDirectionalLights; ++i)
|
||||||
{
|
{
|
||||||
@@ -29,5 +29,5 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
|
|||||||
{
|
{
|
||||||
result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
|
result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
|
||||||
}
|
}
|
||||||
return float4(result, 1.0f);
|
return float4(materialParams.vertexColor, 1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,19 +29,19 @@ void taskMain(
|
|||||||
localToClip = mul(pViewParams.projectionMatrix, mul(pViewParams.viewMatrix, instance.transformMatrix));
|
localToClip = mul(pViewParams.projectionMatrix, mul(pViewParams.viewMatrix, instance.transformMatrix));
|
||||||
// Left
|
// Left
|
||||||
viewFrustum.sides[0].n = float3(1, 0, 0);
|
viewFrustum.sides[0].n = float3(1, 0, 0);
|
||||||
viewFrustum.sides[0].d = -0.8;
|
viewFrustum.sides[0].d = 0.7;
|
||||||
// Right
|
// Right
|
||||||
viewFrustum.sides[1].n = float3(-1, 0, 0);
|
viewFrustum.sides[1].n = float3(-1, 0, 0);
|
||||||
viewFrustum.sides[1].d = 0.8;
|
viewFrustum.sides[1].d = 0.7;
|
||||||
// Top
|
// Top
|
||||||
viewFrustum.sides[2].n = float3(0, -1, 0);
|
viewFrustum.sides[2].n = float3(0, -1, 0);
|
||||||
viewFrustum.sides[2].d = 0.8;
|
viewFrustum.sides[2].d = 0.7;
|
||||||
// Bottom
|
// Bottom
|
||||||
viewFrustum.sides[1].n = float3(0, 1, 0);
|
viewFrustum.sides[3].n = float3(0, 1, 0);
|
||||||
viewFrustum.sides[1].d = -0.8;
|
viewFrustum.sides[3].d = 0.7;
|
||||||
// Base
|
// Base
|
||||||
viewFrustum.basePlane.n = float3(0, 0, 1);
|
viewFrustum.basePlane.n = float3(0, 0, 1);
|
||||||
viewFrustum.basePlane.d = 0;
|
viewFrustum.basePlane.d = 0.2;
|
||||||
}
|
}
|
||||||
GroupMemoryBarrierWithGroupSync();
|
GroupMemoryBarrierWithGroupSync();
|
||||||
MeshData mesh = pScene.meshData[groupID];
|
MeshData mesh = pScene.meshData[groupID];
|
||||||
@@ -51,7 +51,7 @@ void taskMain(
|
|||||||
{
|
{
|
||||||
uint m = mesh.meshletOffset + i;
|
uint m = mesh.meshletOffset + i;
|
||||||
MeshletDescription meshlet = pScene.meshletInfos[m];
|
MeshletDescription meshlet = pScene.meshletInfos[m];
|
||||||
//if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum))
|
if(meshlet.boundingBox.insideFrustum(localToClip, viewFrustum))
|
||||||
{
|
{
|
||||||
uint index;
|
uint index;
|
||||||
InterlockedAdd(head, 1, index);
|
InterlockedAdd(head, 1, index);
|
||||||
@@ -119,7 +119,9 @@ void meshMain(
|
|||||||
uint v = min(i, m.vertexCount - 1);
|
uint v = min(i, m.vertexCount - 1);
|
||||||
{
|
{
|
||||||
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
|
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
|
||||||
vertices[v] = pVertexData.getAttributes(md.indicesOffset + vertexIndex).getParameter(inst.transformMatrix);
|
VertexAttributes attr = pVertexData.getAttributes(md.indicesOffset + vertexIndex);
|
||||||
|
attr.vertexColor = m.color;
|
||||||
|
vertices[v] = attr.getParameter(inst.transformMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+10
-10
@@ -8,18 +8,18 @@ struct AABB
|
|||||||
float pad1;
|
float pad1;
|
||||||
bool insideFrustum(float4x4 transform, Frustum frustum)
|
bool insideFrustum(float4x4 transform, Frustum frustum)
|
||||||
{
|
{
|
||||||
float3 corners[8];
|
float4 corners[8];
|
||||||
corners[0] = mul(transform, float4(min.x, min.y, min.z, 1.0f)).xyz;
|
corners[0] = mul(transform, float4(min.x, min.y, min.z, 1.0f));
|
||||||
corners[1] = mul(transform, float4(min.x, min.y, max.z, 1.0f)).xyz;
|
corners[1] = mul(transform, float4(min.x, min.y, max.z, 1.0f));
|
||||||
corners[2] = mul(transform, float4(min.x, max.y, min.z, 1.0f)).xyz;
|
corners[2] = mul(transform, float4(min.x, max.y, min.z, 1.0f));
|
||||||
corners[3] = mul(transform, float4(min.x, max.y, max.z, 1.0f)).xyz;
|
corners[3] = mul(transform, float4(min.x, max.y, max.z, 1.0f));
|
||||||
corners[4] = mul(transform, float4(max.x, min.y, min.z, 1.0f)).xyz;
|
corners[4] = mul(transform, float4(max.x, min.y, min.z, 1.0f));
|
||||||
corners[5] = mul(transform, float4(max.x, min.y, max.z, 1.0f)).xyz;
|
corners[5] = mul(transform, float4(max.x, min.y, max.z, 1.0f));
|
||||||
corners[6] = mul(transform, float4(max.x, max.y, min.z, 1.0f)).xyz;
|
corners[6] = mul(transform, float4(max.x, max.y, min.z, 1.0f));
|
||||||
corners[7] = mul(transform, float4(max.x, max.y, max.z, 1.0f)).xyz;
|
corners[7] = mul(transform, float4(max.x, max.y, max.z, 1.0f));
|
||||||
for(int i = 0; i < 8; ++i)
|
for(int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
if(frustum.pointInside(corners[i]))
|
if(frustum.pointInside(corners[i].xyz / corners[i].w))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,13 @@ struct Frustum
|
|||||||
Plane basePlane;
|
Plane basePlane;
|
||||||
bool pointInside(float3 point)
|
bool pointInside(float3 point)
|
||||||
{
|
{
|
||||||
float result = dot(basePlane.n, point) + basePlane.d;
|
if (dot(basePlane.n, point) + basePlane.d < 0.0f)
|
||||||
if (0.0f > result)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(int p = 0; p < 4; ++p)
|
for(int p = 0; p < 4; ++p)
|
||||||
{
|
{
|
||||||
result = dot(sides[p].n, point) + sides[p].d;
|
if(dot(sides[p].n, point) + sides[p].d < 0.0f)
|
||||||
if(0.0f > result)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,13 @@ struct MeshletDescription
|
|||||||
uint32_t primitiveCount;
|
uint32_t primitiveCount;
|
||||||
uint32_t vertexOffset;
|
uint32_t vertexOffset;
|
||||||
uint32_t primitiveOffset;
|
uint32_t primitiveOffset;
|
||||||
|
float3 color;
|
||||||
|
float pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshData
|
struct MeshData
|
||||||
{
|
{
|
||||||
|
AABB boundingBox;
|
||||||
uint32_t numMeshlets;
|
uint32_t numMeshlets;
|
||||||
uint32_t meshletOffset;
|
uint32_t meshletOffset;
|
||||||
uint32_t firstIndex;
|
uint32_t firstIndex;
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ void MeshLoader::import(MeshImportArgs args, PMeshAsset meshAsset)
|
|||||||
meshAsset->setStatus(Asset::Status::Loading);
|
meshAsset->setStatus(Asset::Status::Loading);
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
importer.ReadFile(args.filePath.string().c_str(), (uint32)(
|
importer.ReadFile(args.filePath.string().c_str(), (uint32)(
|
||||||
|
aiProcess_ImproveCacheLocality |
|
||||||
aiProcess_FlipUVs |
|
aiProcess_FlipUVs |
|
||||||
aiProcess_Triangulate |
|
aiProcess_Triangulate |
|
||||||
aiProcess_SortByPType |
|
aiProcess_SortByPType |
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Camera::Camera()
|
|||||||
, bNeedsViewBuild(false)
|
, bNeedsViewBuild(false)
|
||||||
, cameraPos(Vector())
|
, cameraPos(Vector())
|
||||||
{
|
{
|
||||||
yaw = 3.1415f/2;
|
yaw = -3.1415f/2;
|
||||||
pitch = 0;
|
pitch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ typedef uint32 KeyModifierFlags;
|
|||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
static constexpr bool useAsyncCompute = true;
|
static constexpr bool useAsyncCompute = true;
|
||||||
static constexpr bool waitIdleOnSubmit = true;
|
static constexpr bool waitIdleOnSubmit = false;
|
||||||
static constexpr bool useMeshShading = true;
|
static constexpr bool useMeshShading = true;
|
||||||
static constexpr uint32 numFramesBuffered = 3;
|
static constexpr uint32 numFramesBuffered = 3;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ void VertexData::updateMesh(PMesh mesh, Component::Transform& transform)
|
|||||||
.instance = InstanceData {
|
.instance = InstanceData {
|
||||||
.transformMatrix = transform.toMatrix(),
|
.transformMatrix = transform.toMatrix(),
|
||||||
},
|
},
|
||||||
.data = data
|
.data = data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
|
matInstanceData.materialInstance = mesh->referencedMaterial->getHandle();
|
||||||
@@ -109,10 +109,12 @@ void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet>
|
|||||||
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
||||||
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
||||||
meshlets.add(MeshletDescription{
|
meshlets.add(MeshletDescription{
|
||||||
|
.boundingBox = m.boundingBox,
|
||||||
.vertexCount = m.numVertices,
|
.vertexCount = m.numVertices,
|
||||||
.primitiveCount = m.numPrimitives,
|
.primitiveCount = m.numPrimitives,
|
||||||
.vertexOffset = vertexOffset,
|
.vertexOffset = vertexOffset,
|
||||||
.primitiveOffset = primitiveOffset,
|
.primitiveOffset = primitiveOffset,
|
||||||
|
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
meshData[id].add(MeshData{
|
meshData[id].add(MeshData{
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ protected:
|
|||||||
uint32_t primitiveCount;
|
uint32_t primitiveCount;
|
||||||
uint32_t vertexOffset;
|
uint32_t vertexOffset;
|
||||||
uint32_t primitiveOffset;
|
uint32_t primitiveOffset;
|
||||||
|
Vector color;
|
||||||
|
float pad0;
|
||||||
};
|
};
|
||||||
Map<std::string, MaterialData> materialData;
|
Map<std::string, MaterialData> materialData;
|
||||||
Map<MeshId, Array<MeshData>> meshData;
|
Map<MeshId, Array<MeshData>> meshData;
|
||||||
|
|||||||
@@ -216,23 +216,35 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
|||||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Allocator::free(PAllocation allocation)
|
void Allocator::free()
|
||||||
{
|
{
|
||||||
//std::cout << "Freeing allocation" << std::endl;
|
|
||||||
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
||||||
{
|
{
|
||||||
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
||||||
{
|
{
|
||||||
if (heaps[heapIndex].allocations[alloc] == allocation)
|
if (heaps[heapIndex].allocations[alloc]->bytesUsed == 0)
|
||||||
{
|
{
|
||||||
heaps[heapIndex].inUse -= allocation->bytesAllocated;
|
heaps[heapIndex].inUse -= heaps[heapIndex].allocations[alloc]->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.removeAt(alloc, false);
|
heaps[heapIndex].allocations.removeAt(alloc, false);
|
||||||
return;
|
alloc--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Allocator::print()
|
||||||
|
{
|
||||||
|
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
||||||
|
{
|
||||||
|
std::cout << "Heap " << heapIndex << std::endl;
|
||||||
|
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
||||||
|
{
|
||||||
|
std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ public:
|
|||||||
return allocate(requirements, props, &allocInfo);
|
return allocate(requirements, props, &allocInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(PAllocation allocation);
|
void free();
|
||||||
|
void print();
|
||||||
private:
|
private:
|
||||||
static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
|
static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
|
||||||
struct HeapInfo
|
struct HeapInfo
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ void Graphics::pickPhysicalDevice()
|
|||||||
{
|
{
|
||||||
if (std::strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extensionProps[i].extensionName) == 0)
|
if (std::strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extensionProps[i].extensionName) == 0)
|
||||||
{
|
{
|
||||||
//meshShadingEnabled = true;
|
meshShadingEnabled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,4 +170,5 @@ void DestructionManager::notifyCmdComplete(PCommand cmd)
|
|||||||
sems[cmd].clear();
|
sems[cmd].clear();
|
||||||
renderPasses[cmd].clear();
|
renderPasses[cmd].clear();
|
||||||
allocs[cmd].clear();
|
allocs[cmd].clear();
|
||||||
|
//graphics->getAllocator()->free();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "System/LightGather.h"
|
#include "System/LightGather.h"
|
||||||
#include "System/MeshUpdater.h"
|
#include "System/MeshUpdater.h"
|
||||||
#include "System/CameraUpdater.h"
|
#include "System/CameraUpdater.h"
|
||||||
|
#include "Graphics/Vulkan/Graphics.h"
|
||||||
|
#include "Graphics/Vulkan/Allocator.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -96,6 +98,10 @@ void GameView::reloadGame()
|
|||||||
|
|
||||||
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier)
|
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier)
|
||||||
{
|
{
|
||||||
|
if (code == KeyCode::KEY_P && action == InputAction::PRESS)
|
||||||
|
{
|
||||||
|
((Vulkan::Graphics*)graphics.getHandle())->getAllocator()->print();
|
||||||
|
}
|
||||||
keyboardSystem->keyCallback(code, action, modifier);
|
keyboardSystem->keyCallback(code, action, modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user