diff --git a/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp b/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp new file mode 100644 index 0000000000000000000000000000000000000000..d3d1ee72546595fa0c260f7c5493b76beaf2012c --- /dev/null +++ b/projects/indirect_dispatch/resources/shaders/gammaCorrection.comp @@ -0,0 +1,23 @@ +#version 440 +#extension GL_GOOGLE_include_directive : enable + +layout(set=0, binding=0) uniform texture2D inTexture; +layout(set=0, binding=1) uniform sampler textureSampler; +layout(set=0, binding=2, rgba8) uniform image2D outImage; + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +void main(){ + + if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))) + return; + + ivec2 textureRes = textureSize(sampler2D(inTexture, textureSampler), 0); + ivec2 coord = ivec2(gl_GlobalInvocationID.xy); + vec2 uv = vec2(coord) / textureRes; + + vec3 linearColor = texture(sampler2D(inTexture, textureSampler), uv).rgb; + vec3 gammaCorrected = pow(linearColor, vec3(1 / 2.2)); + + imageStore(outImage, coord, vec4(gammaCorrected, 0.f)); +} \ No newline at end of file diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index 47f4a2b7376f0497c41e76685a7c90217ae7cc9d..2654931f01093e9a932f2c3faaca23d682c37455 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -31,12 +31,21 @@ bool App::initialize() { if (!loadSkyPass(m_core, &m_skyPassHandles)) return false; + if (!loadComputePass(m_core, "resources/shaders/gammaCorrection.comp", &m_gammaCorrectionPass)) + return false; + if (!loadMesh(m_core, "resources/models/sphere.gltf", & m_sphereMesh)) return false; if (!loadMesh(m_core, "resources/models/cube.gltf", &m_cubeMesh)) return false; + m_linearSampler = m_core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::CLAMP_TO_EDGE); + m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight); const int cameraIndex = m_cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); @@ -85,8 +94,11 @@ void App::run() { m_cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); const glm::mat4 viewProjection = m_cameraManager.getActiveCamera().getMVP(); - const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, m_renderTargets.depthBuffer }; - const vkcv::CommandStreamHandle cmdStream = m_core.createCommandStream(vkcv::QueueType::Graphics); + const std::vector<vkcv::ImageHandle> renderTargets = { + m_renderTargets.colorBuffer, + m_renderTargets.depthBuffer }; + + const vkcv::CommandStreamHandle cmdStream = m_core.createCommandStream(vkcv::QueueType::Graphics); vkcv::PushConstants meshPushConstants(sizeof(glm::mat4)); meshPushConstants.appendDrawcall(viewProjection); @@ -110,6 +122,32 @@ void App::run() { { cubeDrawcall }, renderTargets); + vkcv::DescriptorWrites gammaCorrectionDescriptorWrites; + gammaCorrectionDescriptorWrites.sampledImageWrites = { + vkcv::SampledImageDescriptorWrite(0, m_renderTargets.colorBuffer) }; + gammaCorrectionDescriptorWrites.samplerWrites = { + vkcv::SamplerDescriptorWrite(1, m_linearSampler) }; + gammaCorrectionDescriptorWrites.storageImageWrites = { + vkcv::StorageImageDescriptorWrite(2, swapchainInput) }; + + m_core.writeDescriptorSet(m_gammaCorrectionPass.descriptorSet, gammaCorrectionDescriptorWrites); + + m_core.prepareImageForSampling(cmdStream, m_renderTargets.colorBuffer); + m_core.prepareImageForStorage (cmdStream, swapchainInput); + + uint32_t gammaCorrectionDispatch[3] = { + (m_windowWidth + 7) / 8, + (m_windowHeight + 7) / 8, + 1 + }; + + m_core.recordComputeDispatchToCmdStream( + cmdStream, + m_gammaCorrectionPass.pipeline, + gammaCorrectionDispatch, + { vkcv::DescriptorSetUsage(0, m_core.getDescriptorSet(m_gammaCorrectionPass.descriptorSet).vulkanHandle) }, + vkcv::PushConstants(0)); + m_core.prepareSwapchainImageForPresent(cmdStream); m_core.submitCommandStream(cmdStream); m_core.endFrame(); diff --git a/projects/indirect_dispatch/src/App.hpp b/projects/indirect_dispatch/src/App.hpp index 066971769028040f9fd9403650512c53a1bfe0b2..ea889108cf59bc1ff1ac897cf492b41134426f16 100644 --- a/projects/indirect_dispatch/src/App.hpp +++ b/projects/indirect_dispatch/src/App.hpp @@ -25,5 +25,8 @@ private: GraphicPassHandles m_meshPassHandles; GraphicPassHandles m_skyPassHandles; - RenderTargets m_renderTargets; + ComputePassHandles m_gammaCorrectionPass; + + RenderTargets m_renderTargets; + vkcv::SamplerHandle m_linearSampler; }; \ No newline at end of file diff --git a/projects/indirect_dispatch/src/AppConfig.hpp b/projects/indirect_dispatch/src/AppConfig.hpp index 71993ebd435348fd7854b3178e95cd9c89f484f3..2ff3d28e350ea55b200211cf1839fdcb338d7868 100644 --- a/projects/indirect_dispatch/src/AppConfig.hpp +++ b/projects/indirect_dispatch/src/AppConfig.hpp @@ -5,4 +5,5 @@ namespace AppConfig{ const int defaultWindowWidth = 1280; const int defaultWindowHeight = 720; const vk::Format depthBufferFormat = vk::Format::eD32Sfloat; + const vk::Format colorBufferFormat = vk::Format::eB10G11R11UfloatPack32; } \ No newline at end of file diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp index db7f689f80241d3173adfc22ab15a298d0b7c5dd..687d8863a02f64cd1b479855f274c40482831846 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -117,7 +117,7 @@ bool loadMeshPass(vkcv::Core& core, GraphicPassHandles* outHandles) { vkcv::AttachmentDescription colorAttachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat()); + AppConfig::colorBufferFormat); vkcv::AttachmentDescription depthAttachment( vkcv::AttachmentOperation::STORE, @@ -139,7 +139,7 @@ bool loadSkyPass(vkcv::Core& core, GraphicPassHandles* outHandles) { vkcv::AttachmentDescription colorAttachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::LOAD, - core.getSwapchain().getFormat()); + AppConfig::colorBufferFormat); vkcv::AttachmentDescription depthAttachment( vkcv::AttachmentOperation::DONT_CARE, @@ -154,6 +154,36 @@ bool loadSkyPass(vkcv::Core& core, GraphicPassHandles* outHandles) { outHandles); } +bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, ComputePassHandles* outComputePass) { + + assert(outComputePass); + vkcv::ShaderProgram shaderProgram; + vkcv::shader::GLSLCompiler compiler; + + compiler.compile(vkcv::ShaderStage::COMPUTE, path, + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shaderProgram.addShader(shaderStage, path); + }); + + if (shaderProgram.getReflectedDescriptors().size() < 1) { + vkcv_log(vkcv::LogLevel::ERROR, "Compute shader has no descriptor set"); + return false; + } + + outComputePass->descriptorSet = core.createDescriptorSet(shaderProgram.getReflectedDescriptors()[0]); + + outComputePass->pipeline = core.createComputePipeline( + shaderProgram, + { core.getDescriptorSet(outComputePass->descriptorSet).layout }); + + if (!outComputePass->pipeline) { + vkcv_log(vkcv::LogLevel::ERROR, "Compute shader pipeline creation failed"); + return false; + } + + return true; +} + RenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height) { RenderTargets targets; @@ -165,5 +195,14 @@ RenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const 1, false).getHandle(); + targets.colorBuffer = core.createImage( + AppConfig::colorBufferFormat, + width, + height, + 1, + false, + false, + true).getHandle(); + return targets; } \ No newline at end of file diff --git a/projects/indirect_dispatch/src/AppSetup.hpp b/projects/indirect_dispatch/src/AppSetup.hpp index f388ede2761c61f6aee85809c6d94715c8f62191..892701aa4e57027f0eaf3904a195b7046d66b785 100644 --- a/projects/indirect_dispatch/src/AppSetup.hpp +++ b/projects/indirect_dispatch/src/AppSetup.hpp @@ -3,6 +3,7 @@ struct RenderTargets { vkcv::ImageHandle depthBuffer; + vkcv::ImageHandle colorBuffer; }; struct GraphicPassHandles { @@ -10,6 +11,11 @@ struct GraphicPassHandles { vkcv::PassHandle renderPass; }; +struct ComputePassHandles { + vkcv::PipelineHandle pipeline; + vkcv::DescriptorSetHandle descriptorSet; +}; + struct MeshResources { vkcv::Mesh mesh; vkcv::BufferHandle vertexBuffer; @@ -29,4 +35,6 @@ bool loadGraphicPass( bool loadMeshPass(vkcv::Core& core, GraphicPassHandles* outHandles); bool loadSkyPass (vkcv::Core& core, GraphicPassHandles* outHandles); +bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, ComputePassHandles* outComputePass); + RenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height); \ No newline at end of file