diff options
| author | 2021-03-20 19:11:56 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | 76c8a962ac4eae77e71d66a72c448930240339f9 (patch) | |
| tree | 267bdb72f0fad43779080cd1907dd8159a6c7154 /src/shader_recompiler/backend/spirv/emit_context.cpp | |
| parent | shader: Refactor half floating instructions (diff) | |
| download | yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.gz yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.xz yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.zip | |
spirv: Implement VertexId and InstanceId, refactor code
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.cpp | 191 |
1 files changed, 111 insertions, 80 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 6c8f16562..4a4de3676 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -48,6 +48,25 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | |||
| 48 | } | 48 | } |
| 49 | throw InvalidArgument("Invalid texture type {}", desc.type); | 49 | throw InvalidArgument("Invalid texture type {}", desc.type); |
| 50 | } | 50 | } |
| 51 | |||
| 52 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | ||
| 53 | spv::StorageClass storage_class) { | ||
| 54 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | ||
| 55 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class)}; | ||
| 56 | if (builtin) { | ||
| 57 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); | ||
| 58 | } | ||
| 59 | ctx.interfaces.push_back(id); | ||
| 60 | return id; | ||
| 61 | } | ||
| 62 | |||
| 63 | Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { | ||
| 64 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Input); | ||
| 65 | } | ||
| 66 | |||
| 67 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { | ||
| 68 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); | ||
| 69 | } | ||
| 51 | } // Anonymous namespace | 70 | } // Anonymous namespace |
| 52 | 71 | ||
| 53 | void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { | 72 | void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { |
| @@ -144,59 +163,8 @@ void EmitContext::DefineCommonConstants() { | |||
| 144 | } | 163 | } |
| 145 | 164 | ||
| 146 | void EmitContext::DefineInterfaces(const Info& info, Stage stage) { | 165 | void EmitContext::DefineInterfaces(const Info& info, Stage stage) { |
| 147 | const auto define{ | 166 | DefineInputs(info, stage); |
| 148 | [this](Id type, std::optional<spv::BuiltIn> builtin, spv::StorageClass storage_class) { | 167 | DefineOutputs(info, stage); |
| 149 | const Id pointer_type{TypePointer(storage_class, type)}; | ||
| 150 | const Id id{AddGlobalVariable(pointer_type, storage_class)}; | ||
| 151 | if (builtin) { | ||
| 152 | Decorate(id, spv::Decoration::BuiltIn, *builtin); | ||
| 153 | } | ||
| 154 | interfaces.push_back(id); | ||
| 155 | return id; | ||
| 156 | }}; | ||
| 157 | using namespace std::placeholders; | ||
| 158 | const auto define_input{std::bind(define, _1, _2, spv::StorageClass::Input)}; | ||
| 159 | const auto define_output{std::bind(define, _1, _2, spv::StorageClass::Output)}; | ||
| 160 | |||
| 161 | if (info.uses_workgroup_id) { | ||
| 162 | workgroup_id = define_input(U32[3], spv::BuiltIn::WorkgroupId); | ||
| 163 | } | ||
| 164 | if (info.uses_local_invocation_id) { | ||
| 165 | local_invocation_id = define_input(U32[3], spv::BuiltIn::LocalInvocationId); | ||
| 166 | } | ||
| 167 | if (info.loads_position) { | ||
| 168 | const bool is_fragment{stage != Stage::Fragment}; | ||
| 169 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; | ||
| 170 | input_position = define_input(F32[4], built_in); | ||
| 171 | } | ||
| 172 | for (size_t i = 0; i < info.loads_generics.size(); ++i) { | ||
| 173 | if (info.loads_generics[i]) { | ||
| 174 | // FIXME: Declare size from input | ||
| 175 | input_generics[i] = define_input(F32[4], std::nullopt); | ||
| 176 | Decorate(input_generics[i], spv::Decoration::Location, static_cast<u32>(i)); | ||
| 177 | Name(input_generics[i], fmt::format("in_attr{}", i)); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | if (info.stores_position) { | ||
| 181 | output_position = define_output(F32[4], spv::BuiltIn::Position); | ||
| 182 | } | ||
| 183 | for (size_t i = 0; i < info.stores_generics.size(); ++i) { | ||
| 184 | if (info.stores_generics[i]) { | ||
| 185 | output_generics[i] = define_output(F32[4], std::nullopt); | ||
| 186 | Decorate(output_generics[i], spv::Decoration::Location, static_cast<u32>(i)); | ||
| 187 | Name(output_generics[i], fmt::format("out_attr{}", i)); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | if (stage == Stage::Fragment) { | ||
| 191 | for (size_t i = 0; i < 8; ++i) { | ||
| 192 | if (!info.stores_frag_color[i]) { | ||
| 193 | continue; | ||
| 194 | } | ||
| 195 | frag_color[i] = define_output(F32[4], std::nullopt); | ||
| 196 | Decorate(frag_color[i], spv::Decoration::Location, static_cast<u32>(i)); | ||
| 197 | Name(frag_color[i], fmt::format("frag_color{}", i)); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | 168 | } |
| 201 | 169 | ||
| 202 | void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { | 170 | void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { |
| @@ -225,33 +193,6 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { | |||
| 225 | } | 193 | } |
| 226 | } | 194 | } |
| 227 | 195 | ||
| 228 | void EmitContext::DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, | ||
| 229 | u32 binding, Id type, char type_char, u32 element_size) { | ||
| 230 | const Id array_type{TypeArray(type, Constant(U32[1], 65536U / element_size))}; | ||
| 231 | Decorate(array_type, spv::Decoration::ArrayStride, element_size); | ||
| 232 | |||
| 233 | const Id struct_type{TypeStruct(array_type)}; | ||
| 234 | Name(struct_type, fmt::format("cbuf_block_{}{}", type_char, element_size * CHAR_BIT)); | ||
| 235 | Decorate(struct_type, spv::Decoration::Block); | ||
| 236 | MemberName(struct_type, 0, "data"); | ||
| 237 | MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); | ||
| 238 | |||
| 239 | const Id struct_pointer_type{TypePointer(spv::StorageClass::Uniform, struct_type)}; | ||
| 240 | const Id uniform_type{TypePointer(spv::StorageClass::Uniform, type)}; | ||
| 241 | uniform_types.*member_type = uniform_type; | ||
| 242 | |||
| 243 | for (const ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { | ||
| 244 | const Id id{AddGlobalVariable(struct_pointer_type, spv::StorageClass::Uniform)}; | ||
| 245 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 246 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 247 | Name(id, fmt::format("c{}", desc.index)); | ||
| 248 | for (size_t i = 0; i < desc.count; ++i) { | ||
| 249 | cbufs[desc.index + i].*member_type = id; | ||
| 250 | } | ||
| 251 | binding += desc.count; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { | 196 | void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { |
| 256 | if (info.storage_buffers_descriptors.empty()) { | 197 | if (info.storage_buffers_descriptors.empty()) { |
| 257 | return; | 198 | return; |
| @@ -311,4 +252,94 @@ void EmitContext::DefineLabels(IR::Program& program) { | |||
| 311 | } | 252 | } |
| 312 | } | 253 | } |
| 313 | 254 | ||
| 255 | void EmitContext::DefineInputs(const Info& info, Stage stage) { | ||
| 256 | if (info.uses_workgroup_id) { | ||
| 257 | workgroup_id = DefineInput(*this, U32[3], spv::BuiltIn::WorkgroupId); | ||
| 258 | } | ||
| 259 | if (info.uses_local_invocation_id) { | ||
| 260 | local_invocation_id = DefineInput(*this, U32[3], spv::BuiltIn::LocalInvocationId); | ||
| 261 | } | ||
| 262 | if (info.loads_position) { | ||
| 263 | const bool is_fragment{stage != Stage::Fragment}; | ||
| 264 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; | ||
| 265 | input_position = DefineInput(*this, F32[4], built_in); | ||
| 266 | } | ||
| 267 | if (info.loads_instance_id) { | ||
| 268 | if (profile.support_vertex_instance_id) { | ||
| 269 | instance_id = DefineInput(*this, U32[1], spv::BuiltIn::InstanceId); | ||
| 270 | } else { | ||
| 271 | instance_index = DefineInput(*this, U32[1], spv::BuiltIn::InstanceIndex); | ||
| 272 | base_instance = DefineInput(*this, U32[1], spv::BuiltIn::BaseInstance); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | if (info.loads_vertex_id) { | ||
| 276 | if (profile.support_vertex_instance_id) { | ||
| 277 | vertex_id = DefineInput(*this, U32[1], spv::BuiltIn::VertexId); | ||
| 278 | } else { | ||
| 279 | vertex_index = DefineInput(*this, U32[1], spv::BuiltIn::VertexIndex); | ||
| 280 | base_vertex = DefineInput(*this, U32[1], spv::BuiltIn::BaseVertex); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | for (size_t index = 0; index < info.loads_generics.size(); ++index) { | ||
| 284 | if (!info.loads_generics[index]) { | ||
| 285 | continue; | ||
| 286 | } | ||
| 287 | // FIXME: Declare size from input | ||
| 288 | const Id id{DefineInput(*this, F32[4])}; | ||
| 289 | Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); | ||
| 290 | Name(id, fmt::format("in_attr{}", index)); | ||
| 291 | input_generics[index] = id; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | void EmitContext::DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type, | ||
| 296 | u32 binding, Id type, char type_char, u32 element_size) { | ||
| 297 | const Id array_type{TypeArray(type, Constant(U32[1], 65536U / element_size))}; | ||
| 298 | Decorate(array_type, spv::Decoration::ArrayStride, element_size); | ||
| 299 | |||
| 300 | const Id struct_type{TypeStruct(array_type)}; | ||
| 301 | Name(struct_type, fmt::format("cbuf_block_{}{}", type_char, element_size * CHAR_BIT)); | ||
| 302 | Decorate(struct_type, spv::Decoration::Block); | ||
| 303 | MemberName(struct_type, 0, "data"); | ||
| 304 | MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); | ||
| 305 | |||
| 306 | const Id struct_pointer_type{TypePointer(spv::StorageClass::Uniform, struct_type)}; | ||
| 307 | const Id uniform_type{TypePointer(spv::StorageClass::Uniform, type)}; | ||
| 308 | uniform_types.*member_type = uniform_type; | ||
| 309 | |||
| 310 | for (const ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { | ||
| 311 | const Id id{AddGlobalVariable(struct_pointer_type, spv::StorageClass::Uniform)}; | ||
| 312 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 313 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 314 | Name(id, fmt::format("c{}", desc.index)); | ||
| 315 | for (size_t i = 0; i < desc.count; ++i) { | ||
| 316 | cbufs[desc.index + i].*member_type = id; | ||
| 317 | } | ||
| 318 | binding += desc.count; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | void EmitContext::DefineOutputs(const Info& info, Stage stage) { | ||
| 323 | if (info.stores_position) { | ||
| 324 | output_position = DefineOutput(*this, F32[4], spv::BuiltIn::Position); | ||
| 325 | } | ||
| 326 | for (size_t i = 0; i < info.stores_generics.size(); ++i) { | ||
| 327 | if (info.stores_generics[i]) { | ||
| 328 | output_generics[i] = DefineOutput(*this, F32[4]); | ||
| 329 | Decorate(output_generics[i], spv::Decoration::Location, static_cast<u32>(i)); | ||
| 330 | Name(output_generics[i], fmt::format("out_attr{}", i)); | ||
| 331 | } | ||
| 332 | } | ||
| 333 | if (stage == Stage::Fragment) { | ||
| 334 | for (size_t i = 0; i < 8; ++i) { | ||
| 335 | if (!info.stores_frag_color[i]) { | ||
| 336 | continue; | ||
| 337 | } | ||
| 338 | frag_color[i] = DefineOutput(*this, F32[4]); | ||
| 339 | Decorate(frag_color[i], spv::Decoration::Location, static_cast<u32>(i)); | ||
| 340 | Name(frag_color[i], fmt::format("frag_color{}", i)); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 314 | } // namespace Shader::Backend::SPIRV | 345 | } // namespace Shader::Backend::SPIRV |