BilinearUpscale.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // The MIT License(MIT)
  2. //
  3. // Copyright(c) 2021 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 "BilinearUpscale.h"
  22. #include "DXUtilities.h"
  23. #include "Utilities.h"
  24. #include <iostream>
  25. #include <d3dcompiler.h>
  26. void BilinearUpdateConfig(BilinearUpscaleConfig& config,
  27. uint32_t inputViewportOriginX, uint32_t inputViewportOriginY,
  28. uint32_t inputViewportWidth, uint32_t inputViewportHeight,
  29. uint32_t inputTextureWidth, uint32_t inputTextureHeight,
  30. uint32_t outputViewportOriginX, uint32_t outputViewportOriginY,
  31. uint32_t outputViewportWidth, uint32_t outputViewportHeight,
  32. uint32_t outputTextureWidth, uint32_t outputTextureHeight)
  33. {
  34. config.kInputViewportHeight = inputViewportHeight;
  35. config.kInputViewportWidth = inputViewportWidth;
  36. config.kOutputViewportHeight = outputViewportHeight;
  37. config.kOutputViewportWidth = outputViewportWidth;
  38. config.kInputViewportOriginX = inputViewportOriginX;
  39. config.kInputViewportOriginY = inputViewportOriginY;
  40. config.kOutputViewportOriginX = outputViewportOriginX;
  41. config.kOutputViewportOriginY = outputViewportOriginY;
  42. config.kScaleX = inputTextureWidth / float(outputTextureWidth);
  43. config.kScaleY = inputTextureWidth / float(outputTextureWidth);
  44. config.kDstNormX = 1.f / outputTextureWidth;
  45. config.kDstNormY = 1.f / outputTextureHeight;
  46. config.kSrcNormX = 1.f / inputTextureWidth;
  47. config.kSrcNormY = 1.f / inputTextureHeight;
  48. }
  49. BilinearUpscale::BilinearUpscale(DeviceResources& deviceResources)
  50. : m_deviceResources(deviceResources)
  51. , m_outputWidth(0)
  52. , m_outputHeight(0)
  53. {
  54. std::string skBlockWidth = std::to_string(kBlockWidth);
  55. std::string skBlockHeight = std::to_string(kBlockHeight);
  56. const D3D_SHADER_MACRO shaderMacros[] = { {"kBlockWidth", skBlockWidth.c_str() },
  57. {"kBlockHeight", skBlockHeight.c_str() },
  58. { nullptr, nullptr } };
  59. static const char* upscaleShader =
  60. R"(
  61. Texture2D in_texture : register(t0); // image srv
  62. RWTexture2D<unorm float4> out_texture : register(u1); // working uav
  63. cbuffer cb : register(b0) {
  64. uint kInputViewportOriginX;
  65. uint kInputViewportOriginY;
  66. uint kInputViewportWidth;
  67. uint kInputViewportHeight;
  68. uint kOutputViewportOriginX;
  69. uint kOutputViewportOriginY;
  70. uint kOutputViewportWidth;
  71. uint kOutputViewportHeight;
  72. float kScaleX;
  73. float kScaleY;
  74. float kDstNormX;
  75. float kDstNormY;
  76. float kSrcNormX;
  77. float kSrcNormY;
  78. }
  79. SamplerState samplerLinearClamp : register(s0);
  80. [numthreads(kBlockWidth, kBlockHeight, 1)]
  81. void Bilinear(uint3 id : SV_DispatchThreadID) {
  82. float dX = (id.x + 0.5f) * kScaleX;
  83. float dY = (id.y + 0.5f) * kScaleY;
  84. if (id.x < kOutputViewportWidth && id.y < kOutputViewportHeight && dX < kInputViewportWidth && dY < kInputViewportHeight) {
  85. float uvX = (dX + kInputViewportOriginX) * kSrcNormX;
  86. float uvY = (dY + kInputViewportOriginY) * kSrcNormY;
  87. uint dstX = id.x + kOutputViewportOriginX;
  88. uint dstY = id.y + kOutputViewportOriginY;
  89. out_texture[uint2(dstX, dstY)] = in_texture.SampleLevel(samplerLinearClamp, float2(uvX, uvY), 0);
  90. }
  91. }
  92. )";
  93. DX::CompileComputeShader(m_deviceResources.device(), upscaleShader, strlen(upscaleShader), "Bilinear", &m_computeShader, shaderMacros);
  94. BilinearUpdateConfig(m_config, 0, 0, 100, 100, 100, 100, 0, 0, 100, 100, 100, 100);
  95. m_deviceResources.createLinearClampSampler(&m_LinearClampSampler);
  96. D3D11_BUFFER_DESC bDesc;
  97. bDesc.ByteWidth = sizeof(BilinearUpscaleConfig);
  98. bDesc.Usage = D3D11_USAGE_DYNAMIC;
  99. bDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  100. bDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
  101. bDesc.MiscFlags = 0;
  102. bDesc.StructureByteStride = 0;
  103. D3D11_SUBRESOURCE_DATA srData;
  104. srData.pSysMem = &m_config;
  105. srData.SysMemPitch = sizeof(BilinearUpscaleConfig);
  106. srData.SysMemSlicePitch = 1;
  107. DX::ThrowIfFailed(m_deviceResources.device()->CreateBuffer(&bDesc, &srData, &m_csBuffer));
  108. }
  109. void BilinearUpscale::update(uint32_t inputWidth, uint32_t inputHeight, uint32_t outputWidth, uint32_t outputHeight)
  110. {
  111. BilinearUpdateConfig(m_config, 0, 0, inputWidth, inputHeight, inputWidth, inputHeight, 0, 0, outputWidth, outputHeight, outputWidth, outputHeight);
  112. D3D11_MAPPED_SUBRESOURCE mappedResource;
  113. m_deviceResources.context()->Map(m_csBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
  114. BilinearUpscaleConfig* dataPtr = (BilinearUpscaleConfig*)mappedResource.pData;
  115. memcpy(dataPtr, &m_config, sizeof(BilinearUpscaleConfig));
  116. m_deviceResources.context()->Unmap(m_csBuffer.Get(), 0);
  117. m_outputWidth = outputWidth;
  118. m_outputHeight = outputHeight;
  119. }
  120. void BilinearUpscale::dispatch(ID3D11ShaderResourceView* const* input, ID3D11UnorderedAccessView* const* output)
  121. {
  122. auto context = m_deviceResources.context();
  123. context->CSSetShader(m_computeShader.Get(), nullptr, 0);
  124. context->CSSetShaderResources(0, 1, input);
  125. context->CSSetUnorderedAccessViews(1, 1, output, nullptr);
  126. context->CSSetSamplers(0, 1, m_LinearClampSampler.GetAddressOf());
  127. context->CSSetConstantBuffers(0, 1, m_csBuffer.GetAddressOf());
  128. context->Dispatch(UINT(std::ceil(m_outputWidth / float(kBlockWidth))), UINT(std::ceil(m_outputHeight / float(kBlockHeight))), 1);
  129. }