Provisional light culling

This commit is contained in:
Dynamitos
2021-05-10 23:57:55 +02:00
parent 0cf13bcff5
commit e00b382d4a
41 changed files with 1072 additions and 330 deletions
+21 -24
View File
@@ -38,7 +38,7 @@ void BasePassMeshProcessor::addMeshBatch(
assert(collection != nullptr);
for(uint32 i = 0; i < batch.elements.size(); ++i)
{
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocatedDescriptorSet();
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer);
descriptorSet->writeChanges();
cachedPrimitiveSets.add(descriptorSet);
@@ -92,14 +92,12 @@ BasePass::BasePass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics
basePassLayout = graphics->createPipelineLayout();
lightLayout = graphics->createDescriptorLayout("LightLayout");
lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformInitializer.resourceData.size = sizeof(LightEnv);
uniformInitializer.resourceData.data = nullptr;
uniformInitializer.bDynamic = true;
lightUniform = graphics->createUniformBuffer(uniformInitializer);
lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
lightLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
lightLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE);
lightLayout->create();
basePassLayout->addDescriptorLayout(INDEX_LIGHT_ENV, lightLayout);
descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocatedDescriptorSet();
descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocateDescriptorSet();
viewLayout = graphics->createDescriptorLayout("ViewLayout");
viewLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
@@ -107,14 +105,9 @@ BasePass::BasePass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics
uniformInitializer.resourceData.data = (uint8*)&viewParams;
uniformInitializer.bDynamic = true;
viewParamBuffer = graphics->createUniformBuffer(uniformInitializer);
viewLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformInitializer.resourceData.size = sizeof(ScreenToViewParameter);
uniformInitializer.resourceData.data = (uint8*)&screenToViewParams;
uniformInitializer.bDynamic = true;
screenToViewParamBuffer = graphics->createUniformBuffer(uniformInitializer);
viewLayout->create();
basePassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout);
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocatedDescriptorSet();
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout");
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
@@ -131,25 +124,16 @@ void BasePass::beginFrame()
processor->clearCommands();
primitiveLayout->reset();
BulkResourceData uniformUpdate;
uniformUpdate.size = sizeof(LightEnv);
uniformUpdate.data = (uint8*)&scene->getLightEnvironment();
lightUniform->updateContents(uniformUpdate);
descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, lightUniform);
descriptorSets[INDEX_LIGHT_ENV]->writeChanges();
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
screenToViewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
screenToViewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamBuffer->updateContents(uniformUpdate);
uniformUpdate.size = sizeof(ScreenToViewParameter);
uniformUpdate.data = (uint8*)&screenToViewParams;
screenToViewParamBuffer->updateContents(uniformUpdate);
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(1, screenToViewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->writeChanges();
for(auto &&meshBatch : scene->getStaticMeshes())
{
@@ -159,6 +143,17 @@ void BasePass::beginFrame()
void BasePass::render()
{
descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, scene->getLightBuffer());
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);
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);
descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(1, oLightIndexList);
descriptorSets[INDEX_LIGHT_ENV]->updateTexture(2, oLightGrid);
descriptorSets[INDEX_LIGHT_ENV]->writeChanges();
graphics->beginRenderPass(renderPass);
for (auto &&meshBatch : scene->getStaticMeshes())
{
@@ -184,6 +179,8 @@ void BasePass::createRenderPass()
depthAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD;
Gfx::PRenderTargetLayout layout = new Gfx::RenderTargetLayout(colorAttachment, depthAttachment);
renderPass = graphics->createRenderPass(layout);
oLightIndexList = renderGraph->requestBuffer("LIGHTCULLING_OLIGHTLIST");
oLightGrid = renderGraph->requestTexture("LIGHTCULLING_OLIGHTGRID");
}
void BasePass::modifyRenderPassMacros(Map<const char*, const char*>& defines)
+2 -2
View File
@@ -54,13 +54,13 @@ private:
Gfx::PPipelineLayout basePassLayout;
// Set 0: Light environment
static constexpr uint32 INDEX_LIGHT_ENV = 0;
Gfx::PStructuredBuffer oLightIndexList;
Gfx::PTexture oLightGrid;
Gfx::PDescriptorLayout lightLayout;
Gfx::PUniformBuffer lightUniform;
// Set 1: viewParameter
static constexpr uint32 INDEX_VIEW_PARAMS = 1;
Gfx::PDescriptorLayout viewLayout;
Gfx::PUniformBuffer viewParamBuffer;
Gfx::PUniformBuffer screenToViewParamBuffer;
// Set 2: materials, generated
static constexpr uint32 INDEX_MATERIAL = 2;
// Set 3: primitive scene data
@@ -37,7 +37,7 @@ void DepthPrepassMeshProcessor::addMeshBatch(
assert(collection != nullptr);
for(uint32 i = 0; i < batch.elements.size(); ++i)
{
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocatedDescriptorSet();
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet();
descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer);
descriptorSet->writeChanges();
cachedPrimitiveSets.add(descriptorSet);
@@ -97,14 +97,9 @@ DepthPrepass::DepthPrepass(PRenderGraph renderGraph, const PScene scene, Gfx::PG
uniformInitializer.resourceData.data = (uint8*)&viewParams;
uniformInitializer.bDynamic = true;
viewParamBuffer = graphics->createUniformBuffer(uniformInitializer);
viewLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformInitializer.resourceData.size = sizeof(ScreenToViewParameter);
uniformInitializer.resourceData.data = (uint8*)&screenToViewParams;
uniformInitializer.bDynamic = true;
screenToViewParamBuffer = graphics->createUniformBuffer(uniformInitializer);
viewLayout->create();
depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout);
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocatedDescriptorSet();
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout");
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
@@ -125,16 +120,12 @@ void DepthPrepass::beginFrame()
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
screenToViewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
screenToViewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamBuffer->updateContents(uniformUpdate);
uniformUpdate.size = sizeof(ScreenToViewParameter);
uniformUpdate.data = (uint8*)&screenToViewParams;
screenToViewParamBuffer->updateContents(uniformUpdate);
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(1, screenToViewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->writeChanges();
for(auto &&meshBatch : scene->getStaticMeshes())
{
@@ -144,6 +135,10 @@ void DepthPrepass::beginFrame()
void DepthPrepass::render()
{
depthAttachment->getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS);
graphics->beginRenderPass(renderPass);
for (auto &&meshBatch : scene->getStaticMeshes())
{
@@ -55,7 +55,6 @@ private:
static constexpr uint32 INDEX_VIEW_PARAMS = 0;
Gfx::PDescriptorLayout viewLayout;
Gfx::PUniformBuffer viewParamBuffer;
Gfx::PUniformBuffer screenToViewParamBuffer;
// Set 1: materials, generated
static constexpr uint32 INDEX_MATERIAL = 1;
// Set 2: primitive scene data
@@ -1,12 +1,15 @@
#include "LightCullingPass.h"
#include "Graphics/Graphics.h"
#include "Scene/Scene.h"
#include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h"
#include "RenderGraph.h"
using namespace Seele;
LightCullingPass::LightCullingPass(PRenderGraph renderGraph, Gfx::PViewport viewport, Gfx::PGraphics graphics, PCameraActor camera)
LightCullingPass::LightCullingPass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera)
: RenderPass(renderGraph)
, scene(scene)
, viewport(viewport)
, graphics(graphics)
, source(camera->getCameraComponent())
@@ -20,46 +23,58 @@ LightCullingPass::~LightCullingPass()
void LightCullingPass::beginFrame()
{
uint32_t viewportWidth = viewport->getSizeX();
uint32_t viewportHeight = viewport->getSizeY();
BulkResourceData uniformUpdate;
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamsBuffer->updateContents(uniformUpdate);
glm::uvec3 numThreads = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1));
dispatchParams.numThreads = numThreads;
dispatchParams.numThreadGroups = numThreadGroups;
ScreenToView screenToView;
screenToView.inverseProjection = glm::inverse(source->getProjectionMatrix());
screenToView.screenDimensions = glm::vec2(viewportWidth, viewportHeight);
frustumShader = renderDevice->createComputeShader(loadPlaintext("./_Game/shaders/ComputeFrustums.slang"), "computeFrustums");
frustumDescriptorLayout = renderDevice->createDescriptorLayout();
frustumDescriptorLayout->addDescriptorBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
frustumDescriptorLayout->addDescriptorBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
frustumDescriptorLayout->addDescriptorBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
frustumLayout = renderDevice->createPipelineLayout();
frustumLayout->addPushConstants(init::PushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, sizeof(DispatchParams), 0));
frustumLayout->addDescriptorLayout(0, frustumDescriptorLayout);
frustumLayout->create();
frustumShader->setPipelineLayout(frustumLayout);
RHIResourceCreateInfo frustumInfo;
frustumBuffer = renderDevice->createStructuredBuffer(sizeof(Frustum), sizeof(Frustum) * numThreads.x * numThreads.y * numThreads.z, BufferUsageFlags::BUF_UnorderedAccess, frustumInfo);
dispatchParamsBuffer = renderDevice->createUniformBuffer(&dispatchParams, sizeof(DispatchParams), UniformBuffer_MultiFrame);
screenToViewParams = renderDevice->createUniformBuffer(&screenToView, sizeof(ScreenToView), UniformBuffer_MultiFrame);
frustumDescriptorSet = frustumDescriptorLayout->allocateDescriptorSet();
frustumDescriptorSet->updateBuffer(0, dispatchParamsBuffer);
frustumDescriptorSet->updateBuffer(1, screenToViewParams);
frustumDescriptorSet->updateBuffer(2, frustumBuffer);
frustumDescriptorSet->writeChanges();
renderDevice->setComputeShader(frustumShader);
renderDevice->bindComputeDescriptors(frustumLayout, frustumDescriptorSet);
renderDevice->dispatchComputeShader(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z);
renderDevice->pipelineBarrier(frustumBuffer, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
cullingDescriptorLayout->reset();
lightEnvDescriptorLayout->reset();
cullingDescriptorSet = cullingDescriptorLayout->allocateDescriptorSet();
lightEnvDescriptorSet = lightEnvDescriptorLayout->allocateDescriptorSet();
cullingDescriptorSet->updateBuffer(0, viewParamsBuffer);
cullingDescriptorSet->updateBuffer(1, dispatchParamsBuffer);
cullingDescriptorSet->updateBuffer(3, frustumBuffer);
cullingDescriptorSet->updateBuffer(4, oLightIndexCounter);
cullingDescriptorSet->updateBuffer(5, tLightIndexCounter);
cullingDescriptorSet->updateBuffer(6, oLightIndexList);
cullingDescriptorSet->updateBuffer(7, tLightIndexList);
cullingDescriptorSet->updateTexture(8, oLightGrid);
cullingDescriptorSet->updateTexture(9, tLightGrid);
}
void LightCullingPass::render()
{
oLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
oLightGrid->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
depthAttachment->pipelineBarrier(
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
depthAttachment->transferOwnership(Gfx::QueueType::COMPUTE);
cullingDescriptorSet->updateTexture(2, depthAttachment);
cullingDescriptorSet->writeChanges();
lightEnvDescriptorSet->updateBuffer(0, scene->getLightBuffer());
lightEnvDescriptorSet->writeChanges();
Gfx::PComputeCommand computeCommand = graphics->createComputeCommand("CullingCommand");
computeCommand->bindPipeline(cullingPipeline);
Array<Gfx::PDescriptorSet> descriptorSets = {cullingDescriptorSet, lightEnvDescriptorSet};
computeCommand->bindDescriptor(descriptorSets);
computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
Array<Gfx::PComputeCommand> commands = {computeCommand};
graphics->executeCommands(commands);
depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
depthAttachment->transferOwnership(Gfx::QueueType::GRAPHICS);
}
void LightCullingPass::endFrame()
@@ -69,15 +84,172 @@ void LightCullingPass::endFrame()
void LightCullingPass::publishOutputs()
{
setupFrustums();
BulkResourceData resourceData;
StructuredBufferCreateInfo createInfo;
resourceData.size = sizeof(uint32);
resourceData.data = nullptr;
resourceData.owner = Gfx::QueueType::COMPUTE;
createInfo.bDynamic = false;
createInfo.resourceData = resourceData;
oLightIndexCounter = graphics->createStructuredBuffer(createInfo);
tLightIndexCounter = graphics->createStructuredBuffer(createInfo);
resourceData.size = sizeof(uint32_t) * dispatchParams.numThreadGroups.x * dispatchParams.numThreadGroups.y * dispatchParams.numThreadGroups.z * 1024;
oLightIndexList = graphics->createStructuredBuffer(createInfo);
tLightIndexList = graphics->createStructuredBuffer(createInfo);
renderGraph->registerBufferOutput("LIGHTCULLING_OLIGHTLIST", oLightIndexList);
renderGraph->registerBufferOutput("LIGHTCULLING_TLIGHTLIST", tLightIndexList);
TextureCreateInfo textureInfo;
textureInfo.width = dispatchParams.numThreadGroups.x;
textureInfo.height = dispatchParams.numThreadGroups.y;
textureInfo.format = Gfx::SE_FORMAT_R16G16_UINT;
textureInfo.usage = Gfx::SE_IMAGE_USAGE_STORAGE_BIT;
oLightGrid = graphics->createTexture2D(textureInfo);
tLightGrid = graphics->createTexture2D(textureInfo);
renderGraph->registerTextureOutput("LIGHTCULLING_OLIGHTGRID", oLightGrid);
renderGraph->registerTextureOutput("LIGHTCULLING_TLIGHTGRID", tLightGrid);
}
void LightCullingPass::createRenderPass()
void LightCullingPass::createRenderPass()
{
cullingDescriptorLayout = graphics->createDescriptorLayout("CullingLayout");
//ViewParams
cullingDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
//Dispatchparams
cullingDescriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
//DepthTexture
cullingDescriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
//Frustums
cullingDescriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
//o_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(4, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
//t_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(5, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
//o_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(6, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
//t_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(7, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
//o_lightGrid
cullingDescriptorLayout->addDescriptorBinding(8, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE);
//t_lightGrid
cullingDescriptorLayout->addDescriptorBinding(9, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE);
lightEnvDescriptorLayout = graphics->createDescriptorLayout("LightEnv");
//LightEnv
lightEnvDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
cullingLayout = graphics->createPipelineLayout();
cullingLayout->addDescriptorLayout(0, cullingDescriptorLayout);
cullingLayout->addDescriptorLayout(1, lightEnvDescriptorLayout);
cullingLayout->create();
ShaderCreateInfo createInfo;
createInfo.name = "Culling";
std::ifstream codeStream("./shaders/LightCulling.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.entryPoint = "cullLights";
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
createInfo.defines["INDEX_LIGHT_ENV"] = "1";
createInfo.defines["NUM_MATERIAL_TEXCOORDS"] = "0";
cullingShader = graphics->createComputeShader(createInfo);
ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = cullingLayout;
cullingPipeline = graphics->createComputePipeline(pipelineInfo);
depthAttachment = renderGraph->requestRenderTarget("DEPTHPREPASS_DEPTH")->getTexture();
}
void LightCullingPass::modifyRenderPassMacros(Map<const char*, const char*>& defines)
{
}
void LightCullingPass::setupFrustums()
{
uint32_t viewportWidth = viewport->getSizeX();
uint32_t viewportHeight = viewport->getSizeY();
glm::uvec3 numThreads = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1));
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.inverseProjectionMatrix = glm::inverse(source->getProjectionMatrix());
viewParams.screenDimensions = glm::vec2(viewportWidth, viewportHeight);
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
dispatchParams.numThreads = numThreads;
dispatchParams.numThreadGroups = numThreadGroups;
Gfx::PDescriptorLayout frustumDescriptorLayout = graphics->createDescriptorLayout("FrustumLayout");
frustumDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
frustumDescriptorLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
frustumDescriptorLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
frustumLayout = graphics->createPipelineLayout();
frustumLayout->addDescriptorLayout(0, frustumDescriptorLayout);
frustumLayout->create();
ShaderCreateInfo createInfo;
createInfo.name = "Frustum";
std::ifstream codeStream("./shaders/ComputeFrustums.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.entryPoint = "computeFrustums";
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
frustumShader = graphics->createComputeShader(createInfo);
ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = frustumShader;
pipelineInfo.pipelineLayout = frustumLayout;
frustumPipeline = graphics->createComputePipeline(pipelineInfo);
BulkResourceData resourceInfo;
UniformBufferCreateInfo uniformInfo;
resourceInfo.size = sizeof(ViewParameter);
resourceInfo.data = (uint8*)&viewParams;
resourceInfo.owner = Gfx::QueueType::COMPUTE;
uniformInfo.resourceData = resourceInfo;
uniformInfo.bDynamic = false;
viewParamsBuffer = graphics->createUniformBuffer(uniformInfo);
resourceInfo.size = sizeof(DispatchParams);
resourceInfo.data = (uint8*)&dispatchParams;
uniformInfo.resourceData = resourceInfo;
uniformInfo.bDynamic = false;
dispatchParamsBuffer = graphics->createUniformBuffer(uniformInfo);
StructuredBufferCreateInfo structuredInfo;
resourceInfo.size = sizeof(Frustum) * numThreads.x * numThreads.y * numThreads.z;
resourceInfo.data = nullptr;
structuredInfo.resourceData = resourceInfo;
structuredInfo.bDynamic = false;
frustumBuffer = graphics->createStructuredBuffer(structuredInfo);
frustumDescriptorSet = frustumDescriptorLayout->allocateDescriptorSet();
frustumDescriptorSet->updateBuffer(0, viewParamsBuffer);
frustumDescriptorSet->updateBuffer(1, dispatchParamsBuffer);
frustumDescriptorSet->updateBuffer(2, frustumBuffer);
frustumDescriptorSet->writeChanges();
Gfx::PComputeCommand command = graphics->createComputeCommand("FrustumCommand");
command->bindPipeline(frustumPipeline);
command->bindDescriptor(frustumDescriptorSet);
command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z);
Array<Gfx::PComputeCommand> commands = {command};
graphics->executeCommands(commands);
frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
@@ -1,16 +1,17 @@
#pragma once
#include "RenderPass.h"
#include "Graphics/GraphicsResources.h"
namespace Seele
{
DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
DECLARE_NAME_REF(Gfx, Viewport)
DECLARE_NAME_REF(Gfx, Graphics)
DECLARE_REF(Scene)
DECLARE_REF(Viewport)
class LightCullingPass : public RenderPass
{
public:
LightCullingPass(PRenderGraph renderGraph, Gfx::PViewport viewport, Gfx::PGraphics graphics, PCameraActor camera);
LightCullingPass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera);
virtual ~LightCullingPass();
virtual void beginFrame() override;
virtual void render() override;
@@ -19,7 +20,9 @@ public:
virtual void createRenderPass() override;
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
private:
void setupFrustums();
static constexpr uint32 BLOCK_SIZE = 8;
static constexpr uint32 INDEX_LIGHT_ENV = 1;
_declspec(align(16)) struct DispatchParams
{
glm::uvec3 numThreadGroups;
@@ -39,13 +42,36 @@ private:
{
Plane planes[4];
};
struct ScreenToView
{
Matrix4 inverseProjection;
Vector2 screenDimensions;
};
PScene scene;
Gfx::PViewport viewport;
Gfx::PGraphics graphics;
Gfx::PStructuredBuffer frustumBuffer;
Gfx::PUniformBuffer dispatchParamsBuffer;
Gfx::PUniformBuffer viewParamsBuffer;
Gfx::PDescriptorSet frustumDescriptorSet;
Gfx::PComputeShader frustumShader;
Gfx::PPipelineLayout frustumLayout;
Gfx::PComputePipeline frustumPipeline;
Gfx::PTexture2D depthAttachment;
//Gfx::PTexture2D depthComputeTexture;
Gfx::PStructuredBuffer frustums;
Gfx::PStructuredBuffer oLightIndexCounter;
Gfx::PStructuredBuffer tLightIndexCounter;
Gfx::PStructuredBuffer oLightIndexList;
Gfx::PStructuredBuffer tLightIndexList;
Gfx::PTexture2D oLightGrid;
Gfx::PTexture2D tLightGrid;
Gfx::PDescriptorSet lightEnvDescriptorSet;
Gfx::PDescriptorSet cullingDescriptorSet;
Gfx::PDescriptorLayout lightEnvDescriptorLayout;
Gfx::PDescriptorLayout cullingDescriptorLayout;
Gfx::PComputeShader cullingShader;
Gfx::PPipelineLayout cullingLayout;
Gfx::PComputePipeline cullingPipeline;
PCameraComponent source;
};
DEFINE_REF(LightCullingPass)
} // namespace Seele
@@ -23,6 +23,11 @@ void RenderGraph::setup()
}
}
void RenderGraph::addRenderPass(PRenderPass renderPass)
{
renderPasses.add(renderPass);
}
Gfx::PRenderTargetAttachment RenderGraph::requestRenderTarget(const std::string& outputName)
{
if(registeredAttachments.find(outputName) == registeredAttachments.end())
@@ -33,7 +38,38 @@ Gfx::PRenderTargetAttachment RenderGraph::requestRenderTarget(const std::string&
return registeredAttachments[outputName];
}
Gfx::PTexture RenderGraph::requestTexture(const std::string& outputName)
{
if(registeredTextures.find(outputName) == registeredTextures.end())
{
std::cout << "Attachment " << outputName << " not found" << std::endl;
return nullptr;
}
return registeredTextures[outputName];
}
Gfx::PStructuredBuffer RenderGraph::requestBuffer(const std::string& outputName)
{
if(registeredBuffers.find(outputName) == registeredBuffers.end())
{
std::cout << "Attachment " << outputName << " not found" << std::endl;
return nullptr;
}
return registeredBuffers[outputName];
}
void RenderGraph::registerRenderPassOutput(const std::string& outputName, Gfx::PRenderTargetAttachment attachment)
{
registeredAttachments[outputName] = attachment;
}
void RenderGraph::registerTextureOutput(const std::string& outputName, Gfx::PTexture texture)
{
registeredTextures[outputName] = texture;
}
void RenderGraph::registerBufferOutput(const std::string& outputName, Gfx::PStructuredBuffer buffer)
{
registeredBuffers[outputName] = buffer;
}
+8 -1
View File
@@ -11,10 +11,17 @@ public:
RenderGraph();
~RenderGraph();
void setup();
void addRenderPass(PRenderPass renderPass);
Gfx::PRenderTargetAttachment requestRenderTarget(const std::string& outputName);
void registerRenderPassOutput(const std::string& ouputName, Gfx::PRenderTargetAttachment attachment);
Gfx::PTexture requestTexture(const std::string& outputName);
Gfx::PStructuredBuffer requestBuffer(const std::string& outputName);
void registerRenderPassOutput(const std::string& outputName, Gfx::PRenderTargetAttachment attachment);
void registerTextureOutput(const std::string& outputName, Gfx::PTexture buffer);
void registerBufferOutput(const std::string& outputName, Gfx::PStructuredBuffer buffer);
private:
Map<std::string, Gfx::PRenderTargetAttachment> registeredAttachments;
Map<std::string, Gfx::PTexture> registeredTextures;
Map<std::string, Gfx::PStructuredBuffer> registeredBuffers;
List<PRenderPass> renderPasses;
};
DEFINE_REF(RenderGraph)
+2 -5
View File
@@ -21,13 +21,10 @@ protected:
{
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
Vector4 cameraPosition;
} viewParams;
struct ScreenToViewParameter
{
Matrix4 inverseProjectionMatrix;
Vector2 screenDimensions;
} screenToViewParams;
Vector4 cameraPosition;
} viewParams;
Gfx::PRenderPass renderPass;
PRenderGraph renderGraph;
};