emit_spirv_memory.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <bit>
  5. #include "shader_recompiler/backend/spirv/emit_spirv.h"
  6. namespace Shader::Backend::SPIRV {
  7. namespace {
  8. Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) {
  9. if (offset.IsImmediate()) {
  10. const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)};
  11. return ctx.Constant(ctx.U32[1], imm_offset);
  12. }
  13. const u32 shift{static_cast<u32>(std::countr_zero(element_size))};
  14. const Id index{ctx.Def(offset)};
  15. if (shift == 0) {
  16. return index;
  17. }
  18. const Id shift_id{ctx.Constant(ctx.U32[1], shift)};
  19. return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id);
  20. }
  21. Id StoragePointer(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  22. const StorageTypeDefinition& type_def, size_t element_size,
  23. Id StorageDefinitions::*member_ptr) {
  24. if (!binding.IsImmediate()) {
  25. throw NotImplementedException("Dynamic storage buffer indexing");
  26. }
  27. const Id ssbo{ctx.ssbos[binding.U32()].*member_ptr};
  28. const Id index{StorageIndex(ctx, offset, element_size)};
  29. return ctx.OpAccessChain(type_def.element, ssbo, ctx.u32_zero_value, index);
  30. }
  31. Id LoadStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id result_type,
  32. const StorageTypeDefinition& type_def, size_t element_size,
  33. Id StorageDefinitions::*member_ptr) {
  34. const Id pointer{StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr)};
  35. return ctx.OpLoad(result_type, pointer);
  36. }
  37. void WriteStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value,
  38. const StorageTypeDefinition& type_def, size_t element_size,
  39. Id StorageDefinitions::*member_ptr) {
  40. const Id pointer{StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr)};
  41. ctx.OpStore(pointer, value);
  42. }
  43. } // Anonymous namespace
  44. void EmitLoadGlobalU8(EmitContext&) {
  45. throw NotImplementedException("SPIR-V Instruction");
  46. }
  47. void EmitLoadGlobalS8(EmitContext&) {
  48. throw NotImplementedException("SPIR-V Instruction");
  49. }
  50. void EmitLoadGlobalU16(EmitContext&) {
  51. throw NotImplementedException("SPIR-V Instruction");
  52. }
  53. void EmitLoadGlobalS16(EmitContext&) {
  54. throw NotImplementedException("SPIR-V Instruction");
  55. }
  56. void EmitLoadGlobal32(EmitContext&) {
  57. throw NotImplementedException("SPIR-V Instruction");
  58. }
  59. void EmitLoadGlobal64(EmitContext&) {
  60. throw NotImplementedException("SPIR-V Instruction");
  61. }
  62. void EmitLoadGlobal128(EmitContext&) {
  63. throw NotImplementedException("SPIR-V Instruction");
  64. }
  65. void EmitWriteGlobalU8(EmitContext&) {
  66. throw NotImplementedException("SPIR-V Instruction");
  67. }
  68. void EmitWriteGlobalS8(EmitContext&) {
  69. throw NotImplementedException("SPIR-V Instruction");
  70. }
  71. void EmitWriteGlobalU16(EmitContext&) {
  72. throw NotImplementedException("SPIR-V Instruction");
  73. }
  74. void EmitWriteGlobalS16(EmitContext&) {
  75. throw NotImplementedException("SPIR-V Instruction");
  76. }
  77. void EmitWriteGlobal32(EmitContext&) {
  78. throw NotImplementedException("SPIR-V Instruction");
  79. }
  80. void EmitWriteGlobal64(EmitContext&) {
  81. throw NotImplementedException("SPIR-V Instruction");
  82. }
  83. void EmitWriteGlobal128(EmitContext&) {
  84. throw NotImplementedException("SPIR-V Instruction");
  85. }
  86. Id EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  87. return ctx.OpUConvert(ctx.U32[1],
  88. LoadStorage(ctx, binding, offset, ctx.U8, ctx.storage_types.U8,
  89. sizeof(u8), &StorageDefinitions::U8));
  90. }
  91. Id EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  92. return ctx.OpSConvert(ctx.U32[1],
  93. LoadStorage(ctx, binding, offset, ctx.S8, ctx.storage_types.S8,
  94. sizeof(s8), &StorageDefinitions::S8));
  95. }
  96. Id EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  97. return ctx.OpUConvert(ctx.U32[1],
  98. LoadStorage(ctx, binding, offset, ctx.U16, ctx.storage_types.U16,
  99. sizeof(u16), &StorageDefinitions::U16));
  100. }
  101. Id EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  102. return ctx.OpSConvert(ctx.U32[1],
  103. LoadStorage(ctx, binding, offset, ctx.S16, ctx.storage_types.S16,
  104. sizeof(s16), &StorageDefinitions::S16));
  105. }
  106. Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  107. return LoadStorage(ctx, binding, offset, ctx.U32[1], ctx.storage_types.U32, sizeof(u32),
  108. &StorageDefinitions::U32);
  109. }
  110. Id EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  111. return LoadStorage(ctx, binding, offset, ctx.U32[2], ctx.storage_types.U32x2, sizeof(u32[2]),
  112. &StorageDefinitions::U32x2);
  113. }
  114. Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
  115. return LoadStorage(ctx, binding, offset, ctx.U32[4], ctx.storage_types.U32x4, sizeof(u32[4]),
  116. &StorageDefinitions::U32x4);
  117. }
  118. void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  119. Id value) {
  120. WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8,
  121. sizeof(u8), &StorageDefinitions::U8);
  122. }
  123. void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  124. Id value) {
  125. WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8,
  126. sizeof(s8), &StorageDefinitions::S8);
  127. }
  128. void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  129. Id value) {
  130. WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16,
  131. sizeof(u16), &StorageDefinitions::U16);
  132. }
  133. void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  134. Id value) {
  135. WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16,
  136. sizeof(s16), &StorageDefinitions::S16);
  137. }
  138. void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  139. Id value) {
  140. WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32),
  141. &StorageDefinitions::U32);
  142. }
  143. void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  144. Id value) {
  145. WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x2, sizeof(u32[2]),
  146. &StorageDefinitions::U32x2);
  147. }
  148. void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
  149. Id value) {
  150. WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x4, sizeof(u32[4]),
  151. &StorageDefinitions::U32x4);
  152. }
  153. } // namespace Shader::Backend::SPIRV