AppRenderer.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. #pragma once
  22. #include "AppRenderer.h"
  23. using namespace Microsoft::WRL;
  24. AppRenderer::AppRenderer(DeviceResources& deviceResources, UIData& ui, const std::vector<std::string>& shaderPaths)
  25. : m_ui(ui)
  26. , m_deviceResources(deviceResources)
  27. , m_NVSharpen(deviceResources, shaderPaths)
  28. , m_NVScaler(deviceResources, shaderPaths)
  29. , m_upscale(deviceResources)
  30. {}
  31. bool AppRenderer::update()
  32. {
  33. bool updateWindowSize = m_currentFilePath != m_ui.FilePath || m_currentScale != m_ui.Scale;
  34. bool updateSharpeness = m_ui.Sharpness != m_currentSharpness;
  35. if (updateWindowSize)
  36. {
  37. if (m_currentFilePath != m_ui.FilePath)
  38. {
  39. std::vector<uint8_t> image;
  40. uint32_t rowPitch;
  41. img::load(m_ui.FilePath.string(), image, m_inputWidth, m_inputHeight, rowPitch, img::Fmt::R8G8B8A8);
  42. m_deviceResources.createTexture2D(m_inputWidth, m_inputHeight, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_USAGE_DEFAULT, image.data(), rowPitch, rowPitch * m_inputHeight, &m_input);
  43. m_deviceResources.createSRV(m_input.Get(), DXGI_FORMAT_R8G8B8A8_UNORM, &m_inputSRV);
  44. m_currentFilePath = m_ui.FilePath;
  45. }
  46. if (m_ui.Scale == 100)
  47. {
  48. m_outputWidth = m_inputWidth;
  49. m_outputHeight = m_inputHeight;
  50. }
  51. else
  52. {
  53. m_outputWidth = uint32_t(std::ceil(m_inputWidth * 100.f / m_ui.Scale));
  54. m_outputHeight = uint32_t(std::ceil(m_inputHeight * 100.f / m_ui.Scale));
  55. }
  56. m_deviceResources.createTexture2D(m_outputWidth, m_outputHeight, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_USAGE_DEFAULT, nullptr , 0, 0, &m_output);
  57. m_deviceResources.createUAV(m_output.Get(), DXGI_FORMAT_R8G8B8A8_UNORM, &m_outputUAV);
  58. m_currentScale = m_ui.Scale;
  59. m_ui.InputWidth = m_inputWidth;
  60. m_ui.InputHeight = m_inputHeight;
  61. m_ui.OutputWidth = m_outputWidth;
  62. m_ui.OutputHeight = m_outputHeight;
  63. }
  64. if (updateSharpeness)
  65. {
  66. m_currentSharpness = m_ui.Sharpness;
  67. }
  68. if (updateSharpeness || updateWindowSize)
  69. {
  70. m_upscale.update(m_inputWidth, m_inputHeight, m_outputWidth, m_outputHeight);
  71. m_NVScaler.update(m_currentSharpness / 100.f, m_inputWidth, m_inputHeight, m_outputWidth, m_outputHeight);
  72. m_NVSharpen.update(m_currentSharpness / 100.f, m_inputWidth, m_inputHeight);
  73. }
  74. return updateWindowSize;
  75. }
  76. void AppRenderer::saveOutput(const std::string& filename)
  77. {
  78. D3D11_TEXTURE2D_DESC desc;
  79. m_output->GetDesc(&desc);
  80. img::Fmt format = img::Fmt::R8G8B8A8;
  81. switch (desc.Format)
  82. {
  83. case DXGI_FORMAT_R8G8B8A8_UNORM:
  84. format = img::Fmt::R8G8B8A8;
  85. break;
  86. case DXGI_FORMAT_R32G32B32A32_FLOAT:
  87. format = img::Fmt::R32G32B32A32;
  88. break;
  89. case DXGI_FORMAT_R16G16B16A16_FLOAT:
  90. format = img::Fmt::R16G16B16A16;
  91. break;
  92. }
  93. std::vector<uint8_t> data;
  94. uint32_t width, height, rowPitch = 0;
  95. constexpr uint32_t channels = 4;
  96. m_deviceResources.getTextureData(m_output.Get(), data, width, height, rowPitch);
  97. img::save(filename, data.data(), width, height, channels, rowPitch, format);
  98. }
  99. void AppRenderer::render()
  100. {
  101. auto context = m_deviceResources.context();
  102. D3D11_QUERY_DESC desc;
  103. ZeroMemory(&desc, sizeof(D3D11_QUERY_DESC));
  104. desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
  105. m_deviceResources.device()->CreateQuery(&desc, &m_timeStampDis);
  106. desc.Query = D3D11_QUERY_TIMESTAMP;
  107. m_deviceResources.device()->CreateQuery(&desc, &m_timeStampStart);
  108. m_deviceResources.device()->CreateQuery(&desc, &m_timeStampEnd);
  109. context->Begin(m_timeStampDis.Get());
  110. context->End(m_timeStampStart.Get());
  111. if (!m_ui.EnableNVScaler)
  112. {
  113. if (m_ui.Scale == 100)
  114. {
  115. context->CopyResource(m_output.Get(), m_input.Get());
  116. }
  117. else
  118. {
  119. m_upscale.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
  120. }
  121. }
  122. else {
  123. if (m_ui.Scale == 100)
  124. {
  125. m_NVSharpen.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
  126. }
  127. else
  128. {
  129. m_NVScaler.dispatch(m_inputSRV.GetAddressOf(), m_outputUAV.GetAddressOf());
  130. }
  131. }
  132. context->End(m_timeStampEnd.Get());
  133. context->End(m_timeStampDis.Get());
  134. D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disData;
  135. while (context->GetData(m_timeStampDis.Get(), &disData, sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), 0) != S_OK);
  136. UINT64 startime;
  137. UINT64 endtime;
  138. while (context->GetData(m_timeStampStart.Get(), &startime, sizeof(UINT64), 0) != S_OK);
  139. while (context->GetData(m_timeStampEnd.Get(), &endtime, sizeof(UINT64), 0) != S_OK);
  140. if (!disData.Disjoint)
  141. {
  142. m_ui.FilterTime = (endtime - startime) / double(disData.Frequency) * 1E6;
  143. }
  144. D3D11_BOX sourceRegion;
  145. sourceRegion.left = 0;
  146. sourceRegion.right = m_deviceResources.width();
  147. sourceRegion.top = 0;
  148. sourceRegion.bottom = m_deviceResources.height();
  149. sourceRegion.front = 0;
  150. sourceRegion.back = 1;
  151. context->CopySubresourceRegion(m_deviceResources.renderTarget(), 0, 0, 0, 0, m_output.Get(), 0, &sourceRegion);
  152. context->OMSetRenderTargets(1, m_deviceResources.targetViewAddress(), nullptr);
  153. }