NVSharpen.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // The MIT License(MIT)
  2. //
  3. // Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. // this software and associated documentation files(the "Software"), to deal in
  7. // the Software without restriction, including without limitation the rights to
  8. // use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
  9. // the Software, and to permit persons to whom the Software is furnished to do so,
  10. // subject to the following conditions :
  11. //
  12. // The above copyright notice and this permission notice shall be included in all
  13. // copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
  18. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #include "NVSharpen.h"
  22. #include <iostream>
  23. #include <array>
  24. #include "VKUtilities.h"
  25. #include "DeviceResources.h"
  26. #include "Utilities.h"
  27. NVSharpen::NVSharpen(DeviceResources& deviceResources, const std::vector<std::string>& shaderPaths, bool glsl)
  28. : m_deviceResources(deviceResources)
  29. , m_outputWidth(1)
  30. , m_outputHeight(1)
  31. {
  32. NISOptimizer opt(false, NISGPUArchitecture::NVIDIA_Generic);
  33. m_blockWidth = opt.GetOptimalBlockWidth();
  34. m_blockHeight = opt.GetOptimalBlockHeight();
  35. uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
  36. // Shader
  37. {
  38. std::string shaderName = glsl ? "/nis_sharpen_glsl.spv" : "/nis_sharpen.spv";
  39. std::string shaderPath;
  40. for (auto& e : shaderPaths)
  41. {
  42. if (std::filesystem::exists(e + "/" + shaderName))
  43. {
  44. shaderPath = e + "/" + shaderName;
  45. break;
  46. }
  47. }
  48. if (shaderPath.empty())
  49. throw std::runtime_error("Shader file not found" + shaderName);
  50. auto shaderBytes = readBytes(shaderPath);
  51. VkShaderModuleCreateInfo info{};
  52. info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  53. info.codeSize = shaderBytes.size();
  54. info.pCode = reinterpret_cast<uint32_t*>(shaderBytes.data());
  55. VK_OK(vkCreateShaderModule(m_deviceResources.logicalDevice(), &info, nullptr, &m_shaderModule));
  56. }
  57. // Descriptor set
  58. {
  59. std::array<VkDescriptorSetLayoutBinding, 4> bindLayout{ {
  60. VK_COMMON_DESC_LAYOUT(m_deviceResources.sampler()),
  61. } };
  62. VkDescriptorSetLayoutCreateInfo info{};
  63. info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  64. info.bindingCount = (uint32_t)bindLayout.size();
  65. info.pBindings = bindLayout.data();
  66. VK_OK(vkCreateDescriptorSetLayout(m_deviceResources.logicalDevice(), &info, nullptr, &m_descriptorSetLayout));
  67. }
  68. {
  69. VkDescriptorSetAllocateInfo info{};
  70. info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  71. info.descriptorPool = deviceResources.descriptorPool();
  72. info.descriptorSetCount = 1;
  73. info.pSetLayouts = &m_descriptorSetLayout;
  74. VK_OK(vkAllocateDescriptorSets(m_deviceResources.logicalDevice(), &info, &m_descriptorSet));
  75. }
  76. // Constant buffer
  77. {
  78. m_deviceResources.createConstBuffer(&m_config, sizeof(NISConfig), &m_buffer, &m_constantBufferDeviceMemory, &m_constantBufferStride);
  79. VK_OK(vkMapMemory(m_deviceResources.logicalDevice(), m_constantBufferDeviceMemory, 0, m_constantBufferStride, 0, (void**)&m_constantMemory));
  80. VkDescriptorBufferInfo descBuffInfo{};
  81. descBuffInfo.buffer = m_buffer;
  82. descBuffInfo.offset = 0;
  83. descBuffInfo.range = sizeof(NISConfig);
  84. VkWriteDescriptorSet writeDescSet{};
  85. writeDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  86. writeDescSet.dstSet = m_descriptorSet;
  87. writeDescSet.dstBinding = CB_BINDING;
  88. writeDescSet.descriptorCount = 1;
  89. writeDescSet.descriptorType = CB_DESC_TYPE;
  90. writeDescSet.dstArrayElement = 0;
  91. writeDescSet.pBufferInfo = &descBuffInfo;
  92. vkUpdateDescriptorSets(m_deviceResources.logicalDevice(), 1, &writeDescSet, 0, nullptr);
  93. }
  94. // Pipeline layout
  95. {
  96. VkPushConstantRange pushConstRange{};
  97. pushConstRange.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
  98. pushConstRange.size = sizeof(m_config);
  99. VkPipelineLayoutCreateInfo info{};
  100. info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  101. info.setLayoutCount = 1;
  102. info.pSetLayouts = &m_descriptorSetLayout;
  103. info.pushConstantRangeCount = 1;
  104. info.pPushConstantRanges = &pushConstRange;
  105. VK_OK(vkCreatePipelineLayout(m_deviceResources.logicalDevice(), &info, nullptr, &m_pipelineLayout));
  106. }
  107. // Compute pipeline
  108. {
  109. VkPipelineShaderStageCreateInfo pipeShaderStageCreateInfo{};
  110. pipeShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  111. pipeShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
  112. pipeShaderStageCreateInfo.module = m_shaderModule;
  113. pipeShaderStageCreateInfo.pName = "main";
  114. VkComputePipelineCreateInfo csPipeCreateInfo{};
  115. csPipeCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
  116. csPipeCreateInfo.stage = pipeShaderStageCreateInfo;
  117. csPipeCreateInfo.layout = m_pipelineLayout;
  118. VK_OK(vkCreateComputePipelines(m_deviceResources.logicalDevice(), VK_NULL_HANDLE, 1, &csPipeCreateInfo, nullptr, &m_pipeline));
  119. }
  120. }
  121. void NVSharpen::cleanUp()
  122. {
  123. vkDestroyPipeline(m_deviceResources.logicalDevice(), m_pipeline, nullptr);
  124. vkDestroyPipelineLayout(m_deviceResources.logicalDevice(), m_pipelineLayout, nullptr);
  125. vkFreeMemory(m_deviceResources.logicalDevice(), m_constantBufferDeviceMemory, nullptr);
  126. vkDestroyBuffer(m_deviceResources.logicalDevice(), m_buffer, nullptr);
  127. vkFreeDescriptorSets(m_deviceResources.logicalDevice(), m_deviceResources.descriptorPool(), 1, &m_descriptorSet);
  128. vkDestroyDescriptorSetLayout(m_deviceResources.logicalDevice(), m_descriptorSetLayout, nullptr);
  129. vkDestroyShaderModule(m_deviceResources.logicalDevice(), m_shaderModule, nullptr);
  130. }
  131. void NVSharpen::update(float sharpness, uint32_t inputWidth, uint32_t inputHeight)
  132. {
  133. NVSharpenUpdateConfig(m_config, sharpness,
  134. 0, 0, inputWidth, inputHeight, inputWidth, inputHeight,
  135. 0, 0, NISHDRMode::None);
  136. m_outputWidth = inputWidth;
  137. m_outputHeight = inputHeight;
  138. }
  139. void NVSharpen::dispatch(VkImageView inputSrv, VkImageView outputUav)
  140. {
  141. const auto offset = m_constantBufferStride * m_deviceResources.swapchainIndex();
  142. memcpy(m_constantMemory + offset, &m_config, sizeof(m_config));
  143. VkDescriptorBufferInfo descBuffInfo{};
  144. descBuffInfo.buffer = m_buffer;
  145. descBuffInfo.offset = offset;
  146. descBuffInfo.range = sizeof(NISConfig);
  147. VkWriteDescriptorSet inWriteDescSet{};
  148. VkWriteDescriptorSet outWriteDescSet{};
  149. VkDescriptorImageInfo inDescInfo{};
  150. inDescInfo.imageView = inputSrv;
  151. inDescInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  152. inWriteDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  153. inWriteDescSet.dstSet = m_descriptorSet;
  154. inWriteDescSet.dstBinding = IN_TEX_BINDING;
  155. inWriteDescSet.descriptorCount = 1;
  156. inWriteDescSet.descriptorType = IN_TEX_DESC_TYPE;
  157. inWriteDescSet.pImageInfo = &inDescInfo;
  158. VkDescriptorImageInfo outDescInfo{};
  159. outDescInfo.imageView = outputUav;
  160. outDescInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
  161. outWriteDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  162. outWriteDescSet.dstSet = m_descriptorSet;
  163. outWriteDescSet.dstBinding = OUT_TEX_BINDING;
  164. outWriteDescSet.descriptorCount = 1;
  165. outWriteDescSet.descriptorType = OUT_TEX_DESC_TYPE;
  166. outWriteDescSet.pImageInfo = &outDescInfo;
  167. const VkWriteDescriptorSet writeDescSets[] = {
  168. inWriteDescSet,
  169. outWriteDescSet
  170. };
  171. constexpr auto sizeWriteDescSets = static_cast<uint32_t>(std::size(writeDescSets));
  172. vkUpdateDescriptorSets(m_deviceResources.logicalDevice(), sizeWriteDescSets, writeDescSets, 0, nullptr);
  173. auto cmdBuffer = m_deviceResources.commandBuffer();
  174. vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
  175. vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, 1, &m_descriptorSet, 1, (uint32_t*)&descBuffInfo.offset);
  176. uint32_t gridX = uint32_t(std::ceil(m_outputWidth / float(m_blockWidth)));
  177. uint32_t gridY = uint32_t(std::ceil(m_outputHeight / float(m_blockHeight)));
  178. vkCmdDispatch(cmdBuffer, gridX, gridY, 1);
  179. }