Provisional light culling
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user