Created CPU and GPU data for SSAO

Renderpass for SSAO not yet done (that's next)
This commit is contained in:
Brandon Mak 2022-10-31 10:32:32 +08:00
parent 997ce3011a
commit 94a57219da
9 changed files with 130 additions and 2 deletions

View File

@ -0,0 +1,24 @@
#version 450
uint const NUM_SAMPLES = 64;
uint const NUM_ROTATIONS = 16;
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba32f) uniform image2D outputImage;
// SSAO data
layout(std430, set = 5, binding = 0) buffer SSAOData
{
vec3 samples[NUM_SAMPLES];
vec3 rotations[NUM_ROTATIONS];
} ssaoData;
void main()
{
// store result into result image
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
}

View File

@ -253,6 +253,18 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>(); lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool); lightingSubSystem->Init(device, descPool);
ssaoStorage = resourceManager.Create<SHSSAO>();
ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
ssaoTransferCmdBuffer->BeginRecording();
ssaoStorage->Init(device, ssaoTransferCmdBuffer);
ssaoTransferCmdBuffer->EndRecording();
graphicsQueue->SubmitCommandBuffer({ssaoTransferCmdBuffer});
graphicsQueue->WaitIdle();
} }
#ifdef SHEDITOR #ifdef SHEDITOR

View File

@ -32,6 +32,7 @@ of DigiPen Institute of Technology is prohibited.
#include "../Textures/SHVkSamplerCache.h" #include "../Textures/SHVkSamplerCache.h"
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h" #include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" #include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/MiddleEnd/PostProcessing/SHSSAO.h"
namespace SHADE namespace SHADE
{ {
@ -313,6 +314,7 @@ namespace SHADE
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool; Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer; Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> ssaoTransferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer; Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext; SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores; std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
@ -357,6 +359,7 @@ namespace SHADE
Handle<SHMousePickSystem> mousePickSystem; Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender; Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
Handle<SHLightingSubSystem> lightingSubSystem; Handle<SHLightingSubSystem> lightingSubSystem;
Handle<SHSSAO> ssaoStorage;
uint32_t resizeWidth = 1; uint32_t resizeWidth = 1;
uint32_t resizeHeight = 1; uint32_t resizeHeight = 1;

View File

@ -1,7 +1,60 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHSSAO.h" #include "SHSSAO.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include <random>
namespace SHADE namespace SHADE
{ {
void SHSSAO::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{
// create memory on CPU side
ssaoData = std::make_unique<SamplesAndKernel>();
// Initialize a distribution to get values from 0 to 1
std::uniform_real_distribution<float> distrib{0.0f, 1.0f};
// generator for random number
std::default_random_engine generator;
// generate samples
auto& samples = ssaoData->samples;
for (uint32_t i = 0; i < NUM_SAMPLES; ++i)
{
samples[i] = SHVec4
{
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator), // 0.0f - 1.0f so that sample space is a hemisphere
0.0f
};
// This makes sure that most points are closer to fragment's position
float scale = 1.0f / static_cast<float>(NUM_SAMPLES);
scale = std::lerp(0.1f, 1.0f, scale * scale);
samples[i] *= scale;
}
// generate rotation vector
auto& rotationVectors = ssaoData->rotatationVectors;
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
{
samples[i] = SHVec4
{
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
0.0f, // we want to rotate about the z axis in tangent space
0.0f
};
}
// Get aligned size for buffer
uint32_t alignedSize = logicalDevice->PadSSBOSize(sizeof (SamplesAndKernel));
// Create buffer
ssaoDataBuffer = logicalDevice->CreateBuffer(alignedSize, ssaoData.get(), alignedSize, vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, {});
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
}
} }

View File

@ -2,14 +2,36 @@
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Math/Vector/SHVec4.h"
namespace SHADE namespace SHADE
{ {
class SHVkBuffer;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
class SHSSAO class SHSSAO
{ {
private: private:
static constexpr uint32_t NUM_SAMPLES = 64;
static constexpr uint32_t NUM_ROTATION_VECTORS = 16;
struct SamplesAndKernel
{
//! distances from a pixel we want to sample
std::array<SHVec4, NUM_SAMPLES> samples;
std::array<SHVec4, NUM_ROTATION_VECTORS> rotatationVectors;
};
private:
//! Samples and kernel on CPU side
std::unique_ptr<SamplesAndKernel> ssaoData;
//! For passing SSAO samples and kernel to GPU
Handle<SHVkBuffer> ssaoDataBuffer;
public:
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
}; };
} }

View File

@ -129,4 +129,9 @@ namespace SHADE
return vkQueue; return vkQueue;
} }
void SHVkQueue::WaitIdle(void) const noexcept
{
vkQueue.waitIdle();
}
} }

View File

@ -50,6 +50,8 @@ namespace SHADE
void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept; void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept; vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
vk::Queue GetVkQueue() noexcept; vk::Queue GetVkQueue() noexcept;
void WaitIdle (void) const noexcept;
}; };
} }

View File

@ -164,4 +164,9 @@ namespace SHADE
} }
} }
void SHRenderGraphNodeCompute::ModifyWriteDescBufferComputeResource(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
{
computeResource->descSet->ModifyWriteDescBuffer(set, binding, buffers, offset, range);
}
} }

View File

@ -18,6 +18,7 @@ namespace SHADE
class SHRenderGraphResource; class SHRenderGraphResource;
class SHVkShaderModule; class SHVkShaderModule;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkBuffer;
class SHRenderGraphNodeCompute class SHRenderGraphNodeCompute
@ -37,8 +38,6 @@ namespace SHADE
static constexpr uint32_t workGroupSizeX = 16; static constexpr uint32_t workGroupSizeX = 16;
static constexpr uint32_t workGroupSizeY = 16; static constexpr uint32_t workGroupSizeY = 16;
using ExternalDescSetBindCommands = std::function<void(Handle<SHVkCommandBuffer>, Handle<SHVkPipelineLayout>)>;
//! To run the dispatch command //! To run the dispatch command
Handle<SHVkPipeline> computePipeline; Handle<SHVkPipeline> computePipeline;
@ -48,6 +47,7 @@ namespace SHADE
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE) //! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> graphResourceDescSets; std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> graphResourceDescSets;
//! Compute resources
Handle<ComputeResource> computeResource; Handle<ComputeResource> computeResource;
//! vector of resources needed by the subpass compute //! vector of resources needed by the subpass compute
@ -73,6 +73,8 @@ namespace SHADE
void SetDynamicOffsets (std::span<uint32_t> perFrameSizes) noexcept; void SetDynamicOffsets (std::span<uint32_t> perFrameSizes) noexcept;
void ModifyWriteDescBufferComputeResource (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
}; };