vk_fsr.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <cmath>
  4. #include "common/bit_cast.h"
  5. #include "common/common_types.h"
  6. #include "common/div_ceil.h"
  7. #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_comp_spv.h"
  8. #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h"
  9. #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp16_comp_spv.h"
  10. #include "video_core/host_shaders/vulkan_fidelityfx_fsr_rcas_fp32_comp_spv.h"
  11. #include "video_core/renderer_vulkan/vk_fsr.h"
  12. #include "video_core/renderer_vulkan/vk_scheduler.h"
  13. #include "video_core/renderer_vulkan/vk_shader_util.h"
  14. #include "video_core/vulkan_common/vulkan_device.h"
  15. namespace Vulkan {
  16. namespace {
  17. // Reimplementations of the constant generating functions in ffx_fsr1.h
  18. // GCC generated a lot of warnings when using the official header.
  19. u32 AU1_AH1_AF1(f32 f) {
  20. static constexpr u32 base[512]{
  21. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  22. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  23. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  24. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  25. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  26. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  27. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  28. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  29. 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  30. 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040,
  31. 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00, 0x2000,
  32. 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400, 0x4800, 0x4c00,
  33. 0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800,
  34. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  35. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  36. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  37. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  38. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  39. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  40. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  41. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  42. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  43. 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
  44. 0x7bff, 0x7bff, 0x7bff, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  45. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  46. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  47. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  48. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  49. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  50. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  51. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  52. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  53. 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008,
  54. 0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400,
  55. 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00, 0xc000,
  56. 0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, 0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00,
  57. 0xf000, 0xf400, 0xf800, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  58. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  59. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  60. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  61. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  62. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  63. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  64. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  65. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  66. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  67. 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff, 0xfbff,
  68. };
  69. static constexpr s8 shift[512]{
  70. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  71. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  72. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  73. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  74. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  75. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  76. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16,
  77. 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
  78. 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
  79. 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  80. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  81. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  82. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  83. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  84. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  85. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  86. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  87. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  88. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  89. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  90. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  91. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  92. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  93. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17,
  94. 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
  95. 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
  96. 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  97. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  98. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  99. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  100. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  101. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  102. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  103. 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  104. 0x18, 0x18,
  105. };
  106. const u32 u = Common::BitCast<u32>(f);
  107. const u32 i = u >> 23;
  108. return base[i] + ((u & 0x7fffff) >> shift[i]);
  109. }
  110. u32 AU1_AH2_AF2(f32 a[2]) {
  111. return AU1_AH1_AF1(a[0]) + (AU1_AH1_AF1(a[1]) << 16);
  112. }
  113. void FsrEasuCon(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4], f32 inputViewportInPixelsX,
  114. f32 inputViewportInPixelsY, f32 inputSizeInPixelsX, f32 inputSizeInPixelsY,
  115. f32 outputSizeInPixelsX, f32 outputSizeInPixelsY) {
  116. con0[0] = Common::BitCast<u32>(inputViewportInPixelsX / outputSizeInPixelsX);
  117. con0[1] = Common::BitCast<u32>(inputViewportInPixelsY / outputSizeInPixelsY);
  118. con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f);
  119. con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f);
  120. con1[0] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX);
  121. con1[1] = Common::BitCast<u32>(1.0f / inputSizeInPixelsY);
  122. con1[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX);
  123. con1[3] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsY);
  124. con2[0] = Common::BitCast<u32>(-1.0f / inputSizeInPixelsX);
  125. con2[1] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY);
  126. con2[2] = Common::BitCast<u32>(1.0f / inputSizeInPixelsX);
  127. con2[3] = Common::BitCast<u32>(2.0f / inputSizeInPixelsY);
  128. con3[0] = Common::BitCast<u32>(0.0f / inputSizeInPixelsX);
  129. con3[1] = Common::BitCast<u32>(4.0f / inputSizeInPixelsY);
  130. con3[2] = con3[3] = 0;
  131. }
  132. void FsrEasuConOffset(u32 con0[4], u32 con1[4], u32 con2[4], u32 con3[4],
  133. f32 inputViewportInPixelsX, f32 inputViewportInPixelsY,
  134. f32 inputSizeInPixelsX, f32 inputSizeInPixelsY, f32 outputSizeInPixelsX,
  135. f32 outputSizeInPixelsY, f32 inputOffsetInPixelsX, f32 inputOffsetInPixelsY) {
  136. FsrEasuCon(con0, con1, con2, con3, inputViewportInPixelsX, inputViewportInPixelsY,
  137. inputSizeInPixelsX, inputSizeInPixelsY, outputSizeInPixelsX, outputSizeInPixelsY);
  138. con0[2] = Common::BitCast<u32>(0.5f * inputViewportInPixelsX / outputSizeInPixelsX - 0.5f +
  139. inputOffsetInPixelsX);
  140. con0[3] = Common::BitCast<u32>(0.5f * inputViewportInPixelsY / outputSizeInPixelsY - 0.5f +
  141. inputOffsetInPixelsY);
  142. }
  143. void FsrRcasCon(u32* con, f32 sharpness) {
  144. sharpness = std::exp2f(-sharpness);
  145. f32 hSharp[2]{sharpness, sharpness};
  146. con[0] = Common::BitCast<u32>(sharpness);
  147. con[1] = AU1_AH2_AF2(hSharp);
  148. con[2] = 0;
  149. con[3] = 0;
  150. }
  151. } // Anonymous namespace
  152. FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image_count_,
  153. VkExtent2D output_size_)
  154. : device{device_}, memory_allocator{memory_allocator_}, image_count{image_count_},
  155. output_size{output_size_} {
  156. CreateImages();
  157. CreateSampler();
  158. CreateShaders();
  159. CreateDescriptorPool();
  160. CreateDescriptorSetLayout();
  161. CreateDescriptorSets();
  162. CreatePipelineLayout();
  163. CreatePipeline();
  164. }
  165. VkImageView FSR::Draw(VKScheduler& scheduler, size_t image_index, VkImageView image_view,
  166. VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect) {
  167. UpdateDescriptorSet(image_index, image_view);
  168. scheduler.Record([this, image_index, input_image_extent, crop_rect](vk::CommandBuffer cmdbuf) {
  169. const VkImageMemoryBarrier base_barrier{
  170. .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  171. .pNext = nullptr,
  172. .srcAccessMask = 0,
  173. .dstAccessMask = 0,
  174. .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
  175. .newLayout = VK_IMAGE_LAYOUT_GENERAL,
  176. .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  177. .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
  178. .image = {},
  179. .subresourceRange =
  180. {
  181. .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  182. .baseMipLevel = 0,
  183. .levelCount = 1,
  184. .baseArrayLayer = 0,
  185. .layerCount = 1,
  186. },
  187. };
  188. cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *easu_pipeline);
  189. std::array<u32, 4 * 4> push_constants;
  190. FsrEasuConOffset(
  191. push_constants.data() + 0, push_constants.data() + 4, push_constants.data() + 8,
  192. push_constants.data() + 12,
  193. static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()),
  194. static_cast<f32>(input_image_extent.width), static_cast<f32>(input_image_extent.height),
  195. static_cast<f32>(output_size.width), static_cast<f32>(output_size.height),
  196. static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top));
  197. cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants);
  198. {
  199. VkImageMemoryBarrier fsr_write_barrier = base_barrier;
  200. fsr_write_barrier.image = *images[image_index];
  201. fsr_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  202. cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
  203. VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, fsr_write_barrier);
  204. }
  205. cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
  206. descriptor_sets[image_index * 2], {});
  207. cmdbuf.Dispatch(Common::DivCeil(output_size.width, 16u),
  208. Common::DivCeil(output_size.height, 16u), 1);
  209. cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *rcas_pipeline);
  210. FsrRcasCon(push_constants.data(), 0.25f);
  211. cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants);
  212. {
  213. std::array<VkImageMemoryBarrier, 2> barriers;
  214. auto& fsr_read_barrier = barriers[0];
  215. auto& blit_write_barrier = barriers[1];
  216. fsr_read_barrier = base_barrier;
  217. fsr_read_barrier.image = *images[image_index];
  218. fsr_read_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
  219. fsr_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  220. blit_write_barrier = base_barrier;
  221. blit_write_barrier.image = *images[image_count + image_index];
  222. blit_write_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  223. blit_write_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
  224. cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
  225. VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, {}, {}, barriers);
  226. }
  227. cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
  228. descriptor_sets[image_index * 2 + 1], {});
  229. cmdbuf.Dispatch(Common::DivCeil(output_size.width, 16u),
  230. Common::DivCeil(output_size.height, 16u), 1);
  231. {
  232. std::array<VkImageMemoryBarrier, 1> barriers;
  233. auto& blit_read_barrier = barriers[0];
  234. blit_read_barrier = base_barrier;
  235. blit_read_barrier.image = *images[image_count + image_index];
  236. blit_read_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
  237. blit_read_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  238. cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
  239. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, {}, {}, barriers);
  240. }
  241. });
  242. return *image_views[image_count + image_index];
  243. }
  244. void FSR::CreateDescriptorPool() {
  245. const std::array<VkDescriptorPoolSize, 2> pool_sizes{{
  246. {
  247. .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
  248. .descriptorCount = static_cast<u32>(image_count * 2),
  249. },
  250. {
  251. .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
  252. .descriptorCount = static_cast<u32>(image_count * 2),
  253. },
  254. }};
  255. const VkDescriptorPoolCreateInfo ci{
  256. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
  257. .pNext = nullptr,
  258. .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
  259. .maxSets = static_cast<u32>(image_count * 2),
  260. .poolSizeCount = static_cast<u32>(pool_sizes.size()),
  261. .pPoolSizes = pool_sizes.data(),
  262. };
  263. descriptor_pool = device.GetLogical().CreateDescriptorPool(ci);
  264. }
  265. void FSR::CreateDescriptorSetLayout() {
  266. const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{
  267. {
  268. .binding = 0,
  269. .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
  270. .descriptorCount = 1,
  271. .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
  272. .pImmutableSamplers = sampler.address(),
  273. },
  274. {
  275. .binding = 1,
  276. .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
  277. .descriptorCount = 1,
  278. .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
  279. .pImmutableSamplers = sampler.address(),
  280. },
  281. }};
  282. const VkDescriptorSetLayoutCreateInfo ci{
  283. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
  284. .pNext = nullptr,
  285. .flags = 0,
  286. .bindingCount = static_cast<u32>(layout_bindings.size()),
  287. .pBindings = layout_bindings.data(),
  288. };
  289. descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci);
  290. }
  291. void FSR::CreateDescriptorSets() {
  292. const u32 sets = static_cast<u32>(image_count * 2);
  293. const std::vector layouts(sets, *descriptor_set_layout);
  294. const VkDescriptorSetAllocateInfo ai{
  295. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
  296. .pNext = nullptr,
  297. .descriptorPool = *descriptor_pool,
  298. .descriptorSetCount = sets,
  299. .pSetLayouts = layouts.data(),
  300. };
  301. descriptor_sets = descriptor_pool.Allocate(ai);
  302. }
  303. void FSR::CreateImages() {
  304. images.resize(image_count * 2);
  305. image_views.resize(image_count * 2);
  306. buffer_commits.resize(image_count * 2);
  307. for (size_t i = 0; i < image_count * 2; ++i) {
  308. images[i] = device.GetLogical().CreateImage(VkImageCreateInfo{
  309. .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  310. .pNext = nullptr,
  311. .flags = 0,
  312. .imageType = VK_IMAGE_TYPE_2D,
  313. .format = VK_FORMAT_R16G16B16A16_SFLOAT,
  314. .extent =
  315. {
  316. .width = output_size.width,
  317. .height = output_size.height,
  318. .depth = 1,
  319. },
  320. .mipLevels = 1,
  321. .arrayLayers = 1,
  322. .samples = VK_SAMPLE_COUNT_1_BIT,
  323. .tiling = VK_IMAGE_TILING_OPTIMAL,
  324. .usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
  325. VK_IMAGE_USAGE_SAMPLED_BIT,
  326. .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
  327. .queueFamilyIndexCount = 0,
  328. .pQueueFamilyIndices = nullptr,
  329. .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
  330. });
  331. buffer_commits[i] = memory_allocator.Commit(images[i], MemoryUsage::DeviceLocal);
  332. image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{
  333. .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
  334. .pNext = nullptr,
  335. .flags = 0,
  336. .image = *images[i],
  337. .viewType = VK_IMAGE_VIEW_TYPE_2D,
  338. .format = VK_FORMAT_R16G16B16A16_SFLOAT,
  339. .components =
  340. {
  341. .r = VK_COMPONENT_SWIZZLE_IDENTITY,
  342. .g = VK_COMPONENT_SWIZZLE_IDENTITY,
  343. .b = VK_COMPONENT_SWIZZLE_IDENTITY,
  344. .a = VK_COMPONENT_SWIZZLE_IDENTITY,
  345. },
  346. .subresourceRange =
  347. {
  348. .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
  349. .baseMipLevel = 0,
  350. .levelCount = 1,
  351. .baseArrayLayer = 0,
  352. .layerCount = 1,
  353. },
  354. });
  355. }
  356. }
  357. void FSR::CreatePipelineLayout() {
  358. VkPushConstantRange push_const{
  359. .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
  360. .offset = 0,
  361. .size = sizeof(std::array<u32, 4 * 4>),
  362. };
  363. VkPipelineLayoutCreateInfo ci{
  364. .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
  365. .pNext = nullptr,
  366. .flags = 0,
  367. .setLayoutCount = 1,
  368. .pSetLayouts = descriptor_set_layout.address(),
  369. .pushConstantRangeCount = 1,
  370. .pPushConstantRanges = &push_const,
  371. };
  372. pipeline_layout = device.GetLogical().CreatePipelineLayout(ci);
  373. }
  374. void FSR::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const {
  375. const auto fsr_image_view = *image_views[image_index];
  376. const auto blit_image_view = *image_views[image_count + image_index];
  377. const VkDescriptorImageInfo image_info{
  378. .sampler = VK_NULL_HANDLE,
  379. .imageView = image_view,
  380. .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
  381. };
  382. const VkDescriptorImageInfo fsr_image_info{
  383. .sampler = VK_NULL_HANDLE,
  384. .imageView = fsr_image_view,
  385. .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
  386. };
  387. const VkDescriptorImageInfo blit_image_info{
  388. .sampler = VK_NULL_HANDLE,
  389. .imageView = blit_image_view,
  390. .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
  391. };
  392. VkWriteDescriptorSet sampler_write{
  393. .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
  394. .pNext = nullptr,
  395. .dstSet = descriptor_sets[image_index * 2],
  396. .dstBinding = 0,
  397. .dstArrayElement = 0,
  398. .descriptorCount = 1,
  399. .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
  400. .pImageInfo = &image_info,
  401. .pBufferInfo = nullptr,
  402. .pTexelBufferView = nullptr,
  403. };
  404. VkWriteDescriptorSet output_write{
  405. .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
  406. .pNext = nullptr,
  407. .dstSet = descriptor_sets[image_index * 2],
  408. .dstBinding = 1,
  409. .dstArrayElement = 0,
  410. .descriptorCount = 1,
  411. .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
  412. .pImageInfo = &fsr_image_info,
  413. .pBufferInfo = nullptr,
  414. .pTexelBufferView = nullptr,
  415. };
  416. device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, output_write}, {});
  417. sampler_write.dstSet = descriptor_sets[image_index * 2 + 1];
  418. sampler_write.pImageInfo = &fsr_image_info;
  419. output_write.dstSet = descriptor_sets[image_index * 2 + 1];
  420. output_write.pImageInfo = &blit_image_info;
  421. device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, output_write}, {});
  422. }
  423. void FSR::CreateSampler() {
  424. const VkSamplerCreateInfo ci{
  425. .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
  426. .pNext = nullptr,
  427. .flags = 0,
  428. .magFilter = VK_FILTER_LINEAR,
  429. .minFilter = VK_FILTER_LINEAR,
  430. .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
  431. .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
  432. .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
  433. .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
  434. .mipLodBias = 0.0f,
  435. .anisotropyEnable = VK_FALSE,
  436. .maxAnisotropy = 0.0f,
  437. .compareEnable = VK_FALSE,
  438. .compareOp = VK_COMPARE_OP_NEVER,
  439. .minLod = 0.0f,
  440. .maxLod = 0.0f,
  441. .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
  442. .unnormalizedCoordinates = VK_FALSE,
  443. };
  444. sampler = device.GetLogical().CreateSampler(ci);
  445. }
  446. void FSR::CreateShaders() {
  447. if (device.IsFloat16Supported()) {
  448. easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP16_COMP_SPV);
  449. rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_COMP_SPV);
  450. } else {
  451. easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP32_COMP_SPV);
  452. rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_COMP_SPV);
  453. }
  454. }
  455. void FSR::CreatePipeline() {
  456. VkPipelineShaderStageCreateInfo shader_stage_easu{
  457. .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  458. .pNext = nullptr,
  459. .flags = 0,
  460. .stage = VK_SHADER_STAGE_COMPUTE_BIT,
  461. .module = *easu_shader,
  462. .pName = "main",
  463. .pSpecializationInfo = nullptr,
  464. };
  465. VkPipelineShaderStageCreateInfo shader_stage_rcas{
  466. .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
  467. .pNext = nullptr,
  468. .flags = 0,
  469. .stage = VK_SHADER_STAGE_COMPUTE_BIT,
  470. .module = *rcas_shader,
  471. .pName = "main",
  472. .pSpecializationInfo = nullptr,
  473. };
  474. VkComputePipelineCreateInfo pipeline_ci_easu{
  475. .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
  476. .pNext = nullptr,
  477. .flags = 0,
  478. .stage = shader_stage_easu,
  479. .layout = *pipeline_layout,
  480. .basePipelineHandle = VK_NULL_HANDLE,
  481. .basePipelineIndex = 0,
  482. };
  483. VkComputePipelineCreateInfo pipeline_ci_rcas{
  484. .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
  485. .pNext = nullptr,
  486. .flags = 0,
  487. .stage = shader_stage_rcas,
  488. .layout = *pipeline_layout,
  489. .basePipelineHandle = VK_NULL_HANDLE,
  490. .basePipelineIndex = 0,
  491. };
  492. easu_pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci_easu);
  493. rcas_pipeline = device.GetLogical().CreateComputePipeline(pipeline_ci_rcas);
  494. }
  495. } // namespace Vulkan