Spirv.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/ShaderCompiler/Spirv.h>
  6. #include <AnKi/ShaderCompiler/Dxc.h>
  7. #include <SpirvCross/spirv_cross.hpp>
  8. namespace anki {
  9. Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
  10. {
  11. spirv_cross::Compiler spvc(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32));
  12. spirv_cross::ShaderResources rsrc = spvc.get_shader_resources();
  13. spirv_cross::ShaderResources rsrcActive = spvc.get_shader_resources(spvc.get_active_interface_variables());
  14. auto func = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& resources, const DescriptorType origType) -> Error {
  15. for(const spirv_cross::Resource& r : resources)
  16. {
  17. const U32 id = r.id;
  18. const U32 set = spvc.get_decoration(id, spv::Decoration::DecorationDescriptorSet);
  19. const U32 binding = spvc.get_decoration(id, spv::Decoration::DecorationBinding);
  20. if(set >= kMaxRegisterSpaces && set != ANKI_VK_BINDLESS_TEXTURES_DESCRIPTOR_SET)
  21. {
  22. errorStr.sprintf("Exceeded set for: %s", r.name.c_str());
  23. return Error::kUserData;
  24. }
  25. const spirv_cross::SPIRType& typeInfo = spvc.get_type(r.type_id);
  26. U32 arraySize = 1;
  27. if(typeInfo.array.size() != 0)
  28. {
  29. if(typeInfo.array.size() != 1)
  30. {
  31. errorStr.sprintf("Only 1D arrays are supported: %s", r.name.c_str());
  32. return Error::kUserData;
  33. }
  34. if(set == ANKI_VK_BINDLESS_TEXTURES_DESCRIPTOR_SET && typeInfo.array[0] != 0)
  35. {
  36. errorStr.sprintf("Only the bindless descriptor set can be an unbound array: %s", r.name.c_str());
  37. return Error::kUserData;
  38. }
  39. arraySize = typeInfo.array[0];
  40. }
  41. // Images are special, they might be texel buffers
  42. DescriptorType type = origType;
  43. if((type == DescriptorType::kSrvTexture || type == DescriptorType::kUavTexture) && typeInfo.image.dim == spv::DimBuffer)
  44. {
  45. if(typeInfo.image.sampled == 1)
  46. {
  47. type = DescriptorType::kSrvTexelBuffer;
  48. }
  49. else
  50. {
  51. ANKI_ASSERT(typeInfo.image.sampled == 2);
  52. type = DescriptorType::kUavTexelBuffer;
  53. }
  54. }
  55. if(set == ANKI_VK_BINDLESS_TEXTURES_DESCRIPTOR_SET)
  56. {
  57. // Bindless dset
  58. if(arraySize != 0)
  59. {
  60. errorStr.sprintf("Unexpected unbound array for bindless: %s", r.name.c_str());
  61. }
  62. if(type != DescriptorType::kSrvTexture)
  63. {
  64. errorStr.sprintf("Unexpected bindless binding: %s", r.name.c_str());
  65. return Error::kUserData;
  66. }
  67. refl.m_descriptor.m_hasVkBindlessDescriptorSet = true;
  68. }
  69. else
  70. {
  71. // Regular binding
  72. // Use the binding to find out if it's a read or write storage buffer, there is no other way
  73. if(origType == DescriptorType::kSrvStructuredBuffer
  74. && (binding < kDxcVkBindingShifts[set][HlslResourceType::kSrv]
  75. || binding >= kDxcVkBindingShifts[set][HlslResourceType::kSrv] + 1000))
  76. {
  77. type = DescriptorType::kUavStructuredBuffer;
  78. }
  79. const HlslResourceType hlslResourceType = descriptorTypeToHlslResourceType(type);
  80. if(binding < kDxcVkBindingShifts[set][hlslResourceType] || binding >= kDxcVkBindingShifts[set][hlslResourceType] + 1000)
  81. {
  82. errorStr.sprintf("Unexpected binding: %s", r.name.c_str());
  83. return Error::kUserData;
  84. }
  85. ShaderReflectionBinding akBinding;
  86. akBinding.m_registerBindingPoint = binding - kDxcVkBindingShifts[set][hlslResourceType];
  87. akBinding.m_arraySize = U16(arraySize);
  88. akBinding.m_type = type;
  89. refl.m_descriptor.m_bindings[set][refl.m_descriptor.m_bindingCounts[set]] = akBinding;
  90. ++refl.m_descriptor.m_bindingCounts[set];
  91. }
  92. }
  93. return Error::kNone;
  94. };
  95. Error err = func(rsrc.uniform_buffers, DescriptorType::kConstantBuffer);
  96. if(err)
  97. {
  98. return err;
  99. }
  100. err = func(rsrc.separate_images, DescriptorType::kSrvTexture); // This also handles texel buffers
  101. if(err)
  102. {
  103. return err;
  104. }
  105. err = func(rsrc.separate_samplers, DescriptorType::kSampler);
  106. if(err)
  107. {
  108. return err;
  109. }
  110. err = func(rsrc.storage_buffers, DescriptorType::kSrvStructuredBuffer);
  111. if(err)
  112. {
  113. return err;
  114. }
  115. err = func(rsrc.storage_images, DescriptorType::kUavTexture);
  116. if(err)
  117. {
  118. return err;
  119. }
  120. err = func(rsrc.acceleration_structures, DescriptorType::kAccelerationStructure);
  121. if(err)
  122. {
  123. return err;
  124. }
  125. for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
  126. {
  127. std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
  128. }
  129. // Color attachments
  130. if(type == ShaderType::kPixel)
  131. {
  132. for(const spirv_cross::Resource& r : rsrc.stage_outputs)
  133. {
  134. const U32 id = r.id;
  135. const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
  136. refl.m_pixel.m_colorRenderTargetWritemask.set(location);
  137. }
  138. }
  139. // Push consts
  140. if(rsrc.push_constant_buffers.size() == 1)
  141. {
  142. const U32 blockSize = U32(spvc.get_declared_struct_size(spvc.get_type(rsrc.push_constant_buffers[0].base_type_id)));
  143. if(blockSize == 0 || (blockSize % 16) != 0 || blockSize > kMaxFastConstantsSize)
  144. {
  145. errorStr.sprintf("Incorrect push constants size");
  146. return Error::kUserData;
  147. }
  148. refl.m_descriptor.m_fastConstantsSize = blockSize;
  149. }
  150. // Attribs
  151. if(type == ShaderType::kVertex)
  152. {
  153. for(const spirv_cross::Resource& r : rsrcActive.stage_inputs)
  154. {
  155. VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
  156. #define ANKI_ATTRIB_NAME(x) "in.var." #x
  157. if(r.name == ANKI_ATTRIB_NAME(POSITION))
  158. {
  159. a = VertexAttributeSemantic::kPosition;
  160. }
  161. else if(r.name == ANKI_ATTRIB_NAME(NORMAL))
  162. {
  163. a = VertexAttributeSemantic::kNormal;
  164. }
  165. else if(r.name == ANKI_ATTRIB_NAME(TEXCOORD0) || r.name == ANKI_ATTRIB_NAME(TEXCOORD))
  166. {
  167. a = VertexAttributeSemantic::kTexCoord;
  168. }
  169. else if(r.name == ANKI_ATTRIB_NAME(COLOR))
  170. {
  171. a = VertexAttributeSemantic::kColor;
  172. }
  173. else if(r.name == ANKI_ATTRIB_NAME(MISC0) || r.name == ANKI_ATTRIB_NAME(MISC))
  174. {
  175. a = VertexAttributeSemantic::kMisc0;
  176. }
  177. else if(r.name == ANKI_ATTRIB_NAME(MISC1))
  178. {
  179. a = VertexAttributeSemantic::kMisc1;
  180. }
  181. else if(r.name == ANKI_ATTRIB_NAME(MISC2))
  182. {
  183. a = VertexAttributeSemantic::kMisc2;
  184. }
  185. else if(r.name == ANKI_ATTRIB_NAME(MISC3))
  186. {
  187. a = VertexAttributeSemantic::kMisc3;
  188. }
  189. else
  190. {
  191. errorStr.sprintf("Unexpected attribute name: %s", r.name.c_str());
  192. return Error::kUserData;
  193. }
  194. #undef ANKI_ATTRIB_NAME
  195. refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
  196. const U32 id = r.id;
  197. const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
  198. if(location > kMaxU8)
  199. {
  200. errorStr.sprintf("Too high location value for attribute: %s", r.name.c_str());
  201. return Error::kUserData;
  202. }
  203. refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(location);
  204. }
  205. }
  206. // Discards?
  207. if(type == ShaderType::kPixel)
  208. {
  209. visitSpirv(ConstWeakArray<U32>(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32)),
  210. [&](U32 cmd, [[maybe_unused]] ConstWeakArray<U32> instructions) {
  211. if(cmd == spv::OpKill)
  212. {
  213. refl.m_pixel.m_discards = true;
  214. }
  215. });
  216. }
  217. return Error::kNone;
  218. }
  219. } // end namespace anki