Skip to content
Snippets Groups Projects
Commit 40f4700c authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#87] Add bounding sphere based meshlet culling

parent a0746f0f
No related branches found
No related tags found
1 merge request!74Resolve "Mesh Shader Implementation"
struct ObjectMatrices{
mat4 model;
mat4 mvp;
};
\ No newline at end of file
...@@ -28,5 +28,5 @@ vec3 colorFromIndex(uint i){ ...@@ -28,5 +28,5 @@ vec3 colorFromIndex(uint i){
void main() { void main() {
outColor = normalize(passNormal) * 0.5 + 0.5; outColor = normalize(passNormal) * 0.5 + 0.5;
outColor = colorFromIndex(passTaskIndex); //outColor = colorFromIndex(passTaskIndex);
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#extension GL_GOOGLE_include_directive : enable #extension GL_GOOGLE_include_directive : enable
#include "meshlet.inc" #include "meshlet.inc"
#include "common.inc"
layout(local_size_x=32) in; layout(local_size_x=32) in;
...@@ -13,31 +14,27 @@ taskNV out Task { ...@@ -13,31 +14,27 @@ taskNV out Task {
} OUT; } OUT;
layout( push_constant ) uniform constants{ layout( push_constant ) uniform constants{
uint meshletCount;
uint matrixIndex; uint matrixIndex;
uint meshletCount;
}; };
layout(std430, binding = 2) readonly buffer meshletBuffer // TODO: reuse mesh stage binding at location 2 after required fix in framework
layout(std430, binding = 5) readonly buffer meshletBuffer
{ {
Meshlet meshlets[]; Meshlet meshlets[];
}; };
struct Plane{ struct Plane{
vec3 pointOnPlane; vec3 pointOnPlane;
float padding0; float padding0;
vec3 normal; vec3 normal;
float padding1; float padding1;
}; };
layout(set=0, binding=3, std140) uniform cameraPlaneBuffer{ layout(set=0, binding=3, std140) uniform cameraPlaneBuffer{
Plane cameraPlanes[6]; Plane cameraPlanes[6];
}; };
struct ObjectMatrices{
mat4 model;
mat4 mvp;
};
layout(std430, binding = 4) readonly buffer matrixBuffer layout(std430, binding = 4) readonly buffer matrixBuffer
{ {
ObjectMatrices objectMatrices[]; ObjectMatrices objectMatrices[];
...@@ -49,7 +46,8 @@ bool isSphereInsideFrustum(vec3 spherePos, float sphereRadius, Plane cameraPlane ...@@ -49,7 +46,8 @@ bool isSphereInsideFrustum(vec3 spherePos, float sphereRadius, Plane cameraPlane
bool isInside = true; bool isInside = true;
for(int i = 0; i < 6; i++){ for(int i = 0; i < 6; i++){
Plane p = cameraPlanes[i]; Plane p = cameraPlanes[i];
isInside = isInside && dot(p.normal, spherePos - p.pointOnPlane) + sphereRadius < 0; isInside = isInside && dot(p.normal, spherePos - p.pointOnPlane) - sphereRadius < 0;
//break;
} }
return isInside; return isInside;
} }
...@@ -67,7 +65,9 @@ void main() { ...@@ -67,7 +65,9 @@ void main() {
taskCount = 0; taskCount = 0;
} }
if(isSphereInsideFrustum(meshlet.meanPosition, meshlet.boundingSphereRadius, cameraPlanes)){ // TODO: scaling support
vec3 meshletPositionWorld = (vec4(meshlet.meanPosition, 1) * objectMatrices[matrixIndex].model).xyz;
if(isSphereInsideFrustum(meshletPositionWorld, meshlet.boundingSphereRadius, cameraPlanes)){
uint outIndex = atomicAdd(taskCount, 1); uint outIndex = atomicAdd(taskCount, 1);
OUT.meshletIndices[outIndex] = gl_GlobalInvocationID.x; OUT.meshletIndices[outIndex] = gl_GlobalInvocationID.x;
} }
......
#version 450 #version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
#extension GL_GOOGLE_include_directive : enable
#include "common.inc"
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal; layout(location = 1) in vec3 inNormal;
...@@ -7,13 +10,19 @@ layout(location = 1) in vec3 inNormal; ...@@ -7,13 +10,19 @@ layout(location = 1) in vec3 inNormal;
layout(location = 0) out vec3 passNormal; layout(location = 0) out vec3 passNormal;
layout(location = 1) out uint dummyOutput; layout(location = 1) out uint dummyOutput;
layout(std430, binding = 0) readonly buffer matrixBuffer
{
ObjectMatrices objectMatrices[];
};
layout( push_constant ) uniform constants{ layout( push_constant ) uniform constants{
mat4 mvp; uint matrixIndex;
uint padding; // pad to same size as mesh shader constants uint padding; // pad to same size as mesh shader constants
}; };
void main() { void main() {
gl_Position = mvp * vec4(inPosition, 1.0); gl_Position = objectMatrices[matrixIndex].mvp * vec4(inPosition, 1.0);
passNormal = inNormal; passNormal = inNormal;
dummyOutput = padding * 0; // padding must be used, else compiler shrinks constant size dummyOutput = padding * 0; // padding must be used, else compiler shrinks constant size
......
...@@ -30,7 +30,7 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) { ...@@ -30,7 +30,7 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) {
float far; float far;
camera.getNearFar(near, far); camera.getNearFar(near, far);
glm::vec3 up = glm::dot(forward, glm::vec3(0, -1, 0)) < 0.99 ? glm::vec3(0, -1, 0) : glm::vec3(1, 0, 0); glm::vec3 up = glm::vec3(0, -1, 0);
glm::vec3 right = glm::normalize(glm::cross(forward, up)); glm::vec3 right = glm::normalize(glm::cross(forward, up));
up = glm::cross(forward, right); up = glm::cross(forward, right);
...@@ -51,25 +51,25 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) { ...@@ -51,25 +51,25 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) {
CameraPlanes cameraPlanes; CameraPlanes cameraPlanes;
// near // near
cameraPlanes.planes[0].pointOnPlane = nearCenter; cameraPlanes.planes[0].pointOnPlane = nearCenter;
cameraPlanes.planes[0].normal = -forward; cameraPlanes.planes[0].normal = -forward;
// far // far
cameraPlanes.planes[1].pointOnPlane = farCenter; cameraPlanes.planes[1].pointOnPlane = farCenter;
cameraPlanes.planes[1].normal = forward; cameraPlanes.planes[1].normal = forward;
// top // top
cameraPlanes.planes[2].pointOnPlane = nearUpCenter; cameraPlanes.planes[2].pointOnPlane = nearUpCenter;
cameraPlanes.planes[2].normal = glm::normalize(glm::cross(farUpCenter - nearUpCenter, right)); cameraPlanes.planes[2].normal = glm::normalize(glm::cross(farUpCenter - nearUpCenter, right));
// bot // bot
cameraPlanes.planes[3].pointOnPlane = nearDownCenter; cameraPlanes.planes[3].pointOnPlane = nearDownCenter;
cameraPlanes.planes[3].normal = glm::normalize(glm::cross(right, farDownCenter - nearDownCenter)); cameraPlanes.planes[3].normal = glm::normalize(glm::cross(right, farDownCenter - nearDownCenter));
// right // right
cameraPlanes.planes[4].pointOnPlane = nearRightCenter; cameraPlanes.planes[4].pointOnPlane = nearRightCenter;
cameraPlanes.planes[4].normal = glm::normalize(glm::cross(up, farRightCenter - nearRightCenter)); cameraPlanes.planes[4].normal = glm::normalize(glm::cross(up, farRightCenter - nearRightCenter));
// left // left
cameraPlanes.planes[5].pointOnPlane = nearLeftCenter; cameraPlanes.planes[5].pointOnPlane = nearLeftCenter;
cameraPlanes.planes[5].normal = glm::normalize(glm::cross(farLeftCenter - nearLeftCenter, up)); cameraPlanes.planes[5].normal = glm::normalize(glm::cross(farLeftCenter - nearLeftCenter, up));
return cameraPlanes; return cameraPlanes;
} }
...@@ -201,16 +201,29 @@ int main(int argc, const char** argv) { ...@@ -201,16 +201,29 @@ int main(int argc, const char** argv) {
} }
const vkcv::VertexLayout bunnyLayout (bindings); const vkcv::VertexLayout bunnyLayout (bindings);
vkcv::DescriptorSetHandle vertexShaderDescriptorSet = core.createDescriptorSet(bunnyShaderProgram.getReflectedDescriptors()[0]);
const vkcv::PipelineConfig bunnyPipelineDefinition { const vkcv::PipelineConfig bunnyPipelineDefinition {
bunnyShaderProgram, bunnyShaderProgram,
(uint32_t)windowWidth, (uint32_t)windowWidth,
(uint32_t)windowHeight, (uint32_t)windowHeight,
renderPass, renderPass,
{ bunnyLayout }, { bunnyLayout },
{}, { core.getDescriptorSet(vertexShaderDescriptorSet).layout },
false false
}; };
struct ObjectMatrices {
glm::mat4 model;
glm::mat4 mvp;
};
const size_t objectCount = 1;
vkcv::Buffer<ObjectMatrices> matrixBuffer = core.createBuffer<ObjectMatrices>(vkcv::BufferType::STORAGE, objectCount);
vkcv::DescriptorWrites vertexShaderDescriptorWrites;
vertexShaderDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, matrixBuffer.getHandle()) };
core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
vkcv::PipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition); vkcv::PipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
if (!bunnyPipeline) if (!bunnyPipeline)
...@@ -236,9 +249,9 @@ int main(int argc, const char** argv) { ...@@ -236,9 +249,9 @@ int main(int argc, const char** argv) {
meshShaderProgram.addShader(shaderStage, path); meshShaderProgram.addShader(shaderStage, path);
}); });
uint32_t setID = 0; uint32_t setID = 0;
vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet( meshShaderProgram.getReflectedDescriptors()[setID]); vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet( meshShaderProgram.getReflectedDescriptors()[setID]);
const vkcv::VertexLayout meshShaderLayout(bindings); const vkcv::VertexLayout meshShaderLayout(bindings);
const vkcv::PipelineConfig meshShaderPipelineDefinition{ const vkcv::PipelineConfig meshShaderPipelineDefinition{
meshShaderProgram, meshShaderProgram,
...@@ -260,19 +273,13 @@ int main(int argc, const char** argv) { ...@@ -260,19 +273,13 @@ int main(int argc, const char** argv) {
vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(vkcv::BufferType::UNIFORM, 1); vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(vkcv::BufferType::UNIFORM, 1);
struct ObjectMatrices { vkcv::DescriptorWrites meshShaderWrites;
glm::mat4 model;
glm::mat4 mvp;
};
const size_t objectCount = 1;
vkcv::Buffer<ObjectMatrices> matrixBuffer = core.createBuffer<ObjectMatrices>(vkcv::BufferType::STORAGE, objectCount);
vkcv::DescriptorWrites meshShaderWrites;
meshShaderWrites.storageBufferWrites = { meshShaderWrites.storageBufferWrites = {
vkcv::StorageBufferDescriptorWrite(0, meshShaderVertexBuffer.getHandle()), vkcv::StorageBufferDescriptorWrite(0, meshShaderVertexBuffer.getHandle()),
vkcv::StorageBufferDescriptorWrite(1, meshShaderIndexBuffer.getHandle()), vkcv::StorageBufferDescriptorWrite(1, meshShaderIndexBuffer.getHandle()),
vkcv::StorageBufferDescriptorWrite(2, meshletBuffer.getHandle()), vkcv::StorageBufferDescriptorWrite(2, meshletBuffer.getHandle()),
vkcv::StorageBufferDescriptorWrite(4, matrixBuffer.getHandle()) vkcv::StorageBufferDescriptorWrite(4, matrixBuffer.getHandle()),
vkcv::StorageBufferDescriptorWrite(5, meshletBuffer.getHandle()),
}; };
meshShaderWrites.uniformBufferWrites = { meshShaderWrites.uniformBufferWrites = {
vkcv::UniformBufferDescriptorWrite(3, cameraPlaneBuffer.getHandle()) vkcv::UniformBufferDescriptorWrite(3, cameraPlaneBuffer.getHandle())
...@@ -295,6 +302,9 @@ int main(int argc, const char** argv) { ...@@ -295,6 +302,9 @@ int main(int argc, const char** argv) {
cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -2)); cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -2));
bool useMeshShader = true;
bool updateFrustumPlanes = true;
while (window.isWindowOpen()) while (window.isWindowOpen())
{ {
vkcv::Window::pollEvents(); vkcv::Window::pollEvents();
...@@ -319,19 +329,19 @@ int main(int argc, const char** argv) { ...@@ -319,19 +329,19 @@ int main(int argc, const char** argv) {
matrixBuffer.fill({ objectMatrices }); matrixBuffer.fill({ objectMatrices });
struct PushConstants { struct PushConstants {
uint32_t meshletCount;
uint32_t matrixIndex; uint32_t matrixIndex;
uint32_t meshletCount;
}; };
PushConstants pushConstants{ meshShaderModelData.meshlets.size(), 0 }; PushConstants pushConstants{ 0, meshShaderModelData.meshlets.size() };
const CameraPlanes cameraPlanes = computeCameraPlanes(camera); if (updateFrustumPlanes) {
cameraPlaneBuffer.fill({ cameraPlanes }); const CameraPlanes cameraPlanes = computeCameraPlanes(camera);
cameraPlaneBuffer.fill({ cameraPlanes });
}
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
const bool useMeshShader = true;
vkcv::PushConstants pushConstantData(sizeof(pushConstants)); vkcv::PushConstants pushConstantData(sizeof(pushConstants));
pushConstantData.appendDrawcall(pushConstants); pushConstantData.appendDrawcall(pushConstants);
...@@ -350,26 +360,31 @@ int main(int argc, const char** argv) { ...@@ -350,26 +360,31 @@ int main(int argc, const char** argv) {
} }
else { else {
vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(vertexShaderDescriptorSet).vulkanHandle);
core.recordDrawcallsToCmdStream( core.recordDrawcallsToCmdStream(
cmdStream, cmdStream,
renderPass, renderPass,
bunnyPipeline, bunnyPipeline,
pushConstantData, pushConstantData,
{ vkcv::DrawcallInfo(renderMesh, {}) }, { vkcv::DrawcallInfo(renderMesh, { descriptorUsage }) },
{ renderTargets }); { renderTargets });
} }
core.prepareSwapchainImageForPresent(cmdStream); core.prepareSwapchainImageForPresent(cmdStream);
core.submitCommandStream(cmdStream); core.submitCommandStream(cmdStream);
// gui.beginGUI(); gui.beginGUI();
//
// ImGui::Begin("Settings"); ImGui::Begin("Settings");
// ImGui::End(); ImGui::Checkbox("Use mesh shader", &useMeshShader);
// ImGui::Checkbox("Upadte frustum culling", &updateFrustumPlanes);
// gui.endGUI();
ImGui::End();
core.endFrame();
gui.endGUI();
core.endFrame();
} }
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment