mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-12 14:48:52 +00:00
shader_recompiler: Improve shader exports accuracy (part 1) (#3447)
* video_core: support for RT layer outputs - support for RT layer outputs - refactor for handling of export attributes - move output->attribute mapping to a separate header * export: Rework render target exports - Centralize all code related to MRT exports into a single function to make it easier to follow - Apply swizzle to output RGBA colors instead of the render target channel. This fixes swizzles on formats with < 4 channels For example with render target format R8_UNORM and COMP_SWAP ALT_REV the previous code would output frag_color.a = color.r; instead of frag_color.r = color.a; which would result in incorrect output in some cases * vk_pipeline_cache: Apply swizzle to write masks --------- Co-authored-by: polyproxy <47796739+polybiusproxy@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "shader_recompiler/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/ir/opcodes.h"
|
||||
#include "shader_recompiler/ir/position.h"
|
||||
#include "shader_recompiler/ir/program.h"
|
||||
#include "shader_recompiler/ir/reg.h"
|
||||
#include "shader_recompiler/recompiler.h"
|
||||
@@ -142,11 +143,12 @@ void RingAccessElimination(const IR::Program& program, const RuntimeInfo& runtim
|
||||
ASSERT(it != info.gs_copy_data.attr_map.cend());
|
||||
const auto& [attr, comp] = it->second;
|
||||
|
||||
inst.ReplaceOpcode(IR::Opcode::SetAttribute);
|
||||
inst.ClearArgs();
|
||||
inst.SetArg(0, IR::Value{attr});
|
||||
inst.SetArg(1, data);
|
||||
inst.SetArg(2, ir.Imm32(comp));
|
||||
inst.Invalidate();
|
||||
if (IsPosition(attr)) {
|
||||
ExportPosition(ir, runtime_info.gs_info, attr, comp, data);
|
||||
} else {
|
||||
ir.SetAttribute(attr, data, comp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -160,6 +160,10 @@ void CollectShaderInfoPass(IR::Program& program, const Profile& profile) {
|
||||
}
|
||||
}
|
||||
|
||||
if (info.stores.GetAny(IR::Attribute::RenderTargetId)) {
|
||||
info.has_layer_output = true;
|
||||
}
|
||||
|
||||
// In case Flatbuf has not already been bound by IR and is needed
|
||||
// to query buffer sizes, bind it now.
|
||||
if (!profile.supports_robust_buffer_access && !info.uses_dma) {
|
||||
|
||||
53
src/shader_recompiler/ir/position.h
Normal file
53
src/shader_recompiler/ir/position.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shader_recompiler/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/runtime_info.h"
|
||||
|
||||
namespace Shader::IR {
|
||||
|
||||
/// Maps special position export to builtin attribute stores
|
||||
inline void ExportPosition(IREmitter& ir, const auto& stage, Attribute attribute, u32 comp,
|
||||
const IR::F32& value) {
|
||||
if (attribute == Attribute::Position0) {
|
||||
ir.SetAttribute(attribute, value, comp);
|
||||
return;
|
||||
}
|
||||
const u32 index = u32(attribute) - u32(Attribute::Position1);
|
||||
const auto output = stage.outputs[index][comp];
|
||||
switch (output) {
|
||||
case Output::ClipDist0:
|
||||
case Output::ClipDist1:
|
||||
case Output::ClipDist2:
|
||||
case Output::ClipDist3:
|
||||
case Output::ClipDist4:
|
||||
case Output::ClipDist5:
|
||||
case Output::ClipDist6:
|
||||
case Output::ClipDist7: {
|
||||
const u32 index = u32(output) - u32(Output::ClipDist0);
|
||||
ir.SetAttribute(IR::Attribute::ClipDistance, value, index);
|
||||
break;
|
||||
}
|
||||
case Output::CullDist0:
|
||||
case Output::CullDist1:
|
||||
case Output::CullDist2:
|
||||
case Output::CullDist3:
|
||||
case Output::CullDist4:
|
||||
case Output::CullDist5:
|
||||
case Output::CullDist6:
|
||||
case Output::CullDist7: {
|
||||
const u32 index = u32(output) - u32(Output::CullDist0);
|
||||
ir.SetAttribute(IR::Attribute::CullDistance, value, index);
|
||||
break;
|
||||
}
|
||||
case Output::GsMrtIndex:
|
||||
ir.SetAttribute(IR::Attribute::RenderTargetId, value);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE_MSG("Unhandled output {} on attribute {}", u32(output), u32(attribute));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Shader::IR
|
||||
Reference in New Issue
Block a user