mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-25 20:06:17 +00:00
shader_recompiler: Implement dual source blending (#3054)
This commit is contained in:
parent
2bc199a41b
commit
952cef5a15
6 changed files with 47 additions and 4 deletions
|
@ -634,7 +634,8 @@ void EmitContext::DefineOutputs() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LogicalStage::Fragment:
|
case LogicalStage::Fragment: {
|
||||||
|
u32 num_render_targets = 0;
|
||||||
for (u32 i = 0; i < IR::NumRenderTargets; i++) {
|
for (u32 i = 0; i < IR::NumRenderTargets; i++) {
|
||||||
const IR::Attribute mrt{IR::Attribute::RenderTarget0 + i};
|
const IR::Attribute mrt{IR::Attribute::RenderTarget0 + i};
|
||||||
if (!info.stores.GetAny(mrt)) {
|
if (!info.stores.GetAny(mrt)) {
|
||||||
|
@ -643,11 +644,21 @@ void EmitContext::DefineOutputs() {
|
||||||
const u32 num_components = info.stores.NumComponents(mrt);
|
const u32 num_components = info.stores.NumComponents(mrt);
|
||||||
const AmdGpu::NumberFormat num_format{runtime_info.fs_info.color_buffers[i].num_format};
|
const AmdGpu::NumberFormat num_format{runtime_info.fs_info.color_buffers[i].num_format};
|
||||||
const Id type{GetAttributeType(*this, num_format)[num_components]};
|
const Id type{GetAttributeType(*this, num_format)[num_components]};
|
||||||
const Id id{DefineOutput(type, i)};
|
Id id;
|
||||||
|
if (runtime_info.fs_info.dual_source_blending) {
|
||||||
|
id = DefineOutput(type, 0);
|
||||||
|
Decorate(id, spv::Decoration::Index, i);
|
||||||
|
} else {
|
||||||
|
id = DefineOutput(type, i);
|
||||||
|
}
|
||||||
Name(id, fmt::format("frag_color{}", i));
|
Name(id, fmt::format("frag_color{}", i));
|
||||||
frag_outputs[i] = GetAttributeInfo(num_format, id, num_components, true);
|
frag_outputs[i] = GetAttributeInfo(num_format, id, num_components, true);
|
||||||
|
++num_render_targets;
|
||||||
}
|
}
|
||||||
|
ASSERT_MSG(!runtime_info.fs_info.dual_source_blending || num_render_targets == 2,
|
||||||
|
"Dual source blending enabled, there must be exactly two MRT exports");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case LogicalStage::Geometry: {
|
case LogicalStage::Geometry: {
|
||||||
output_position = DefineVariable(F32[4], spv::BuiltIn::Position, spv::StorageClass::Output);
|
output_position = DefineVariable(F32[4], spv::BuiltIn::Position, spv::StorageClass::Output);
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,11 @@ void Translator::ExportMrtValue(IR::Attribute attribute, u32 comp, const IR::F32
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value) {
|
void Translator::ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value) {
|
||||||
const u32 color_buffer_idx =
|
u32 color_buffer_idx =
|
||||||
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
|
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
|
||||||
|
if (runtime_info.fs_info.dual_source_blending && attribute == IR::Attribute::RenderTarget1) {
|
||||||
|
color_buffer_idx = 0;
|
||||||
|
}
|
||||||
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
|
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
|
||||||
|
|
||||||
AmdGpu::NumberFormat num_format;
|
AmdGpu::NumberFormat num_format;
|
||||||
|
@ -68,8 +71,11 @@ void Translator::ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::ExportMrtUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value) {
|
void Translator::ExportMrtUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value) {
|
||||||
const u32 color_buffer_idx =
|
u32 color_buffer_idx =
|
||||||
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
|
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
|
||||||
|
if (runtime_info.fs_info.dual_source_blending && attribute == IR::Attribute::RenderTarget1) {
|
||||||
|
color_buffer_idx = 0;
|
||||||
|
}
|
||||||
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
|
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
|
||||||
const auto swizzled_comp = SwizzleMrtComponent(color_buffer, comp);
|
const auto swizzled_comp = SwizzleMrtComponent(color_buffer, comp);
|
||||||
|
|
||||||
|
|
|
@ -196,11 +196,13 @@ struct FragmentRuntimeInfo {
|
||||||
u32 num_inputs;
|
u32 num_inputs;
|
||||||
std::array<PsInput, 32> inputs;
|
std::array<PsInput, 32> inputs;
|
||||||
std::array<PsColorBuffer, MaxColorBuffers> color_buffers;
|
std::array<PsColorBuffer, MaxColorBuffers> color_buffers;
|
||||||
|
bool dual_source_blending;
|
||||||
|
|
||||||
bool operator==(const FragmentRuntimeInfo& other) const noexcept {
|
bool operator==(const FragmentRuntimeInfo& other) const noexcept {
|
||||||
return std::ranges::equal(color_buffers, other.color_buffers) &&
|
return std::ranges::equal(color_buffers, other.color_buffers) &&
|
||||||
en_flags.raw == other.en_flags.raw && addr_flags.raw == other.addr_flags.raw &&
|
en_flags.raw == other.en_flags.raw && addr_flags.raw == other.addr_flags.raw &&
|
||||||
num_inputs == other.num_inputs &&
|
num_inputs == other.num_inputs &&
|
||||||
|
dual_source_blending == other.dual_source_blending &&
|
||||||
std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(),
|
std::ranges::equal(inputs.begin(), inputs.begin() + num_inputs, other.inputs.begin(),
|
||||||
other.inputs.begin() + num_inputs);
|
other.inputs.begin() + num_inputs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,19 @@ vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsDualSourceBlendFactor(Liverpool::BlendControl::BlendFactor factor) {
|
||||||
|
using BlendFactor = Liverpool::BlendControl::BlendFactor;
|
||||||
|
switch (factor) {
|
||||||
|
case BlendFactor::Src1Color:
|
||||||
|
case BlendFactor::Src1Alpha:
|
||||||
|
case BlendFactor::InvSrc1Color:
|
||||||
|
case BlendFactor::InvSrc1Alpha:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func) {
|
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func) {
|
||||||
using BlendFunc = Liverpool::BlendControl::BlendFunc;
|
using BlendFunc = Liverpool::BlendControl::BlendFunc;
|
||||||
switch (func) {
|
switch (func) {
|
||||||
|
|
|
@ -30,6 +30,8 @@ vk::FrontFace FrontFace(Liverpool::FrontFace mode);
|
||||||
|
|
||||||
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
||||||
|
|
||||||
|
bool IsDualSourceBlendFactor(Liverpool::BlendControl::BlendFactor factor);
|
||||||
|
|
||||||
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);
|
||||||
|
|
||||||
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode);
|
vk::SamplerAddressMode ClampMode(AmdGpu::ClampMode mode);
|
||||||
|
|
|
@ -158,6 +158,15 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
|
||||||
info.fs_info.addr_flags = regs.ps_input_addr;
|
info.fs_info.addr_flags = regs.ps_input_addr;
|
||||||
const auto& ps_inputs = regs.ps_inputs;
|
const auto& ps_inputs = regs.ps_inputs;
|
||||||
info.fs_info.num_inputs = regs.num_interp;
|
info.fs_info.num_inputs = regs.num_interp;
|
||||||
|
const auto& cb0_blend = regs.blend_control[0];
|
||||||
|
info.fs_info.dual_source_blending =
|
||||||
|
LiverpoolToVK::IsDualSourceBlendFactor(cb0_blend.color_dst_factor) ||
|
||||||
|
LiverpoolToVK::IsDualSourceBlendFactor(cb0_blend.color_src_factor);
|
||||||
|
if (cb0_blend.separate_alpha_blend) {
|
||||||
|
info.fs_info.dual_source_blending |=
|
||||||
|
LiverpoolToVK::IsDualSourceBlendFactor(cb0_blend.alpha_dst_factor) ||
|
||||||
|
LiverpoolToVK::IsDualSourceBlendFactor(cb0_blend.alpha_src_factor);
|
||||||
|
}
|
||||||
for (u32 i = 0; i < regs.num_interp; i++) {
|
for (u32 i = 0; i < regs.num_interp; i++) {
|
||||||
info.fs_info.inputs[i] = {
|
info.fs_info.inputs[i] = {
|
||||||
.param_index = u8(ps_inputs[i].input_offset.Value()),
|
.param_index = u8(ps_inputs[i].input_offset.Value()),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue