Caching descriptor set updates

This commit is contained in:
Dynamitos
2024-05-29 10:40:35 +02:00
parent e0961bce24
commit 4b6022237b
15 changed files with 405 additions and 315 deletions
+1 -1
+4 -4
View File
@@ -15,10 +15,10 @@ void computeFrustums(ComputeShaderInput in)
{ {
float3 origin = float3(0, 0, 0); float3 origin = float3(0, 0, 0);
float3 corners[4] = { float3 corners[4] = {
screenToView(float4(float2(in.dispatchThreadID.x + 0, in.dispatchThreadID.y + 0) * BLOCK_SIZE, -1.0f, 1.0f)).xyz, screenToWorld(float4(float2(in.dispatchThreadID.x + 0, in.dispatchThreadID.y + 0) * BLOCK_SIZE, -1.0f, 1.0f)).xyz,
screenToView(float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 0) * BLOCK_SIZE, -1.0f, 1.0f)).xyz, screenToWorld(float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 0) * BLOCK_SIZE, -1.0f, 1.0f)).xyz,
screenToView(float4(float2(in.dispatchThreadID.x + 0, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f)).xyz, screenToWorld(float4(float2(in.dispatchThreadID.x + 0, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f)).xyz,
screenToView(float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f)).xyz screenToWorld(float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f)).xyz
}; };
Frustum frustum; Frustum frustum;
frustum.sides[0] = computePlane(origin, corners[2], corners[0]); frustum.sides[0] = computePlane(origin, corners[2], corners[0]);
+10 -9
View File
@@ -29,7 +29,6 @@ groupshared uint uMinDepth;
groupshared uint uMaxDepth; groupshared uint uMaxDepth;
groupshared Frustum groupFrustum; groupshared Frustum groupFrustum;
groupshared float4x4 viewMatrix;
groupshared uint oLightCount; groupshared uint oLightCount;
groupshared uint oLightIndexStartOffset; groupshared uint oLightIndexStartOffset;
@@ -70,7 +69,6 @@ void cullLights(ComputeShaderInput in)
uint uDepth = asuint(fDepth); uint uDepth = asuint(fDepth);
if(in.groupIndex == 0) if(in.groupIndex == 0)
{ {
viewMatrix = pViewParams.viewMatrix;
uMinDepth = 0xffffffff; uMinDepth = 0xffffffff;
uMaxDepth = 0x0; uMaxDepth = 0x0;
oLightCount = 0; oLightCount = 0;
@@ -88,20 +86,23 @@ void cullLights(ComputeShaderInput in)
float fMinDepth = asfloat(uMinDepth); float fMinDepth = asfloat(uMinDepth);
float fMaxDepth = asfloat(uMaxDepth); float fMaxDepth = asfloat(uMaxDepth);
float minDepthVS = clipToView(float4(0, 0, fMinDepth, 1)).z; float minDepthWS = clipToWorld(float4(0, 0, fMinDepth, 1)).z;
float maxDepthVS = clipToView(float4(0, 0, fMaxDepth, 1)).z; float maxDepthWS = clipToWorld(float4(0, 0, fMaxDepth, 1)).z;
float nearClipVS = clipToView(float4(0, 0, 0, 1)).z; float nearClipWS = clipToWorld(float4(0, 0, 0, 1)).z;
Plane minPlane = {float3(0, 0, -1), -minDepthVS}; Plane minPlane = {float3(0, 0, -1), -minDepthWS};
for ( uint i = in.groupIndex; i < pLightEnv.numPointLights; i += BLOCK_SIZE * BLOCK_SIZE ) for ( uint i = in.groupIndex; i < pLightEnv.numPointLights; i += BLOCK_SIZE * BLOCK_SIZE )
{ {
PointLight light = pLightEnv.pointLights[i]; PointLight light = pLightEnv.pointLights[i];
float3 light_VS = mul(viewMatrix, float4(light.position_WS.xyz, 1.0f)).xyz; #ifdef LIGHT_CULLING
//if(light.insideFrustum(groupFrustum, light_VS, nearClipVS, maxDepthVS)) if(light.insideFrustum(groupFrustum, light.getPosition(), nearClipWS, maxDepthWS))
#endif
{ {
tAppendLight(i); tAppendLight(i);
//if(!light.insidePlane(minPlane, light_VS)) #ifdef LIGHT_CULLING
if(!light.insidePlane(minPlane, light.getPosition()))
#endif
{ {
oAppendLight(i); oAppendLight(i);
} }
+7
View File
@@ -48,6 +48,13 @@ float4 clipToView(float4 clip)
return view; return view;
} }
float4 clipToWorld(float4 clip)
{
float4 view = clipToView(clip);
return viewToWorld(view);
}
float4 screenToView(float4 screen) float4 screenToView(float4 screen)
{ {
float2 texCoord = screen.xy / pViewParams.screenDimensions; float2 texCoord = screen.xy / pViewParams.screenDimensions;
+4
View File
@@ -52,6 +52,10 @@ struct PointLight : ILightEnv
} }
return result; return result;
} }
float3 getPosition()
{
return position_WS.xyz;
}
}; };
struct LightEnv struct LightEnv
+4
View File
@@ -58,6 +58,10 @@ int main() {
AssetImporter::importMesh(MeshImportArgs{ AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import/models/cube.fbx", .filePath = sourcePath / "import/models/cube.fbx",
}); });
//AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import/models/greek-temple/source/greek-temple.fbx",
// .importPath = "temple"
// });
AssetImporter::importMesh(MeshImportArgs{ AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.fbx", .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.fbx",
.importPath = "Whitechapel" .importPath = "Whitechapel"
@@ -8,6 +8,8 @@
using namespace Seele; using namespace Seele;
extern bool useLightCulling;
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene)
: RenderPass(graphics, scene) : RenderPass(graphics, scene)
{ {
@@ -63,7 +65,14 @@ void LightCullingPass::render()
cullingDescriptorSet->updateTexture(6, Gfx::PTexture2D(tLightGrid)); cullingDescriptorSet->updateTexture(6, Gfx::PTexture2D(tLightGrid));
cullingDescriptorSet->writeChanges(); cullingDescriptorSet->writeChanges();
Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand"); Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand");
if (useLightCulling)
{
computeCommand->bindPipeline(cullingEnabledPipeline);
}
else
{
computeCommand->bindPipeline(cullingPipeline); computeCommand->bindPipeline(cullingPipeline);
}
computeCommand->bindDescriptor({ viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet() }); computeCommand->bindDescriptor({ viewParamsSet, dispatchParamsSet, cullingDescriptorSet, lightEnv->getDescriptorSet() });
computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z); computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
Array<Gfx::OComputeCommand> commands; Array<Gfx::OComputeCommand> commands;
@@ -120,6 +129,7 @@ void LightCullingPass::publishOutputs()
lightEnv = scene->getLightEnvironment(); lightEnv = scene->getLightEnvironment();
{
cullingLayout = graphics->createPipelineLayout("CullingLayout"); cullingLayout = graphics->createPipelineLayout("CullingLayout");
cullingLayout->addDescriptorLayout(viewParamsLayout); cullingLayout->addDescriptorLayout(viewParamsLayout);
cullingLayout->addDescriptorLayout(dispatchParamsLayout); cullingLayout->addDescriptorLayout(dispatchParamsLayout);
@@ -139,6 +149,30 @@ void LightCullingPass::publishOutputs()
pipelineInfo.computeShader = cullingShader; pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = std::move(cullingLayout); pipelineInfo.pipelineLayout = std::move(cullingLayout);
cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo)); cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
{
cullingEnableLayout = graphics->createPipelineLayout("CullingEnabledLayout");
cullingEnableLayout->addDescriptorLayout(viewParamsLayout);
cullingEnableLayout->addDescriptorLayout(dispatchParamsLayout);
cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout);
cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
ShaderCreateInfo createInfo = {
.name = "Culling",
.mainModule = "LightCulling",
.entryPoint = "cullLights",
.rootSignature = cullingEnableLayout,
};
createInfo.defines["LIGHT_CULLING"] = "1";
cullingEnabledShader = graphics->createComputeShader(createInfo);
cullingEnableLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = std::move(cullingEnableLayout);
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
uint32 counterReset = 0; uint32 counterReset = 0;
ShaderBufferCreateInfo structInfo = { ShaderBufferCreateInfo structInfo = {
@@ -60,9 +60,12 @@ private:
Gfx::OTexture2D tLightGrid; Gfx::OTexture2D tLightGrid;
Gfx::PDescriptorSet cullingDescriptorSet; Gfx::PDescriptorSet cullingDescriptorSet;
Gfx::ODescriptorLayout cullingDescriptorLayout; Gfx::ODescriptorLayout cullingDescriptorLayout;
Gfx::OComputeShader cullingShader;
Gfx::PComputePipeline cullingPipeline;
Gfx::OPipelineLayout cullingLayout; Gfx::OPipelineLayout cullingLayout;
Gfx::OPipelineLayout cullingEnableLayout;
Gfx::OComputeShader cullingShader;
Gfx::OComputeShader cullingEnabledShader;
Gfx::PComputePipeline cullingPipeline;
Gfx::PComputePipeline cullingEnabledPipeline;
}; };
DEFINE_REF(LightCullingPass) DEFINE_REF(LightCullingPass)
} // namespace Seele } // namespace Seele
+28 -1
View File
@@ -185,6 +185,11 @@ DescriptorSet::~DescriptorSet()
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) { void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) {
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>(); PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
if (boundResources[binding] == vulkanBuffer->getAlloc())
{
return;
}
bufferInfos.add(VkDescriptorBufferInfo{ bufferInfos.add(VkDescriptorBufferInfo{
.buffer = vulkanBuffer->getHandle(), .buffer = vulkanBuffer->getHandle(),
.offset = 0, .offset = 0,
@@ -207,6 +212,10 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBu
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) { void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) {
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>(); PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
if (boundResources[binding] == vulkanBuffer->getAlloc())
{
return;
}
bufferInfos.add(VkDescriptorBufferInfo{ bufferInfos.add(VkDescriptorBufferInfo{
.buffer = vulkanBuffer->getHandle(), .buffer = vulkanBuffer->getHandle(),
@@ -229,6 +238,11 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuff
void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) { void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) {
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>(); PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
if (boundResources[binding] == vulkanBuffer->getAlloc())
{
return;
}
bufferInfos.add(VkDescriptorBufferInfo{ bufferInfos.add(VkDescriptorBufferInfo{
.buffer = vulkanBuffer->getHandle(), .buffer = vulkanBuffer->getHandle(),
.offset = 0, .offset = 0,
@@ -251,6 +265,10 @@ void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuf
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) { void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) {
PSampler vulkanSampler = samplerState.cast<Sampler>(); PSampler vulkanSampler = samplerState.cast<Sampler>();
if (boundResources[binding] == vulkanSampler->getHandle())
{
return;
}
imageInfos.add(VkDescriptorImageInfo{ imageInfos.add(VkDescriptorImageInfo{
.sampler = vulkanSampler->getSampler(), .sampler = vulkanSampler->getSampler(),
@@ -274,6 +292,10 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState)
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) { void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) {
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle(); TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
if (boundResources[binding] == vulkanTexture->getHandle())
{
return;
}
// It is assumed that the image is in the correct layout // It is assumed that the image is in the correct layout
imageInfos.add(VkDescriptorImageInfo{ imageInfos.add(VkDescriptorImageInfo{
@@ -284,7 +306,8 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
if (samplerState != nullptr) { if (samplerState != nullptr) {
descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
} else if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) { }
else if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) {
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
} }
writeDescriptors.add(VkWriteDescriptorSet{ writeDescriptors.add(VkWriteDescriptorSet{
@@ -306,6 +329,10 @@ void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> te
boundResources.resize(binding + textures.size()); boundResources.resize(binding + textures.size());
for (auto& gfxTexture : textures) { for (auto& gfxTexture : textures) {
TextureBase* vulkanTexture = gfxTexture.cast<TextureBase>().getHandle(); TextureBase* vulkanTexture = gfxTexture.cast<TextureBase>().getHandle();
if (boundResources[binding + arrayElement] == vulkanTexture->getHandle())
{
continue;
}
imageInfos.add(VkDescriptorImageInfo{ imageInfos.add(VkDescriptorImageInfo{
.sampler = VK_NULL_HANDLE, .sampler = VK_NULL_HANDLE,
.imageView = vulkanTexture->getView(), .imageView = vulkanTexture->getView(),
+1 -1
View File
@@ -114,7 +114,7 @@ void Window::pollInput()
void Window::beginFrame() void Window::beginFrame()
{ {
imageAvailableFences[currentSemaphoreIndex]->wait(100000000); imageAvailableFences[currentSemaphoreIndex]->wait(10000000000);
imageAvailableFences[currentSemaphoreIndex]->reset(); imageAvailableFences[currentSemaphoreIndex]->reset();
vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), &currentImageIndex); vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), imageAvailableFences[currentSemaphoreIndex]->getHandle(), &currentImageIndex);
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]); graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, imageAvailableSemaphores[currentSemaphoreIndex]);
+1 -1
View File
@@ -28,7 +28,7 @@ Slang::ComPtr<slang::IBlob> Seele::generateShader(const ShaderCreateInfo& create
option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE; option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE;
option[3].name = slang::CompilerOptionName::DebugInformationFormat; option[3].name = slang::CompilerOptionName::DebugInformationFormat;
option[3].value.kind = slang::CompilerOptionValueKind::Int; option[3].value.kind = slang::CompilerOptionValueKind::Int;
option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB; option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_DEFAULT;
sessionDesc.compilerOptionEntries = option.data(); sessionDesc.compilerOptionEntries = option.data();
sessionDesc.compilerOptionEntryCount = option.size(); sessionDesc.compilerOptionEntryCount = option.size();
+10
View File
@@ -104,6 +104,16 @@ public:
return object <=> rhs.object; return object <=> rhs.object;
} }
template<typename F> template<typename F>
constexpr bool operator==(const RefPtr<F>& rhs) const noexcept
{
return object == rhs.getHandle();
}
template<typename F>
constexpr auto operator<=>(const RefPtr<F>& rhs) const noexcept
{
return object <=> rhs.getHandle();
}
template<typename F>
constexpr operator RefPtr<F>() constexpr operator RefPtr<F>()
{ {
return RefPtr<F>(static_cast<F*>(object)); return RefPtr<F>(static_cast<F*>(object));
+7 -7
View File
@@ -14,6 +14,7 @@ using namespace Seele;
bool usePositionOnly = false; bool usePositionOnly = false;
bool useViewCulling = false; bool useViewCulling = false;
bool useLightCulling = false;
GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo, std::string dllPath) GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo, std::string dllPath)
: View(graphics, window, createInfo, "Game") : View(graphics, window, createInfo, "Game")
@@ -103,19 +104,18 @@ void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifie
keyboardSystem->keyCallback(code, action, modifier); keyboardSystem->keyCallback(code, action, modifier);
if (code == KeyCode::KEY_P && action == InputAction::RELEASE) if (code == KeyCode::KEY_P && action == InputAction::RELEASE)
{ {
usePositionOnly = true; usePositionOnly = !usePositionOnly;
std::cout << "Use Pos only " << usePositionOnly << std::endl;
} }
if (code == KeyCode::KEY_O && action == InputAction::RELEASE) if (code == KeyCode::KEY_O && action == InputAction::RELEASE)
{ {
usePositionOnly = false; useViewCulling = !useViewCulling;
std::cout << "Use View Culling " << useViewCulling << std::endl;
} }
if (code == KeyCode::KEY_L && action == InputAction::RELEASE) if (code == KeyCode::KEY_L && action == InputAction::RELEASE)
{ {
useViewCulling = true; useLightCulling = !useLightCulling;
} std::cout << "Use Light Culling " << useLightCulling << std::endl;
if (code == KeyCode::KEY_K && action == InputAction::RELEASE)
{
useViewCulling = false;
} }
} }