diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.cpp | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index d2dbd56d4..21900d387 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -12,6 +12,43 @@ | |||
| 12 | #include "shader_recompiler/backend/spirv/emit_context.h" | 12 | #include "shader_recompiler/backend/spirv/emit_context.h" |
| 13 | 13 | ||
| 14 | namespace Shader::Backend::SPIRV { | 14 | namespace Shader::Backend::SPIRV { |
| 15 | namespace { | ||
| 16 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | ||
| 17 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | ||
| 18 | const Id type{ctx.F32[1]}; | ||
| 19 | switch (desc.type) { | ||
| 20 | case TextureType::Color1D: | ||
| 21 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 1, format); | ||
| 22 | case TextureType::ColorArray1D: | ||
| 23 | return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 1, format); | ||
| 24 | case TextureType::Color2D: | ||
| 25 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 1, format); | ||
| 26 | case TextureType::ColorArray2D: | ||
| 27 | return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 1, format); | ||
| 28 | case TextureType::Color3D: | ||
| 29 | return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 1, format); | ||
| 30 | case TextureType::ColorCube: | ||
| 31 | return ctx.TypeImage(type, spv::Dim::Cube, false, false, false, 1, format); | ||
| 32 | case TextureType::ColorArrayCube: | ||
| 33 | return ctx.TypeImage(type, spv::Dim::Cube, false, true, false, 1, format); | ||
| 34 | case TextureType::Shadow1D: | ||
| 35 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, false, false, 1, format); | ||
| 36 | case TextureType::ShadowArray1D: | ||
| 37 | return ctx.TypeImage(type, spv::Dim::Dim1D, true, true, false, 1, format); | ||
| 38 | case TextureType::Shadow2D: | ||
| 39 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, false, false, 1, format); | ||
| 40 | case TextureType::ShadowArray2D: | ||
| 41 | return ctx.TypeImage(type, spv::Dim::Dim2D, true, true, false, 1, format); | ||
| 42 | case TextureType::Shadow3D: | ||
| 43 | return ctx.TypeImage(type, spv::Dim::Dim3D, true, false, false, 1, format); | ||
| 44 | case TextureType::ShadowCube: | ||
| 45 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); | ||
| 46 | case TextureType::ShadowArrayCube: | ||
| 47 | return ctx.TypeImage(type, spv::Dim::Cube, false, true, false, 1, format); | ||
| 48 | } | ||
| 49 | throw InvalidArgument("Invalid texture type {}", desc.type); | ||
| 50 | } | ||
| 51 | } // Anonymous namespace | ||
| 15 | 52 | ||
| 16 | void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { | 53 | void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { |
| 17 | defs[0] = sirit_ctx.Name(base_type, name); | 54 | defs[0] = sirit_ctx.Name(base_type, name); |
| @@ -35,6 +72,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program) | |||
| 35 | u32 binding{}; | 72 | u32 binding{}; |
| 36 | DefineConstantBuffers(program.info, binding); | 73 | DefineConstantBuffers(program.info, binding); |
| 37 | DefineStorageBuffers(program.info, binding); | 74 | DefineStorageBuffers(program.info, binding); |
| 75 | DefineTextures(program.info, binding); | ||
| 38 | 76 | ||
| 39 | DefineLabels(program); | 77 | DefineLabels(program); |
| 40 | } | 78 | } |
| @@ -46,6 +84,10 @@ Id EmitContext::Def(const IR::Value& value) { | |||
| 46 | return value.Inst()->Definition<Id>(); | 84 | return value.Inst()->Definition<Id>(); |
| 47 | } | 85 | } |
| 48 | switch (value.Type()) { | 86 | switch (value.Type()) { |
| 87 | case IR::Type::Void: | ||
| 88 | // Void instructions are used for optional arguments (e.g. texture offsets) | ||
| 89 | // They are not meant to be used in the SPIR-V module | ||
| 90 | return Id{}; | ||
| 49 | case IR::Type::U1: | 91 | case IR::Type::U1: |
| 50 | return value.U1() ? true_value : false_value; | 92 | return value.U1() ? true_value : false_value; |
| 51 | case IR::Type::U32: | 93 | case IR::Type::U32: |
| @@ -122,7 +164,7 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { | |||
| 122 | uniform_u32 = TypePointer(spv::StorageClass::Uniform, U32[1]); | 164 | uniform_u32 = TypePointer(spv::StorageClass::Uniform, U32[1]); |
| 123 | 165 | ||
| 124 | u32 index{}; | 166 | u32 index{}; |
| 125 | for (const Info::ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { | 167 | for (const ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { |
| 126 | const Id id{AddGlobalVariable(uniform_type, spv::StorageClass::Uniform)}; | 168 | const Id id{AddGlobalVariable(uniform_type, spv::StorageClass::Uniform)}; |
| 127 | Decorate(id, spv::Decoration::Binding, binding); | 169 | Decorate(id, spv::Decoration::Binding, binding); |
| 128 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | 170 | Decorate(id, spv::Decoration::DescriptorSet, 0U); |
| @@ -152,7 +194,7 @@ void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { | |||
| 152 | storage_u32 = TypePointer(spv::StorageClass::StorageBuffer, U32[1]); | 194 | storage_u32 = TypePointer(spv::StorageClass::StorageBuffer, U32[1]); |
| 153 | 195 | ||
| 154 | u32 index{}; | 196 | u32 index{}; |
| 155 | for (const Info::StorageBufferDescriptor& desc : info.storage_buffers_descriptors) { | 197 | for (const StorageBufferDescriptor& desc : info.storage_buffers_descriptors) { |
| 156 | const Id id{AddGlobalVariable(storage_type, spv::StorageClass::StorageBuffer)}; | 198 | const Id id{AddGlobalVariable(storage_type, spv::StorageClass::StorageBuffer)}; |
| 157 | Decorate(id, spv::Decoration::Binding, binding); | 199 | Decorate(id, spv::Decoration::Binding, binding); |
| 158 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | 200 | Decorate(id, spv::Decoration::DescriptorSet, 0U); |
| @@ -163,6 +205,29 @@ void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { | |||
| 163 | } | 205 | } |
| 164 | } | 206 | } |
| 165 | 207 | ||
| 208 | void EmitContext::DefineTextures(const Info& info, u32& binding) { | ||
| 209 | textures.reserve(info.texture_descriptors.size()); | ||
| 210 | for (const TextureDescriptor& desc : info.texture_descriptors) { | ||
| 211 | if (desc.count != 1) { | ||
| 212 | throw NotImplementedException("Array of textures"); | ||
| 213 | } | ||
| 214 | const Id type{TypeSampledImage(ImageType(*this, desc))}; | ||
| 215 | const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, type)}; | ||
| 216 | const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; | ||
| 217 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 218 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 219 | Name(id, fmt::format("tex{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 220 | for (u32 index = 0; index < desc.count; ++index) { | ||
| 221 | // TODO: Pass count info | ||
| 222 | textures.push_back(TextureDefinition{ | ||
| 223 | .id{id}, | ||
| 224 | .type{type}, | ||
| 225 | }); | ||
| 226 | } | ||
| 227 | binding += desc.count; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 166 | void EmitContext::DefineLabels(IR::Program& program) { | 231 | void EmitContext::DefineLabels(IR::Program& program) { |
| 167 | for (const IR::Function& function : program.functions) { | 232 | for (const IR::Function& function : program.functions) { |
| 168 | for (IR::Block* const block : function.blocks) { | 233 | for (IR::Block* const block : function.blocks) { |