diff options
Diffstat (limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/texture_pass.cpp | 49 |
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 | ||
| 367 | TexturePixelFormat 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 | |||
| 366 | class Descriptors { | 375 | class Descriptors { |
| 367 | public: | 376 | public: |
| 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 | |||
| 464 | void 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 | ||
| 456 | void TexturePass(Environment& env, IR::Program& program) { | 497 | void 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 | ||