summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/texture_pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index e8be58357..9eff84a3d 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -7,6 +7,7 @@
7 7
8#include <boost/container/small_vector.hpp> 8#include <boost/container/small_vector.hpp>
9 9
10#include "common/settings.h"
10#include "shader_recompiler/environment.h" 11#include "shader_recompiler/environment.h"
11#include "shader_recompiler/frontend/ir/basic_block.h" 12#include "shader_recompiler/frontend/ir/basic_block.h"
12#include "shader_recompiler/frontend/ir/breadth_first_search.h" 13#include "shader_recompiler/frontend/ir/breadth_first_search.h"
@@ -363,6 +364,14 @@ TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {
363 return env.ReadTextureType(lhs_raw | rhs_raw); 364 return env.ReadTextureType(lhs_raw | rhs_raw);
364} 365}
365 366
367TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) {
368 const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index};
369 const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset};
370 const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)};
371 const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)};
372 return env.ReadTexturePixelFormat(lhs_raw | rhs_raw);
373}
374
366class Descriptors { 375class Descriptors {
367public: 376public:
368 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, 377 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -451,6 +460,38 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
451 ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)), 460 ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)),
452 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1)))))); 461 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
453} 462}
463
464void PathTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
465 const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
466 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
467 auto get_max_value = [pixel_format]() -> float {
468 switch (pixel_format) {
469 case TexturePixelFormat::A8B8G8R8_SNORM:
470 case TexturePixelFormat::R8G8_SNORM:
471 case TexturePixelFormat::R8_SNORM:
472 return 1.f / std::numeric_limits<char>::max();
473 case TexturePixelFormat::R16G16B16A16_SNORM:
474 case TexturePixelFormat::R16G16_SNORM:
475 case TexturePixelFormat::R16_SNORM:
476 return 1.f / std::numeric_limits<short>::max();
477 default:
478 throw InvalidArgument("Invalid texture pixel format");
479 }
480 };
481
482 const IR::Value new_inst{&*block.PrependNewInst(it, inst)};
483 const IR::F32 x(ir.CompositeExtract(new_inst, 0));
484 const IR::F32 y(ir.CompositeExtract(new_inst, 1));
485 const IR::F32 z(ir.CompositeExtract(new_inst, 2));
486 const IR::F32 w(ir.CompositeExtract(new_inst, 3));
487 const IR::F16F32F64 max_value(ir.Imm32(get_max_value()));
488 const IR::Value converted =
489 ir.CompositeConstruct(ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(x)), max_value),
490 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(y)), max_value),
491 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(z)), max_value),
492 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(w)), max_value));
493 inst.ReplaceUsesWith(converted);
494}
454} // Anonymous namespace 495} // Anonymous namespace
455 496
456void TexturePass(Environment& env, IR::Program& program) { 497void TexturePass(Environment& env, IR::Program& program) {
@@ -597,6 +638,14 @@ void TexturePass(Environment& env, IR::Program& program) {
597 } else { 638 } else {
598 inst->SetArg(0, IR::Value{}); 639 inst->SetArg(0, IR::Value{});
599 } 640 }
641
642 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
643 inst->GetOpcode() == IR::Opcode::ImageFetch && flags.type == TextureType::Buffer) {
644 const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
645 if (pixel_format != TexturePixelFormat::OTHER) {
646 PathTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
647 }
648 }
600 } 649 }
601} 650}
602 651