diff options
Diffstat (limited to 'src/shader_recompiler/backend')
4 files changed, 54 insertions, 5 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 2d39ea373..d01633628 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -46,6 +46,8 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | |||
| 46 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); | 46 | return ctx.TypeImage(type, spv::Dim::Cube, true, false, false, 1, format); |
| 47 | case TextureType::ShadowArrayCube: | 47 | case TextureType::ShadowArrayCube: |
| 48 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); | 48 | return ctx.TypeImage(type, spv::Dim::Cube, true, true, false, 1, format); |
| 49 | case TextureType::Buffer: | ||
| 50 | break; | ||
| 49 | } | 51 | } |
| 50 | throw InvalidArgument("Invalid texture type {}", desc.type); | 52 | throw InvalidArgument("Invalid texture type {}", desc.type); |
| 51 | } | 53 | } |
| @@ -129,6 +131,7 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin | |||
| 129 | DefineConstantBuffers(program.info, binding); | 131 | DefineConstantBuffers(program.info, binding); |
| 130 | DefineStorageBuffers(program.info, binding); | 132 | DefineStorageBuffers(program.info, binding); |
| 131 | DefineTextures(program.info, binding); | 133 | DefineTextures(program.info, binding); |
| 134 | DefineTextureBuffers(program.info, binding); | ||
| 132 | DefineAttributeMemAccess(program.info); | 135 | DefineAttributeMemAccess(program.info); |
| 133 | DefineLabels(program); | 136 | DefineLabels(program); |
| 134 | } | 137 | } |
| @@ -541,6 +544,32 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { | |||
| 541 | } | 544 | } |
| 542 | } | 545 | } |
| 543 | 546 | ||
| 547 | void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { | ||
| 548 | if (info.texture_buffer_descriptors.empty()) { | ||
| 549 | return; | ||
| 550 | } | ||
| 551 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | ||
| 552 | image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); | ||
| 553 | sampled_texture_buffer_type = TypeSampledImage(image_buffer_type); | ||
| 554 | |||
| 555 | const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)}; | ||
| 556 | texture_buffers.reserve(info.texture_buffer_descriptors.size()); | ||
| 557 | for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { | ||
| 558 | if (desc.count != 1) { | ||
| 559 | throw NotImplementedException("Array of texture buffers"); | ||
| 560 | } | ||
| 561 | const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; | ||
| 562 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 563 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 564 | Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 565 | texture_buffers.insert(texture_buffers.end(), desc.count, id); | ||
| 566 | if (profile.supported_spirv >= 0x00010400) { | ||
| 567 | interfaces.push_back(id); | ||
| 568 | } | ||
| 569 | binding += desc.count; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 544 | void EmitContext::DefineLabels(IR::Program& program) { | 573 | void EmitContext::DefineLabels(IR::Program& program) { |
| 545 | for (IR::Block* const block : program.blocks) { | 574 | for (IR::Block* const block : program.blocks) { |
| 546 | block->SetDefinition(OpLabel()); | 575 | block->SetDefinition(OpLabel()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 7a2ac0511..2a10e94e5 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -90,9 +90,13 @@ public: | |||
| 90 | 90 | ||
| 91 | Id storage_u32{}; | 91 | Id storage_u32{}; |
| 92 | 92 | ||
| 93 | Id image_buffer_type{}; | ||
| 94 | Id sampled_texture_buffer_type{}; | ||
| 95 | |||
| 93 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; | 96 | std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{}; |
| 94 | std::array<Id, Info::MAX_SSBOS> ssbos{}; | 97 | std::array<Id, Info::MAX_SSBOS> ssbos{}; |
| 95 | std::vector<TextureDefinition> textures; | 98 | std::vector<TextureDefinition> textures; |
| 99 | std::vector<Id> texture_buffers; | ||
| 96 | 100 | ||
| 97 | Id workgroup_id{}; | 101 | Id workgroup_id{}; |
| 98 | Id local_invocation_id{}; | 102 | Id local_invocation_id{}; |
| @@ -151,6 +155,7 @@ private: | |||
| 151 | void DefineConstantBuffers(const Info& info, u32& binding); | 155 | void DefineConstantBuffers(const Info& info, u32& binding); |
| 152 | void DefineStorageBuffers(const Info& info, u32& binding); | 156 | void DefineStorageBuffers(const Info& info, u32& binding); |
| 153 | void DefineTextures(const Info& info, u32& binding); | 157 | void DefineTextures(const Info& info, u32& binding); |
| 158 | void DefineTextureBuffers(const Info& info, u32& binding); | ||
| 154 | void DefineAttributeMemAccess(const Info& info); | 159 | void DefineAttributeMemAccess(const Info& info); |
| 155 | void DefineLabels(IR::Program& program); | 160 | void DefineLabels(IR::Program& program); |
| 156 | 161 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 191380db0..32512a0e5 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -249,6 +249,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 249 | // TODO: Track this usage | 249 | // TODO: Track this usage |
| 250 | ctx.AddCapability(spv::Capability::ImageGatherExtended); | 250 | ctx.AddCapability(spv::Capability::ImageGatherExtended); |
| 251 | ctx.AddCapability(spv::Capability::ImageQuery); | 251 | ctx.AddCapability(spv::Capability::ImageQuery); |
| 252 | ctx.AddCapability(spv::Capability::SampledBuffer); | ||
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { | 255 | Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index fc40615af..525f67c6e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -128,12 +128,18 @@ Id Texture(EmitContext& ctx, const IR::Value& index) { | |||
| 128 | throw NotImplementedException("Indirect texture sample"); | 128 | throw NotImplementedException("Indirect texture sample"); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | Id TextureImage(EmitContext& ctx, const IR::Value& index) { | 131 | Id TextureImage(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { |
| 132 | if (index.IsImmediate()) { | 132 | if (!index.IsImmediate()) { |
| 133 | throw NotImplementedException("Indirect texture sample"); | ||
| 134 | } | ||
| 135 | if (info.type == TextureType::Buffer) { | ||
| 136 | const Id sampler_id{ctx.texture_buffers.at(index.U32())}; | ||
| 137 | const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)}; | ||
| 138 | return ctx.OpImage(ctx.image_buffer_type, id); | ||
| 139 | } else { | ||
| 133 | const TextureDefinition def{ctx.textures.at(index.U32())}; | 140 | const TextureDefinition def{ctx.textures.at(index.U32())}; |
| 134 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); | 141 | return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); |
| 135 | } | 142 | } |
| 136 | throw NotImplementedException("Indirect texture sample"); | ||
| 137 | } | 143 | } |
| 138 | 144 | ||
| 139 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 145 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
| @@ -297,17 +303,22 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | |||
| 297 | ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); | 303 | ctx.F32[4], Texture(ctx, index), coords, dref, operands.Mask(), operands.Span()); |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 306 | #pragma optimize("", off) | ||
| 307 | |||
| 300 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 308 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
| 301 | Id lod, Id ms) { | 309 | Id lod, Id ms) { |
| 302 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 310 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 311 | if (info.type == TextureType::Buffer) { | ||
| 312 | lod = Id{}; | ||
| 313 | } | ||
| 303 | const ImageOperands operands(offset, lod, ms); | 314 | const ImageOperands operands(offset, lod, ms); |
| 304 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], | 315 | return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], |
| 305 | TextureImage(ctx, index), coords, operands.Mask(), operands.Span()); | 316 | TextureImage(ctx, index, info), coords, operands.Mask(), operands.Span()); |
| 306 | } | 317 | } |
| 307 | 318 | ||
| 308 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { | 319 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { |
| 309 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 320 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 310 | const Id image{TextureImage(ctx, index)}; | 321 | const Id image{TextureImage(ctx, index, info)}; |
| 311 | const Id zero{ctx.u32_zero_value}; | 322 | const Id zero{ctx.u32_zero_value}; |
| 312 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 323 | const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; |
| 313 | switch (info.type) { | 324 | switch (info.type) { |
| @@ -331,6 +342,9 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 331 | case TextureType::ShadowArrayCube: | 342 | case TextureType::ShadowArrayCube: |
| 332 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), | 343 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), |
| 333 | mips()); | 344 | mips()); |
| 345 | case TextureType::Buffer: | ||
| 346 | return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySize(ctx.U32[1], image), zero, | ||
| 347 | zero, mips()); | ||
| 334 | } | 348 | } |
| 335 | throw LogicError("Unspecified image type {}", info.type.Value()); | 349 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 336 | } | 350 | } |