diff --git a/ref_vk/shaders/denoiser.comp b/ref_vk/shaders/denoiser.comp new file mode 100644 index 00000000..3284f062 --- /dev/null +++ b/ref_vk/shaders/denoiser.comp @@ -0,0 +1,18 @@ +#version 460 + +layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in; + +layout(set = 0, binding = 0, rgba8) uniform image2D source; +layout(set = 0, binding = 1, rgba8) uniform image2D dest; + +void main() { + ivec2 res = ivec2(imageSize(source)); + ivec2 pix = ivec2(gl_GlobalInvocationID); + + vec3 colour = vec3(0.); + + if (all(lessThan(pix, res))) + colour = imageLoad(source, pix).rgb; + + imageStore(dest, pix, vec4(colour, 1.)); +} diff --git a/ref_vk/vk_denoiser.c b/ref_vk/vk_denoiser.c index 077d56d0..216fcd75 100644 --- a/ref_vk/vk_denoiser.c +++ b/ref_vk/vk_denoiser.c @@ -1,5 +1,8 @@ #include "vk_denoiser.h" +#include "vk_descriptor.h" +#include "vk_pipeline.h" + #include "eiface.h" // ARRAYSIZE static void blitImage( VkCommandBuffer cmdbuf, VkImage src, VkImage dst, int src_width, int src_height, int dst_width, int dst_height ) @@ -45,14 +48,100 @@ static void blitImage( VkCommandBuffer cmdbuf, VkImage src, VkImage dst, int src } } -void XVK_DenoiserDenoise( const xvk_denoiser_args_t* args ) { - // Blit RTX frame onto swapchain image - blitImage(args->cmdbuf, args->in.image, args->out.image, args->in.width, args->in.height, args->out.width, args->out.height); +enum { + DenoiserBinding_SourceImage = 0, + DenoiserBinding_DestImage = 1, + + DenoiserBinding_COUNT +}; + +static struct { + vk_descriptors_t descriptors; + vk_descriptor_value_t desc_values[DenoiserBinding_COUNT]; + + VkDescriptorSetLayoutBinding desc_bindings[DenoiserBinding_COUNT]; + VkDescriptorSet desc_sets[1]; + + VkPipeline pipeline; +} g_denoiser = {0}; + +static void createLayouts( void ) { + g_denoiser.descriptors.bindings = g_denoiser.desc_bindings; + g_denoiser.descriptors.num_bindings = ARRAYSIZE(g_denoiser.desc_bindings); + g_denoiser.descriptors.values = g_denoiser.desc_values; + g_denoiser.descriptors.num_sets = 1; + g_denoiser.descriptors.desc_sets = g_denoiser.desc_sets; + g_denoiser.descriptors.push_constants = (VkPushConstantRange){ + .offset = 0, + .size = 0, + .stageFlags = 0, + }; + + g_denoiser.desc_bindings[DenoiserBinding_DestImage] = (VkDescriptorSetLayoutBinding){ + .binding = DenoiserBinding_DestImage, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + }; + + g_denoiser.desc_bindings[DenoiserBinding_SourceImage] = (VkDescriptorSetLayoutBinding){ + .binding = DenoiserBinding_SourceImage, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + }; + + VK_DescriptorsCreate(&g_denoiser.descriptors); +} + +static VkPipeline createPipeline( void ) { + const vk_pipeline_compute_create_info_t pcci = { + .layout = g_denoiser.descriptors.pipeline_layout, + .shader_filename = "denoiser.comp.spv", + .specialization_info = NULL, + }; + + return VK_PipelineComputeCreate( &pcci ); } qboolean XVK_DenoiserInit( void ) { - return true; + ASSERT(vk_core.rtx); + + createLayouts(); + + ASSERT(!g_denoiser.pipeline); + g_denoiser.pipeline = createPipeline(); + + return g_denoiser.pipeline != VK_NULL_HANDLE; } void XVK_DenoiserDestroy( void ) { + ASSERT(vk_core.rtx); + ASSERT(g_denoiser.pipeline); + + vkDestroyPipeline(vk_core.device, g_denoiser.pipeline, NULL); + VK_DescriptorsDestroy(&g_denoiser.descriptors); +} + +void XVK_DenoiserDenoise( const xvk_denoiser_args_t* args ) { + const uint32_t WG_W = 16; + const uint32_t WG_H = 8; + + g_denoiser.desc_values[DenoiserBinding_SourceImage].image = (VkDescriptorImageInfo){ + .sampler = VK_NULL_HANDLE, + .imageView = args->in.image_view, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + }; + + g_denoiser.desc_values[DenoiserBinding_DestImage].image = (VkDescriptorImageInfo){ + .sampler = VK_NULL_HANDLE, + .imageView = args->out.image_view, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + }; + + VK_DescriptorsWrite(&g_denoiser.descriptors); + + vkCmdBindPipeline(args->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, g_denoiser.pipeline); + vkCmdBindDescriptorSets(args->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, g_denoiser.descriptors.pipeline_layout, 0, 1, g_denoiser.descriptors.desc_sets + 0, 0, NULL); + vkCmdDispatch(args->cmdbuf, (args->out.width + WG_W - 1) / WG_W, (args->out.height + WG_H - 1) / WG_H, 1); } diff --git a/ref_vk/vk_denoiser.h b/ref_vk/vk_denoiser.h index 1200948a..bd03b270 100644 --- a/ref_vk/vk_denoiser.h +++ b/ref_vk/vk_denoiser.h @@ -9,12 +9,12 @@ typedef struct { VkCommandBuffer cmdbuf; struct { - VkImage image; + VkImageView image_view; uint32_t width, height; } in; struct { - VkImage image; + VkImageView image_view; uint32_t width, height; } out; } xvk_denoiser_args_t; diff --git a/ref_vk/vk_framectl.c b/ref_vk/vk_framectl.c index 60b7c19e..be022dc4 100644 --- a/ref_vk/vk_framectl.c +++ b/ref_vk/vk_framectl.c @@ -232,7 +232,7 @@ static qboolean createSwapchain( void ) create_info->imageExtent.width = vk_frame.width; create_info->imageExtent.height = vk_frame.height; create_info->imageArrayLayers = 1; - create_info->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | (vk_core.rtx ? /*VK_IMAGE_USAGE_STORAGE_BIT |*/ VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0); + create_info->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | (vk_core.rtx ? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0); create_info->imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; create_info->preTransform = g_frame.surface_caps.currentTransform; create_info->compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/ref_vk/vk_rtx.c b/ref_vk/vk_rtx.c index 21815b32..43467c9e 100644 --- a/ref_vk/vk_rtx.c +++ b/ref_vk/vk_rtx.c @@ -814,9 +814,10 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .image = args->dst.image, .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .subresourceRange = (VkImageSubresourceRange){ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -829,7 +830,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) vkCmdPipelineBarrier(args->cmdbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers); } } else { @@ -844,9 +845,9 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .image = frame_dst->image, .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, .oldLayout = VK_IMAGE_LAYOUT_GENERAL, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, .subresourceRange = (VkImageSubresourceRange){ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -860,9 +861,9 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .image = args->dst.image, .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, .subresourceRange = (VkImageSubresourceRange){ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -874,7 +875,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) }}; vkCmdPipelineBarrier(args->cmdbuf, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, - VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers); } } @@ -883,12 +884,12 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) const xvk_denoiser_args_t denoiser_args = { .cmdbuf = cmdbuf, .in = { - .image = frame_src->image, + .image_view = frame_src->view, .width = FRAME_WIDTH, .height = FRAME_HEIGHT, }, .out = { - .image = args->dst.image, + .image_view = args->dst.image_view, .width = args->dst.width, .height = args->dst.height, }, @@ -897,6 +898,30 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args) XVK_DenoiserDenoise( &denoiser_args ); } + { + const VkImageMemoryBarrier image_barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .image = args->dst.image, + .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_GENERAL, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .subresourceRange = + (VkImageSubresourceRange){ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }}; + vkCmdPipelineBarrier(args->cmdbuf, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, 0, NULL, 0, NULL, ARRAYSIZE(image_barriers), image_barriers); + } + } static void createLayouts( void ) { diff --git a/ref_vk/vk_textures.h b/ref_vk/vk_textures.h index f99e5849..be7c45f5 100644 --- a/ref_vk/vk_textures.h +++ b/ref_vk/vk_textures.h @@ -66,7 +66,8 @@ int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags #define VK_LoadTextureInternal( name, pic, flags ) VK_LoadTextureFromBuffer( name, pic, flags, false ) typedef struct { - // TODO better memory allocation + // FIXME better memory allocation + // OCHEN PLOHO device_memory_t devmem; VkImage image; VkImageView view;