From e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 1 Aug 2021 18:57:45 -0300 Subject: shader: Properly scale image reads and add GL SPIR-V support Thanks for everything! --- .../backend/spirv/emit_context.cpp | 65 +++++++++++++++++----- 1 file changed, 52 insertions(+), 13 deletions(-) (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp') diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 222baa177..8646fe989 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp @@ -14,6 +14,7 @@ #include "common/common_types.h" #include "common/div_ceil.h" #include "shader_recompiler/backend/spirv/emit_context.h" +#include "shader_recompiler/backend/spirv/emit_spirv.h" namespace Shader::Backend::SPIRV { namespace { @@ -476,8 +477,9 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_info_, IR::Program& program, Bindings& bindings) - : Sirit::Module(profile_.supported_spirv), profile{profile_}, - runtime_info{runtime_info_}, stage{program.stage} { + : Sirit::Module(profile_.supported_spirv), profile{profile_}, runtime_info{runtime_info_}, + stage{program.stage}, texture_rescaling_index{bindings.texture_scaling_index}, + image_rescaling_index{bindings.image_scaling_index} { const bool is_unified{profile.unified_descriptor_binding}; u32& uniform_binding{is_unified ? bindings.unified : bindings.uniform_buffer}; u32& storage_binding{is_unified ? bindings.unified : bindings.storage_buffer}; @@ -494,8 +496,8 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf DefineStorageBuffers(program.info, storage_binding); DefineTextureBuffers(program.info, texture_binding); DefineImageBuffers(program.info, image_binding); - DefineTextures(program.info, texture_binding); - DefineImages(program.info, image_binding); + DefineTextures(program.info, texture_binding, bindings.texture_scaling_index); + DefineImages(program.info, image_binding, bindings.image_scaling_index); DefineAttributeMemAccess(program.info); DefineGlobalMemoryFunctions(program.info); DefineRescalingInput(program.info); @@ -1003,25 +1005,49 @@ void EmitContext::DefineRescalingInput(const Info& info) { if (!info.uses_rescaling_uniform) { return; } - boost::container::static_vector members{F32[1]}; + if (profile.unified_descriptor_binding) { + DefineRescalingInputPushConstant(info); + } else { + DefineRescalingInputUniformConstant(); + } +} + +void EmitContext::DefineRescalingInputPushConstant(const Info& info) { + boost::container::static_vector members{F32[1]}; u32 member_index{0}; - const u32 num_texture_words{Common::DivCeil(runtime_info.num_textures, 32u)}; - if (runtime_info.num_textures > 0) { - rescaling_textures_type = TypeArray(U32[1], Const(num_texture_words)); + if (!info.texture_descriptors.empty()) { + rescaling_textures_type = TypeArray(U32[1], Const(4u)); Decorate(rescaling_textures_type, spv::Decoration::ArrayStride, 4u); members.push_back(rescaling_textures_type); rescaling_textures_member_index = ++member_index; } + if (!info.image_descriptors.empty()) { + rescaling_images_type = TypeArray(U32[1], Const(NUM_IMAGE_SCALING_WORDS)); + if (rescaling_textures_type.value != rescaling_images_type.value) { + Decorate(rescaling_images_type, spv::Decoration::ArrayStride, 4u); + } + members.push_back(rescaling_images_type); + rescaling_images_member_index = ++member_index; + } const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))}; Decorate(push_constant_struct, spv::Decoration::Block); Name(push_constant_struct, "ResolutionInfo"); + MemberDecorate(push_constant_struct, 0u, spv::Decoration::Offset, 0u); MemberName(push_constant_struct, 0u, "down_factor"); - if (runtime_info.num_textures > 0) { - MemberDecorate(push_constant_struct, rescaling_textures_member_index, - spv::Decoration::Offset, 4u); + + const u32 offset_bias = stage == Stage::Compute ? sizeof(u32) : 0; + if (!info.texture_descriptors.empty()) { + MemberDecorate( + push_constant_struct, rescaling_textures_member_index, spv::Decoration::Offset, + static_cast(offsetof(RescalingLayout, rescaling_textures) - offset_bias)); MemberName(push_constant_struct, rescaling_textures_member_index, "rescaling_textures"); } + if (!info.image_descriptors.empty()) { + MemberDecorate(push_constant_struct, rescaling_images_member_index, spv::Decoration::Offset, + static_cast(offsetof(RescalingLayout, rescaling_images) - offset_bias)); + MemberName(push_constant_struct, rescaling_images_member_index, "rescaling_images"); + } const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)}; rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant); Name(rescaling_push_constants, "rescaling_push_constants"); @@ -1031,6 +1057,17 @@ void EmitContext::DefineRescalingInput(const Info& info) { } } +void EmitContext::DefineRescalingInputUniformConstant() { + const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, F32[4])}; + rescaling_uniform_constant = + AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant); + Decorate(rescaling_uniform_constant, spv::Decoration::Location, 0u); + + if (profile.supported_spirv >= 0x00010400) { + interfaces.push_back(rescaling_uniform_constant); + } +} + void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { if (info.constant_buffer_descriptors.empty()) { return; @@ -1219,7 +1256,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { } } -void EmitContext::DefineTextures(const Info& info, u32& binding) { +void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_index) { textures.reserve(info.texture_descriptors.size()); for (const TextureDescriptor& desc : info.texture_descriptors) { const Id image_type{ImageType(*this, desc)}; @@ -1241,13 +1278,14 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { interfaces.push_back(id); } ++binding; + ++scaling_index; } if (info.uses_atomic_image_u32) { image_u32 = TypePointer(spv::StorageClass::Image, U32[1]); } } -void EmitContext::DefineImages(const Info& info, u32& binding) { +void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_index) { images.reserve(info.image_descriptors.size()); for (const ImageDescriptor& desc : info.image_descriptors) { if (desc.count != 1) { @@ -1268,6 +1306,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding) { interfaces.push_back(id); } ++binding; + ++scaling_index; } } -- cgit v1.2.3