summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-07-25 22:26:23 -0300
committerGravatar Fernando Sahmkow2021-11-16 22:11:28 +0100
commit656adee630cb1de738ed4dc6cf1cbc35af40f64f (patch)
tree5c5ec069a136655476180ce03fc24ccd911b3871 /src/shader_recompiler/backend
parentshader/rescaling_pass: Patch more instructions (diff)
downloadyuzu-656adee630cb1de738ed4dc6cf1cbc35af40f64f.tar.gz
yuzu-656adee630cb1de738ed4dc6cf1cbc35af40f64f.tar.xz
yuzu-656adee630cb1de738ed4dc6cf1cbc35af40f64f.zip
spirv: Implement rescaling patching
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp35
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h5
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h5
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp6
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp26
5 files changed, 72 insertions, 5 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 3c84e6466..222baa177 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -7,6 +7,8 @@
7#include <climits> 7#include <climits>
8#include <string_view> 8#include <string_view>
9 9
10#include <boost/container/static_vector.hpp>
11
10#include <fmt/format.h> 12#include <fmt/format.h>
11 13
12#include "common/common_types.h" 14#include "common/common_types.h"
@@ -496,6 +498,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
496 DefineImages(program.info, image_binding); 498 DefineImages(program.info, image_binding);
497 DefineAttributeMemAccess(program.info); 499 DefineAttributeMemAccess(program.info);
498 DefineGlobalMemoryFunctions(program.info); 500 DefineGlobalMemoryFunctions(program.info);
501 DefineRescalingInput(program.info);
499} 502}
500 503
501EmitContext::~EmitContext() = default; 504EmitContext::~EmitContext() = default;
@@ -996,6 +999,38 @@ void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
996 define(&StorageDefinitions::U32x4, storage_types.U32x4, U32[4], sizeof(u32[4])); 999 define(&StorageDefinitions::U32x4, storage_types.U32x4, U32[4], sizeof(u32[4]));
997} 1000}
998 1001
1002void EmitContext::DefineRescalingInput(const Info& info) {
1003 if (!info.uses_rescaling_uniform) {
1004 return;
1005 }
1006 boost::container::static_vector<Id, 2> members{F32[1]};
1007 u32 member_index{0};
1008 const u32 num_texture_words{Common::DivCeil(runtime_info.num_textures, 32u)};
1009 if (runtime_info.num_textures > 0) {
1010 rescaling_textures_type = TypeArray(U32[1], Const(num_texture_words));
1011 Decorate(rescaling_textures_type, spv::Decoration::ArrayStride, 4u);
1012 members.push_back(rescaling_textures_type);
1013 rescaling_textures_member_index = ++member_index;
1014 }
1015 const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))};
1016 Decorate(push_constant_struct, spv::Decoration::Block);
1017 Name(push_constant_struct, "ResolutionInfo");
1018 MemberDecorate(push_constant_struct, 0u, spv::Decoration::Offset, 0u);
1019 MemberName(push_constant_struct, 0u, "down_factor");
1020 if (runtime_info.num_textures > 0) {
1021 MemberDecorate(push_constant_struct, rescaling_textures_member_index,
1022 spv::Decoration::Offset, 4u);
1023 MemberName(push_constant_struct, rescaling_textures_member_index, "rescaling_textures");
1024 }
1025 const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)};
1026 rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant);
1027 Name(rescaling_push_constants, "rescaling_push_constants");
1028
1029 if (profile.supported_spirv >= 0x00010400) {
1030 interfaces.push_back(rescaling_push_constants);
1031 }
1032}
1033
999void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { 1034void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
1000 if (info.constant_buffer_descriptors.empty()) { 1035 if (info.constant_buffer_descriptors.empty()) {
1001 return; 1036 return;
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 112c52382..a7917ac51 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -238,6 +238,10 @@ public:
238 Id indexed_load_func{}; 238 Id indexed_load_func{};
239 Id indexed_store_func{}; 239 Id indexed_store_func{};
240 240
241 Id rescaling_push_constants{};
242 Id rescaling_textures_type{};
243 u32 rescaling_textures_member_index{};
244
241 Id local_memory{}; 245 Id local_memory{};
242 246
243 Id shared_memory_u8{}; 247 Id shared_memory_u8{};
@@ -314,6 +318,7 @@ private:
314 void DefineImages(const Info& info, u32& binding); 318 void DefineImages(const Info& info, u32& binding);
315 void DefineAttributeMemAccess(const Info& info); 319 void DefineAttributeMemAccess(const Info& info);
316 void DefineGlobalMemoryFunctions(const Info& info); 320 void DefineGlobalMemoryFunctions(const Info& info);
321 void DefineRescalingInput(const Info& info);
317 322
318 void DefineInputs(const IR::Program& program); 323 void DefineInputs(const IR::Program& program);
319 void DefineOutputs(const IR::Program& program); 324 void DefineOutputs(const IR::Program& program);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index db0c935fe..7b0d8d980 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -20,8 +20,11 @@ namespace Shader::Backend::SPIRV {
20 IR::Program& program, Bindings& bindings); 20 IR::Program& program, Bindings& bindings);
21 21
22[[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program) { 22[[nodiscard]] inline std::vector<u32> EmitSPIRV(const Profile& profile, IR::Program& program) {
23 RuntimeInfo runtime_info{};
24 runtime_info.num_textures = Shader::NumDescriptors(program.info.texture_descriptors);
25
23 Bindings binding; 26 Bindings binding;
24 return EmitSPIRV(profile, {}, program, binding); 27 return EmitSPIRV(profile, runtime_info, program, binding);
25} 28}
26 29
27} // namespace Shader::Backend::SPIRV 30} // namespace Shader::Backend::SPIRV
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 43f440dfb..6bb791b03 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -527,8 +527,10 @@ Id EmitYDirection(EmitContext& ctx) {
527} 527}
528 528
529Id EmitResolutionDownFactor(EmitContext& ctx) { 529Id EmitResolutionDownFactor(EmitContext& ctx) {
530 UNIMPLEMENTED(); 530 const Id pointer_type{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.F32[1])};
531 return ctx.Const(1.0f); 531 const Id pointer{
532 ctx.OpAccessChain(pointer_type, ctx.rescaling_push_constants, ctx.u32_zero_value)};
533 return ctx.OpLoad(ctx.F32[1], pointer);
532} 534}
533 535
534Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { 536Id EmitLoadLocal(EmitContext& ctx, Id word_offset) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 2f925cc3e..7d7c0627e 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -470,8 +470,30 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id
470 ctx.OpImageWrite(Image(ctx, index, info), coords, color); 470 ctx.OpImageWrite(Image(ctx, index, info), coords, color);
471} 471}
472 472
473Id EmitIsTextureScaled([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR::Value& index) { 473Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) {
474 return ctx.false_value; 474 const Id push_constant_u32{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1])};
475 const Id member_index{ctx.Const(ctx.rescaling_textures_member_index)};
476 Id bit{};
477 if (index.IsImmediate()) {
478 // Use BitwiseAnd instead of BitfieldExtract for better codegen on Nvidia OpenGL.
479 // LOP32I.NZ is used to set the predicate rather than BFE+ISETP.
480 const u32 index_value{index.U32()};
481 const Id word_index{ctx.Const(index_value / 32)};
482 const Id bit_index_mask{ctx.Const(1u << (index_value % 32))};
483 const Id pointer{ctx.OpAccessChain(push_constant_u32, ctx.rescaling_push_constants,
484 member_index, word_index)};
485 const Id word{ctx.OpLoad(ctx.U32[1], pointer)};
486 bit = ctx.OpBitwiseAnd(ctx.U32[1], word, bit_index_mask);
487 } else {
488 const Id index_value{ctx.Def(index)};
489 const Id word_index{ctx.OpShiftRightArithmetic(ctx.U32[1], index_value, ctx.Const(5u))};
490 const Id pointer{ctx.OpAccessChain(push_constant_u32, ctx.rescaling_push_constants,
491 member_index, word_index)};
492 const Id word{ctx.OpLoad(ctx.U32[1], pointer)};
493 const Id bit_index{ctx.OpBitwiseAnd(ctx.U32[1], index_value, ctx.Const(31u))};
494 bit = ctx.OpBitFieldUExtract(ctx.U32[1], index_value, bit_index, ctx.Const(1u));
495 }
496 return ctx.OpINotEqual(ctx.U1, bit, ctx.u32_zero_value);
475} 497}
476 498
477} // namespace Shader::Backend::SPIRV 499} // namespace Shader::Backend::SPIRV