mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-10-11 22:49:55 +00:00
rsx/vk: Plumb programmable blending shader emitter
This commit is contained in:
@@ -344,7 +344,7 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
||||
OS << "void main()\n";
|
||||
OS << "{\n";
|
||||
|
||||
::glsl::insert_rop_init(OS);
|
||||
::glsl::insert_rop_init(OS, m_prog.mrt_buffers_count);
|
||||
|
||||
OS << "\n" << " fs_main();\n\n";
|
||||
|
||||
|
||||
@@ -151,8 +151,13 @@ namespace glsl
|
||||
;
|
||||
}
|
||||
|
||||
void insert_rop_init(std::ostream& OS)
|
||||
void insert_rop_init(std::ostream& OS, u32 mrt_buffer_count)
|
||||
{
|
||||
program_common::define_glsl_constants<u32>(OS,
|
||||
{
|
||||
{ "_MRT_BUFFERS_COUNT", mrt_buffer_count },
|
||||
});
|
||||
|
||||
OS <<
|
||||
#include "GLSLSnippets/RSXProg/RSXROPPrologue.glsl"
|
||||
;
|
||||
@@ -346,6 +351,11 @@ namespace glsl
|
||||
enabled_options.push_back("_ENABLE_ROP_CHANNEL_REMAPPING");
|
||||
}
|
||||
|
||||
if (props.ROP_programmable_blend)
|
||||
{
|
||||
enabled_options.push_back("_ENABLE_PROGRAMMABLE_BLENDING");
|
||||
}
|
||||
|
||||
if (props.require_fog_read)
|
||||
{
|
||||
program_common::define_glsl_constants<rsx::fog_mode>(OS,
|
||||
@@ -493,6 +503,11 @@ namespace glsl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (props.ROP_programmable_blend)
|
||||
{
|
||||
insert_blend_prologue(OS);
|
||||
}
|
||||
}
|
||||
|
||||
std::string getFunctionImpl(FUNCTION f)
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace glsl
|
||||
std::string getHalfTypeNameImpl(usz elementCount);
|
||||
std::string compareFunctionImpl(COMPARE f, std::string_view Op0, std::string_view Op1, bool scalar = false);
|
||||
void insert_vertex_input_fetch(std::stringstream& OS, glsl_rules rules, bool glsl4_compliant=true);
|
||||
void insert_rop_init(std::ostream& OS);
|
||||
void insert_rop_init(std::ostream& OS, u32 mrt_buffers_count);
|
||||
void insert_rop(std::ostream& OS, const shader_properties& props);
|
||||
void insert_glsl_legacy_function(std::ostream& OS, const shader_properties& props);
|
||||
std::string getFunctionImpl(FUNCTION f);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
R"(
|
||||
|
||||
#define _MRT_BUFFERS_COUNT 4 // TODO
|
||||
|
||||
#ifdef _32_BIT_OUTPUT
|
||||
// Everything is fp32 on ouput channels
|
||||
#define _mrt_color_t(expr) expr
|
||||
|
||||
@@ -4,9 +4,9 @@ R"(
|
||||
* Required register definitions from ROP config
|
||||
struct {
|
||||
vec4 blend_constants; // fp32x4
|
||||
uint blend_func; // rgb16, a16
|
||||
uint blend_factors_a; // src16, dst16
|
||||
uint blend_factors_rgb; // src16, dst16
|
||||
uint blend_eqn; // Packed RGB in lower 16 bits, A in upper 16 bits
|
||||
uint blend_sfactors; // Ditto
|
||||
uint blend_dfactors; // Ditto
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -91,9 +91,9 @@ vec3 get_blend_factor_rgb(const in uint op, const in vec4 src, const in vec4 dst
|
||||
|
||||
float apply_blend_func_a(const in vec4 src, const in vec4 dst)
|
||||
{
|
||||
uint blend_factor_a_s = _get_bits(blend_factors_a, 0, 16);
|
||||
uint blend_factor_a_d = _get_bits(blend_factors_a, 16, 16);
|
||||
uint func = _get_bits(blend_func, 16, 16);
|
||||
uint blend_factor_a_s = _get_bits(blend_sfactors, 16, 16);
|
||||
uint blend_factor_a_d = _get_bits(blend_dfactors, 16, 16);
|
||||
uint func = _get_bits(blend_eqn, 16, 16);
|
||||
|
||||
const float src_factor_a = get_blend_factor_a(blend_factor_a_s, src, dst);
|
||||
const float dst_factor_a = get_blend_factor_a(blend_factor_a_d, src, dst);
|
||||
@@ -119,9 +119,9 @@ float apply_blend_func_a(const in vec4 src, const in vec4 dst)
|
||||
|
||||
vec3 apply_blend_func_rgb(const in vec4 src, const in vec4 dst)
|
||||
{
|
||||
uint blend_factor_rgb_s = _get_bits(blend_factors_rgb, 0, 16);
|
||||
uint blend_factor_rgb_d = _get_bits(blend_factors_rgb, 16, 16);
|
||||
uint func = _get_bits(blend_func, 0, 16);
|
||||
uint blend_factor_rgb_s = _get_bits(blend_sfactors, 0, 16);
|
||||
uint blend_factor_rgb_d = _get_bits(blend_dfactors, 0, 16);
|
||||
uint func = _get_bits(blend_eqn, 0, 16);
|
||||
|
||||
const vec3 src_factor_rgb = get_blend_factor_rgb(blend_factor_rgb_s, src, dst);
|
||||
const vec3 dst_factor_rgb = get_blend_factor_rgb(blend_factor_rgb_d, src, dst);
|
||||
|
||||
@@ -20,11 +20,26 @@ R"(
|
||||
#endif
|
||||
|
||||
#if defined(_ENABLE_PROGRAMMABLE_BLENDING) && _MRT_BUFFERS_COUNT >= 1
|
||||
#define FRAG_LOAD(n) mrt_color[n] = subpassLoad(frag_src_##n)
|
||||
// TODO: Multisampled output support.
|
||||
vec4 mrt_color[_MRT_BUFFERS_COUNT];
|
||||
for (int n = 0; n < _MRT_BUFFERS_COUNT; ++n)
|
||||
{
|
||||
mrt_color[n] = subpassLoad(mrtAttachments[n]);
|
||||
}
|
||||
|
||||
#if _MRT_BUFFERS_COUNT >= 1
|
||||
FRAG_LOAD(0);
|
||||
#endif
|
||||
|
||||
#if _MRT_BUFFERS_COUNT >= 2
|
||||
FRAG_LOAD(1);
|
||||
#endif
|
||||
|
||||
#if _MRT_BUFFERS_COUNT >= 3
|
||||
FRAG_LOAD(2);
|
||||
#endif
|
||||
|
||||
#if _MRT_BUFFERS_COUNT == 4
|
||||
FRAG_LOAD(3);
|
||||
#endif
|
||||
|
||||
#undef FRAG_LOAD
|
||||
#endif
|
||||
)"
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace glsl
|
||||
bool ROP_polygon_stipple_test : 1;
|
||||
bool ROP_discard : 1;
|
||||
bool ROP_channel_remap : 1;
|
||||
bool ROP_programmable_blend : 1;
|
||||
|
||||
// Texturing spec
|
||||
bool require_texture_ops : 1; // Global switch to enable/disable all texture code
|
||||
|
||||
@@ -96,6 +96,15 @@ void VKFragmentDecompilerThread::prepareBindingTable()
|
||||
{
|
||||
vk_prog->binding_table.frag_depth_input_location = location++;
|
||||
}
|
||||
|
||||
std::memset(vk_prog->binding_table.frag_src_location, 0xff, sizeof(vk_prog->binding_table.frag_src_location));
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING)
|
||||
{
|
||||
for (u32 i = 0; i < m_prog.mrt_buffers_count; ++i)
|
||||
{
|
||||
vk_prog->binding_table.frag_src_location[i] = location++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKFragmentDecompilerThread::insertHeader(std::stringstream & OS)
|
||||
@@ -262,6 +271,22 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
));
|
||||
}
|
||||
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING)
|
||||
{
|
||||
for (u32 i = 0; i < m_prog.mrt_buffers_count; ++i)
|
||||
{
|
||||
OS << "layout(input_attachment_index= " << i << ", set=" << vk::glsl::binding_set_index_fragment << ", binding=" << vk_prog->binding_table.frag_src_location[i] << ") uniform subpassInput frag_src_" << i << ";\n";
|
||||
|
||||
inputs.push_back(vk::glsl::program_input::make(
|
||||
glsl::glsl_fragment_program,
|
||||
fmt::format("frag_src_%u", i),
|
||||
vk::glsl::input_type_attachment,
|
||||
vk::glsl::binding_set_index_fragment,
|
||||
vk_prog->binding_table.frag_src_location[i]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw params are always provided by vertex program. Instead of pointer chasing, they're provided as varyings.
|
||||
if (!(m_prog.ctrl & RSX_SHADER_CONTROL_INTERPRETER_MODEL))
|
||||
{
|
||||
@@ -300,6 +325,29 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
OS << " uvec4 stipple_pattern[];\n";
|
||||
OS << "};\n\n";
|
||||
|
||||
if (m_prog.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING)
|
||||
{
|
||||
OS <<
|
||||
"layout(push_constant) uniform push_constants_block\n"
|
||||
"{\n"
|
||||
" layout(offset = 4) uint blend_eqn;\n"
|
||||
" uint blend_sfactors;\n"
|
||||
" uint blend_dfactors;\n"
|
||||
" vec4 blend_constants;\n"
|
||||
"};\n\n";
|
||||
|
||||
vk::glsl::program_input push_constants
|
||||
{
|
||||
.domain = glsl::glsl_fragment_program,
|
||||
.type = vk::glsl::input_type_push_constant,
|
||||
.bound_data = vk::glsl::push_constant_ref{ .offset = 4, .size = 28 },
|
||||
.set = vk::glsl::binding_set_index_fragment,
|
||||
.location = umax,
|
||||
.name = "push_constants_block"
|
||||
};
|
||||
inputs.push_back(std::move(push_constants));
|
||||
}
|
||||
|
||||
vk::glsl::program_input in
|
||||
{
|
||||
.domain = glsl::glsl_fragment_program,
|
||||
@@ -357,6 +405,7 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
|
||||
m_shader_props.ROP_polygon_stipple_test = !!(m_prog.ctrl & RSX_SHADER_CONTROL_POLYGON_STIPPLE);
|
||||
m_shader_props.ROP_discard = !!(m_prog.ctrl & RSX_SHADER_CONTROL_USES_KIL);
|
||||
m_shader_props.ROP_channel_remap = !!(m_prog.ctrl & RSX_SHADER_CONTROL_ROP_OUTPUT_REMAP);
|
||||
m_shader_props.ROP_programmable_blend = !!(m_prog.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING);
|
||||
|
||||
m_shader_props.require_tex1D_ops = properties.has_tex1D;
|
||||
m_shader_props.require_tex2D_ops = properties.has_tex2D;
|
||||
@@ -499,7 +548,7 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
|
||||
" const float alpha_ref = fs_contexts[_fs_context_offset].alpha_ref;\n\n";
|
||||
}
|
||||
|
||||
::glsl::insert_rop_init(OS);
|
||||
::glsl::insert_rop_init(OS, m_prog.mrt_buffers_count);
|
||||
|
||||
OS << "\n" << " fs_main();\n\n";
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
u32 ftex_location[16]; // Texture locations array
|
||||
u32 ftex_stencil_location[16]; // Texture stencil mirror array
|
||||
u32 frag_depth_input_location = umax; // Fragment depth compare
|
||||
u32 frag_src_location[4]; // Fragment input attachment locations
|
||||
|
||||
} binding_table;
|
||||
|
||||
|
||||
@@ -2290,6 +2290,29 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_
|
||||
4,
|
||||
&push_val);
|
||||
|
||||
if (current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING)
|
||||
{
|
||||
// TODO: This should be cached aggressively.
|
||||
u32 blend_config[7];
|
||||
blend_config[0] = REGS(m_ctx)->registers[NV4097_SET_BLEND_EQUATION];
|
||||
blend_config[1] = REGS(m_ctx)->registers[NV4097_SET_BLEND_FUNC_SFACTOR];
|
||||
blend_config[2] = REGS(m_ctx)->registers[NV4097_SET_BLEND_FUNC_DFACTOR];
|
||||
|
||||
const auto blend_colors = rsx::get_constant_blend_colors();
|
||||
blend_config[3] = std::bit_cast<u32>(blend_colors[0]);
|
||||
blend_config[4] = std::bit_cast<u32>(blend_colors[1]);
|
||||
blend_config[5] = std::bit_cast<u32>(blend_colors[2]);
|
||||
blend_config[6] = std::bit_cast<u32>(blend_colors[3]);
|
||||
|
||||
vkCmdPushConstants(
|
||||
*m_current_command_buffer,
|
||||
m_program->layout(),
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
4,
|
||||
28,
|
||||
blend_config);
|
||||
}
|
||||
|
||||
// Now actually fill in the data
|
||||
m_draw_processor.fill_vertex_layout_state(
|
||||
m_vertex_layout,
|
||||
|
||||
@@ -60,6 +60,8 @@ namespace vk
|
||||
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
case input_type_storage_texture:
|
||||
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
case input_type_attachment:
|
||||
return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
default:
|
||||
fmt::throw_exception("Unexpected program input type %d", static_cast<int>(type));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace vk
|
||||
input_type_storage_buffer,
|
||||
input_type_storage_texture,
|
||||
input_type_push_constant,
|
||||
input_type_attachment,
|
||||
|
||||
// Meta
|
||||
input_type_max_enum,
|
||||
|
||||
@@ -454,9 +454,6 @@ namespace gcm
|
||||
RSX_SHADER_CONTROL_UNKNOWN0 = 0x00000400, // seemingly always set
|
||||
RSX_SHADER_CONTROL_UNKNOWN1 = 0x00008000, // seemingly set when srgb packer is used??
|
||||
|
||||
// Meta
|
||||
RSX_SHADER_CONTROL_GCM_FLAGS_MASK = 0x000007ff, // Reserved range for GCM flags. We don't care about most GCM-specific flags.
|
||||
|
||||
// Custom
|
||||
RSX_SHADER_CONTROL_FLAT_SHADING = 0x00000800, // Interpolate front/back colors using the provoking vertex
|
||||
RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION = 0x00010000, // Rasterizing triangles and not lines or points
|
||||
@@ -478,9 +475,11 @@ namespace gcm
|
||||
RSX_SHADER_CONTROL_MULTISAMPLED_ZBUFFER = 0x10000000, // Z buffer is multisampled. Only affects depth comparison behavior at this time.
|
||||
|
||||
RSX_SHADER_CONTROL_ROP_OUTPUT_REMAP = 0x20000000, // ROP outputs need channel swizzles.
|
||||
RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING = 0x40000000, // Enable programmable blending.
|
||||
|
||||
// Meta
|
||||
RSX_SHADER_CONTROL_META_USES_DISCARD = (RSX_SHADER_CONTROL_USES_KIL | RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL | RSX_SHADER_CONTROL_ALPHA_TEST | RSX_SHADER_CONTROL_POLYGON_STIPPLE | RSX_SHADER_CONTROL_ALPHA_TO_COVERAGE)
|
||||
RSX_SHADER_CONTROL_META_USES_DISCARD = (RSX_SHADER_CONTROL_USES_KIL | RSX_SHADER_CONTROL_TEXTURE_ALPHA_KILL | RSX_SHADER_CONTROL_ALPHA_TEST | RSX_SHADER_CONTROL_POLYGON_STIPPLE | RSX_SHADER_CONTROL_ALPHA_TO_COVERAGE),
|
||||
RSX_SHADER_CONTROL_META_GCM_FLAGS_MASK = 0x000007ff, // Reserved range for GCM flags. We don't care about most GCM-specific flags.
|
||||
};
|
||||
|
||||
// GCM Reports
|
||||
|
||||
Reference in New Issue
Block a user