1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 11:13:19 +01:00

rsx: Improve vertex textures support

- Adds proper support for vertex textures, including dimensions other than 2D textures
- Minor analyser fixup, removes spurious 'analyser failed' errors
- Minor optimizations for program state tracking
This commit is contained in:
kd-11 2018-07-09 21:31:31 +03:00 committed by kd-11
parent c5b2469fe7
commit fa55a8072c
20 changed files with 166 additions and 105 deletions

View File

@ -604,8 +604,13 @@ namespace glsl
return "dFdx($0)"; return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY: case FUNCTION::FUNCTION_DFDY:
return "dFdy($0)"; return "dFdy($0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH1D:
return "textureLod($t, $0.x, 0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
return "textureLod($t, $0.xy, 0)"; return "textureLod($t, $0.xy, 0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH3D:
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCHCUBE:
return "textureLod($t, $0.xyz, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "TEX2D_DEPTH_RGBA8($_i, $t, $0.xy)"; return "TEX2D_DEPTH_RGBA8($_i, $t, $0.xy)";
} }

View File

@ -31,7 +31,7 @@ size_t vertex_program_utils::get_vertex_program_ucode_hash(const RSXVertexProgra
vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vertex_program(const u32* data, u32 entry, RSXVertexProgram& dst_prog) vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vertex_program(const u32* data, u32 entry, RSXVertexProgram& dst_prog)
{ {
vertex_program_utils::vertex_program_metadata result; vertex_program_utils::vertex_program_metadata result{};
u32 last_instruction_address = 0; u32 last_instruction_address = 0;
u32 first_instruction_address = entry; u32 first_instruction_address = entry;
@ -79,6 +79,17 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
instruction_range.first = std::min(current_instrution, instruction_range.first); instruction_range.first = std::min(current_instrution, instruction_range.first);
instruction_range.second = std::max(current_instrution, instruction_range.second); instruction_range.second = std::max(current_instrution, instruction_range.second);
// Basic vec op analysis, must be done before flow analysis
switch (d1.vec_opcode)
{
case RSX_VEC_OPCODE_TXL:
{
d2.HEX = instruction->word[2];
result.referenced_textures_mask |= (1 << d2.tex_num);
break;
}
}
bool static_jump = false; bool static_jump = false;
bool function_call = true; bool function_call = true;
@ -223,7 +234,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
// Verification // Verification
for (const u32 target : dst_prog.jump_table) for (const u32 target : dst_prog.jump_table)
{ {
if (!result.instruction_mask[target]) if (!dst_prog.instruction_mask[target])
{ {
LOG_ERROR(RSX, "vp_analyser: Failed, branch target 0x%x was not resolved", target); LOG_ERROR(RSX, "vp_analyser: Failed, branch target 0x%x was not resolved", target);
} }
@ -237,6 +248,7 @@ size_t vertex_program_storage_hash::operator()(const RSXVertexProgram &program)
{ {
size_t hash = vertex_program_utils::get_vertex_program_ucode_hash(program); size_t hash = vertex_program_utils::get_vertex_program_ucode_hash(program);
hash ^= program.output_mask; hash ^= program.output_mask;
hash ^= program.texture_dimensions;
return hash; return hash;
} }
@ -244,6 +256,8 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
{ {
if (binary1.output_mask != binary2.output_mask) if (binary1.output_mask != binary2.output_mask)
return false; return false;
if (binary1.texture_dimensions != binary2.texture_dimensions)
return false;
if (binary1.data.size() != binary2.data.size()) if (binary1.data.size() != binary2.data.size())
return false; return false;
if (binary1.jump_table != binary2.jump_table) if (binary1.jump_table != binary2.jump_table)

View File

@ -31,6 +31,7 @@ namespace program_hash_util
{ {
std::bitset<512> instruction_mask; std::bitset<512> instruction_mask;
u32 ucode_length; u32 ucode_length;
u32 referenced_textures_mask;
}; };
static size_t get_vertex_program_ucode_hash(const RSXVertexProgram &program); static size_t get_vertex_program_ucode_hash(const RSXVertexProgram &program);

View File

@ -176,7 +176,24 @@ void VertexProgramDecompiler::SetDST(bool is_sca, std::string value)
std::string VertexProgramDecompiler::GetTex() std::string VertexProgramDecompiler::GetTex()
{ {
return m_parr.AddParam(PF_PARAM_UNIFORM, "sampler2D", std::string("vtex") + std::to_string(d2.tex_num)); std::string sampler;
switch (m_prog.get_texture_dimension(d2.tex_num))
{
case rsx::texture_dimension_extended::texture_dimension_1d:
sampler = "sampler1D";
break;
case rsx::texture_dimension_extended::texture_dimension_2d:
sampler = "sampler2D";
break;
case rsx::texture_dimension_extended::texture_dimension_3d:
sampler = "sampler3D";
break;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
sampler = "samplerCube";
break;
}
return m_parr.AddParam(PF_PARAM_UNIFORM, sampler, std::string("vtex") + std::to_string(d2.tex_num));
} }
std::string VertexProgramDecompiler::Format(const std::string& code) std::string VertexProgramDecompiler::Format(const std::string& code)
@ -612,8 +629,26 @@ std::string VertexProgramDecompiler::Decompile()
case RSX_VEC_OPCODE_SNE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SNE, "$0", "$1") + ")"); break; case RSX_VEC_OPCODE_SNE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SNE, "$0", "$1") + ")"); break;
case RSX_VEC_OPCODE_STR: SetDSTVec(getFunction(FUNCTION::FUNCTION_STR)); break; case RSX_VEC_OPCODE_STR: SetDSTVec(getFunction(FUNCTION::FUNCTION_STR)); break;
case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break; case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break;
case RSX_VEC_OPCODE_TXL: SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D)); break; case RSX_VEC_OPCODE_TXL:
{
switch (m_prog.get_texture_dimension(d2.tex_num))
{
case rsx::texture_dimension_extended::texture_dimension_1d:
SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH1D));
break;
case rsx::texture_dimension_extended::texture_dimension_2d:
SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D));
break;
case rsx::texture_dimension_extended::texture_dimension_3d:
SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH3D));
break;
case rsx::texture_dimension_extended::texture_dimension_cubemap:
SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCHCUBE));
break;
}
break;
}
default: default:
AddCode(fmt::format("//Unknown vp opcode 0x%x", u32{ d1.vec_opcode })); AddCode(fmt::format("//Unknown vp opcode 0x%x", u32{ d1.vec_opcode }));
LOG_ERROR(RSX, "Unknown vp opcode 0x%x", u32{ d1.vec_opcode }); LOG_ERROR(RSX, "Unknown vp opcode 0x%x", u32{ d1.vec_opcode });

View File

@ -25,7 +25,7 @@ std::string getFunctionImp(FUNCTION f)
switch (f) switch (f)
{ {
default: default:
abort(); fmt::throw_exception("Unsupported program function %d", (u32)f);
case FUNCTION::FUNCTION_DP2: case FUNCTION::FUNCTION_DP2:
return "dot($0.xy, $1.xy).xxxx"; return "dot($0.xy, $1.xy).xxxx";
case FUNCTION::FUNCTION_DP2A: case FUNCTION::FUNCTION_DP2A:

View File

@ -6,6 +6,7 @@
#include "D3D12Formats.h" #include "D3D12Formats.h"
#include "../rsx_methods.h" #include "../rsx_methods.h"
#include "../rsx_utils.h" #include "../rsx_utils.h"
#include "../Common/TextureUtils.h"
#define TO_STRING(x) #x #define TO_STRING(x) #x
@ -53,7 +54,7 @@ void D3D12GSRender::load_program()
return std::make_tuple(true, native_pitch); return std::make_tuple(true, native_pitch);
}; };
get_current_vertex_program(false); get_current_vertex_program({}, true);
get_current_fragment_program_legacy(rtt_lookup_func); get_current_fragment_program_legacy(rtt_lookup_func);
if (!current_fragment_program.valid) if (!current_fragment_program.valid)

View File

@ -24,7 +24,7 @@ namespace
GLGSRender::GLGSRender() : GSRender() GLGSRender::GLGSRender() : GSRender()
{ {
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.5")); m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.6"));
if (g_cfg.video.disable_vertex_cache) if (g_cfg.video.disable_vertex_cache)
m_vertex_cache.reset(new gl::null_vertex_cache()); m_vertex_cache.reset(new gl::null_vertex_cache());
@ -330,7 +330,7 @@ void GLGSRender::end()
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.fragment_textures[i], m_rtts); *sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.fragment_textures[i], m_rtts);
if (m_textures_dirty[i]) if (m_textures_dirty[i])
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i], fs_sampler_state[i].get()); m_fs_sampler_states[i].apply(rsx::method_registers.fragment_textures[i], fs_sampler_state[i].get());
} }
else else
{ {
@ -354,6 +354,9 @@ void GLGSRender::end()
if (rsx::method_registers.vertex_textures[i].enabled()) if (rsx::method_registers.vertex_textures[i].enabled())
{ {
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.vertex_textures[i], m_rtts); *sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.vertex_textures[i], m_rtts);
if (m_vertex_textures_dirty[i])
m_vs_sampler_states[i].apply(rsx::method_registers.vertex_textures[i], vs_sampler_state[i].get());
} }
else else
*sampler_state = {}; *sampler_state = {};
@ -783,8 +786,14 @@ void GLGSRender::on_init_thread()
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{ {
m_gl_sampler_states[i].create(); m_fs_sampler_states[i].create();
m_gl_sampler_states[i].bind(i); m_fs_sampler_states[i].bind(i);
}
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
m_vs_sampler_states[i].create();
m_vs_sampler_states[i].bind(rsx::limits::fragment_textures_count + i);
} }
//Occlusion query //Occlusion query
@ -917,7 +926,12 @@ void GLGSRender::on_exit()
m_gl_persistent_stream_buffer.reset(); m_gl_persistent_stream_buffer.reset();
m_gl_volatile_stream_buffer.reset(); m_gl_volatile_stream_buffer.reset();
for (auto &sampler : m_gl_sampler_states) for (auto &sampler : m_fs_sampler_states)
{
sampler.remove();
}
for (auto &sampler : m_vs_sampler_states)
{ {
sampler.remove(); sampler.remove();
} }
@ -1101,7 +1115,7 @@ void GLGSRender::load_program(const gl::vertex_upload_info& upload_info)
get_current_fragment_program(fs_sampler_state); get_current_fragment_program(fs_sampler_state);
verify(HERE), current_fragment_program.valid; verify(HERE), current_fragment_program.valid;
get_current_vertex_program(); get_current_vertex_program(vs_sampler_state);
current_vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side current_vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side
current_fragment_program.unnormalized_coords = 0; //unused current_fragment_program.unnormalized_coords = 0; //unused

View File

@ -279,7 +279,8 @@ private:
GLFragmentProgram m_fragment_prog; GLFragmentProgram m_fragment_prog;
GLVertexProgram m_vertex_prog; GLVertexProgram m_vertex_prog;
gl::sampler_state m_gl_sampler_states[rsx::limits::fragment_textures_count]; gl::sampler_state m_fs_sampler_states[rsx::limits::fragment_textures_count];
gl::sampler_state m_vs_sampler_states[rsx::limits::vertex_textures_count];
gl::glsl::program *m_program; gl::glsl::program *m_program;

View File

@ -48,14 +48,14 @@ struct GLTraits
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{ {
int location; int location;
if (result.uniforms.has_location("tex" + std::to_string(i), &location)) if (result.uniforms.has_location(rsx::constants::fragment_texture_names[i], &location))
result.uniforms[location] = i; result.uniforms[location] = i;
} }
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{ {
int location; int location;
if (result.uniforms.has_location("vtex" + std::to_string(i), &location)) if (result.uniforms.has_location(rsx::constants::vertex_texture_names[i], &location))
result.uniforms[location] = (i + rsx::limits::fragment_textures_count); result.uniforms[location] = (i + rsx::limits::fragment_textures_count);
} }

View File

@ -204,7 +204,7 @@ namespace gl
} }
//Apply sampler state settings //Apply sampler state settings
void sampler_state::apply(rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image) void sampler_state::apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image)
{ {
const color4f border_color = rsx::decode_border_color(tex.border_color()); const color4f border_color = rsx::decode_border_color(tex.border_color());
@ -274,6 +274,22 @@ namespace gl
glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE); glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE);
} }
void sampler_state::apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* /*sampled_image*/)
{
const color4f border_color = rsx::decode_border_color(tex.border_color());
glSamplerParameterfv(samplerHandle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, tex.bias());
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
bool is_compressed_format(u32 texture_format) bool is_compressed_format(u32 texture_format)
{ {
switch (texture_format) switch (texture_format)

View File

@ -57,6 +57,7 @@ namespace gl
glBindSampler(index, samplerHandle); glBindSampler(index, samplerHandle);
} }
void apply(rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image); void apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
void apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
}; };
} }

View File

@ -191,17 +191,6 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS)
OS << " vec4 " << PI.name << "= read_location(" << std::to_string(PI.location) << ");\n"; OS << " vec4 " << PI.name << "= read_location(" << std::to_string(PI.location) << ");\n";
} }
} }
for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type == "sampler2D")
{
for (const ParamItem &PI : PT.items)
{
OS << " vec2 " << PI.name << "_coord_scale = vec2(1.);\n";
}
}
}
} }
void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)

View File

@ -396,11 +396,6 @@ namespace rsx
return (max_mipmap_count > 0) ? max_mipmap_count : 1; return (max_mipmap_count > 0) ? max_mipmap_count : 1;
} }
u8 vertex_texture::unsigned_remap() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf);
}
std::pair<std::array<u8, 4>, std::array<u8, 4>> vertex_texture::decoded_remap() const std::pair<std::array<u8, 4>, std::array<u8, 4>> vertex_texture::decoded_remap() const
{ {
return return
@ -416,26 +411,6 @@ namespace rsx
return 0xAAE4; return 0xAAE4;
} }
u8 vertex_texture::zfunc() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf);
}
u8 vertex_texture::gamma() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf);
}
u8 vertex_texture::aniso_bias() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf);
}
u8 vertex_texture::signed_remap() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf);
}
bool vertex_texture::enabled() const bool vertex_texture::enabled() const
{ {
return location() <= 1 && ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1); return location() <= 1 && ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1);
@ -451,16 +426,6 @@ namespace rsx
return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff);
} }
rsx::texture_max_anisotropy vertex_texture::max_aniso() const
{
return rsx::to_texture_max_anisotropy((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7);
}
bool vertex_texture::alpha_kill_enabled() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1);
}
u16 vertex_texture::bias() const u16 vertex_texture::bias() const
{ {
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff);
@ -468,37 +433,27 @@ namespace rsx
rsx::texture_minify_filter vertex_texture::min_filter() const rsx::texture_minify_filter vertex_texture::min_filter() const
{ {
return rsx::to_texture_minify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7); return rsx::texture_minify_filter::nearest;
} }
rsx::texture_magnify_filter vertex_texture::mag_filter() const rsx::texture_magnify_filter vertex_texture::mag_filter() const
{ {
return rsx::to_texture_magnify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7); return rsx::texture_magnify_filter::nearest;
} }
u8 vertex_texture::convolution_filter() const rsx::texture_wrap_mode vertex_texture::wrap_s() const
{ {
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf); return rsx::to_texture_wrap_mode((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)]) & 0xf);
} }
bool vertex_texture::a_signed() const rsx::texture_wrap_mode vertex_texture::wrap_t() const
{ {
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1); return rsx::to_texture_wrap_mode((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 8) & 0xf);
} }
bool vertex_texture::r_signed() const rsx::texture_wrap_mode vertex_texture::wrap_r() const
{ {
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1); return rsx::texture_wrap_mode::wrap;
}
bool vertex_texture::g_signed() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1);
}
bool vertex_texture::b_signed() const
{
return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1);
} }
u16 vertex_texture::width() const u16 vertex_texture::width() const

View File

@ -123,11 +123,9 @@ namespace rsx
u16 mipmap() const; u16 mipmap() const;
// Address // Address
u8 unsigned_remap() const; rsx::texture_wrap_mode wrap_s() const;
u8 zfunc() const; rsx::texture_wrap_mode wrap_t() const;
u8 gamma() const; rsx::texture_wrap_mode wrap_r() const;
u8 aniso_bias() const;
u8 signed_remap() const;
std::pair<std::array<u8, 4>, std::array<u8, 4>> decoded_remap() const; std::pair<std::array<u8, 4>, std::array<u8, 4>> decoded_remap() const;
u32 remap() const; u32 remap() const;
@ -136,18 +134,11 @@ namespace rsx
bool enabled() const; bool enabled() const;
u16 min_lod() const; u16 min_lod() const;
u16 max_lod() const; u16 max_lod() const;
rsx::texture_max_anisotropy max_aniso() const;
bool alpha_kill_enabled() const;
// Filter // Filter
u16 bias() const; u16 bias() const;
rsx::texture_minify_filter min_filter() const; rsx::texture_minify_filter min_filter() const;
rsx::texture_magnify_filter mag_filter() const; rsx::texture_magnify_filter mag_filter() const;
u8 convolution_filter() const;
bool a_signed() const;
bool r_signed() const;
bool g_signed() const;
bool b_signed() const;
// Image Rect // Image Rect
u16 width() const; u16 width() const;

View File

@ -829,15 +829,15 @@ namespace rsx
} }
default: default:
{ {
//TODO: Reorder draw commands between synchronization events to maximize batched sizes // TODO: Reorder draw commands between synchronization events to maximize batched sizes
static const std::pair<u32, u32> skippable_ranges[] = static const std::pair<u32, u32> skippable_ranges[] =
{ {
//Texture configuration // Texture configuration
{ NV4097_SET_TEXTURE_OFFSET, 8 * 16 }, { NV4097_SET_TEXTURE_OFFSET, 8 * 16 },
{ NV4097_SET_TEXTURE_CONTROL2, 16 }, { NV4097_SET_TEXTURE_CONTROL2, 16 },
{ NV4097_SET_TEXTURE_CONTROL3, 16 }, { NV4097_SET_TEXTURE_CONTROL3, 16 },
{ NV4097_SET_VERTEX_TEXTURE_OFFSET, 8 * 4 }, { NV4097_SET_VERTEX_TEXTURE_OFFSET, 8 * 4 },
//Surface configuration // Surface configuration
{ NV4097_SET_SURFACE_CLIP_HORIZONTAL, 1 }, { NV4097_SET_SURFACE_CLIP_HORIZONTAL, 1 },
{ NV4097_SET_SURFACE_CLIP_VERTICAL, 1 }, { NV4097_SET_SURFACE_CLIP_VERTICAL, 1 },
{ NV4097_SET_SURFACE_COLOR_AOFFSET, 1 }, { NV4097_SET_SURFACE_COLOR_AOFFSET, 1 },
@ -855,7 +855,11 @@ namespace rsx
{ NV4097_SET_SURFACE_PITCH_B, 1 }, { NV4097_SET_SURFACE_PITCH_B, 1 },
{ NV4097_SET_SURFACE_PITCH_C, 1 }, { NV4097_SET_SURFACE_PITCH_C, 1 },
{ NV4097_SET_SURFACE_PITCH_D, 1 }, { NV4097_SET_SURFACE_PITCH_D, 1 },
{ NV4097_SET_SURFACE_PITCH_Z, 1 } { NV4097_SET_SURFACE_PITCH_Z, 1 },
// Program configuration
{ NV4097_SET_TRANSFORM_PROGRAM_START, 1 },
{ NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, 1 },
{ NV4097_SET_TRANSFORM_PROGRAM, 512 }
}; };
if (has_deferred_call) if (has_deferred_call)
@ -1393,7 +1397,7 @@ namespace rsx
return rsx::get_address(offset_zeta, m_context_dma_z); return rsx::get_address(offset_zeta, m_context_dma_z);
} }
void thread::get_current_vertex_program(bool skip_vertex_inputs) void thread::get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures, bool skip_vertex_inputs)
{ {
if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty)) if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty))
return; return;
@ -1406,6 +1410,7 @@ namespace rsx
current_vertex_program.rsx_vertex_inputs.resize(0); current_vertex_program.rsx_vertex_inputs.resize(0);
current_vertex_program.data.reserve(512 * 4); current_vertex_program.data.reserve(512 * 4);
current_vertex_program.jump_table.clear(); current_vertex_program.jump_table.clear();
current_vertex_program.texture_dimensions = 0;
current_vp_metadata = program_hash_util::vertex_program_utils::analyse_vertex_program current_vp_metadata = program_hash_util::vertex_program_utils::analyse_vertex_program
( (
@ -1414,6 +1419,18 @@ namespace rsx
current_vertex_program // [out] Program object current_vertex_program // [out] Program object
); );
if (!skip_textures && current_vp_metadata.referenced_textures_mask != 0)
{
for (u32 i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
const auto &tex = rsx::method_registers.vertex_textures[i];
if (tex.enabled() && (current_vp_metadata.referenced_textures_mask & (1 << i)))
{
current_vertex_program.texture_dimensions |= ((u32)sampler_descriptors[i]->image_type << (i << 1));
}
}
}
if (!skip_vertex_inputs) if (!skip_vertex_inputs)
{ {
const u32 input_mask = rsx::method_registers.vertex_attrib_input_mask(); const u32 input_mask = rsx::method_registers.vertex_attrib_input_mask();

View File

@ -362,6 +362,9 @@ namespace rsx
u32 m_graphics_state = 0; u32 m_graphics_state = 0;
u64 ROP_sync_timestamp = 0; u64 ROP_sync_timestamp = 0;
program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {};
program_hash_util::vertex_program_utils::vertex_program_metadata current_vp_metadata = {};
protected: protected:
std::array<u32, 4> get_color_surface_addresses() const; std::array<u32, 4> get_color_surface_addresses() const;
u32 get_zeta_surface_address() const; u32 get_zeta_surface_address() const;
@ -374,10 +377,7 @@ namespace rsx
RSXVertexProgram current_vertex_program = {}; RSXVertexProgram current_vertex_program = {};
RSXFragmentProgram current_fragment_program = {}; RSXFragmentProgram current_fragment_program = {};
program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {}; void get_current_vertex_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures = false, bool skip_vertex_inputs = true);
program_hash_util::vertex_program_utils::vertex_program_metadata current_vp_metadata = {};
void get_current_vertex_program(bool skip_vertex_inputs = true);
/** /**
* Gets current fragment program and associated fragment state * Gets current fragment program and associated fragment state

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "RSXTexture.h"
#include <bitset> #include <bitset>
#include <set> #include <set>
@ -231,10 +233,16 @@ struct RSXVertexProgram
std::vector<u32> data; std::vector<u32> data;
std::vector<rsx_vertex_input> rsx_vertex_inputs; std::vector<rsx_vertex_input> rsx_vertex_inputs;
u32 output_mask; u32 output_mask;
u32 texture_dimensions;
bool skip_vertex_input_check; bool skip_vertex_input_check;
u32 base_address; u32 base_address;
u32 entry; u32 entry;
std::bitset<512> instruction_mask; std::bitset<512> instruction_mask;
std::set<u32> jump_table; std::set<u32> jump_table;
rsx::texture_dimension_extended get_texture_dimension(u8 id) const
{
return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);
}
}; };

View File

@ -626,7 +626,7 @@ VKGSRender::VKGSRender() : GSRender()
else else
m_vertex_cache.reset(new vk::weak_vertex_cache()); m_vertex_cache.reset(new vk::weak_vertex_cache());
m_shaders_cache.reset(new vk::shader_cache(*m_prog_buffer.get(), "vulkan", "v1.5")); m_shaders_cache.reset(new vk::shader_cache(*m_prog_buffer.get(), "vulkan", "v1.6"));
open_command_buffer(); open_command_buffer();
@ -2200,7 +2200,7 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info)
get_current_fragment_program(fs_sampler_state); get_current_fragment_program(fs_sampler_state);
verify(HERE), current_fragment_program.valid; verify(HERE), current_fragment_program.valid;
get_current_vertex_program(); get_current_vertex_program(vs_sampler_state);
} }
auto &vertex_program = current_vertex_program; auto &vertex_program = current_vertex_program;

View File

@ -378,6 +378,7 @@ namespace rsx
u64 pipeline_storage_hash; u64 pipeline_storage_hash;
u32 vp_ctrl; u32 vp_ctrl;
u32 vp_texture_dimensions;
u64 vp_instruction_mask[8]; u64 vp_instruction_mask[8];
u32 vp_base_address; u32 vp_base_address;
@ -698,6 +699,7 @@ namespace rsx
u64 state_hash = 0; u64 state_hash = 0;
state_hash ^= rpcs3::hash_base<u32>(data.vp_ctrl); state_hash ^= rpcs3::hash_base<u32>(data.vp_ctrl);
state_hash ^= rpcs3::hash_base<u32>(data.fp_ctrl); state_hash ^= rpcs3::hash_base<u32>(data.fp_ctrl);
state_hash ^= rpcs3::hash_base<u32>(data.vp_texture_dimensions);
state_hash ^= rpcs3::hash_base<u32>(data.fp_texture_dimensions); state_hash ^= rpcs3::hash_base<u32>(data.fp_texture_dimensions);
state_hash ^= rpcs3::hash_base<u16>(data.fp_unnormalized_coords); state_hash ^= rpcs3::hash_base<u16>(data.fp_unnormalized_coords);
state_hash ^= rpcs3::hash_base<u16>(data.fp_height); state_hash ^= rpcs3::hash_base<u16>(data.fp_height);
@ -750,6 +752,7 @@ namespace rsx
pipeline_storage_type pipeline = data.pipeline_properties; pipeline_storage_type pipeline = data.pipeline_properties;
vp.output_mask = data.vp_ctrl; vp.output_mask = data.vp_ctrl;
vp.texture_dimensions = data.vp_texture_dimensions;
vp.base_address = data.vp_base_address; vp.base_address = data.vp_base_address;
vp.entry = data.vp_entry; vp.entry = data.vp_entry;
@ -796,6 +799,7 @@ namespace rsx
data_block.pipeline_storage_hash = m_storage.get_hash(pipeline); data_block.pipeline_storage_hash = m_storage.get_hash(pipeline);
data_block.vp_ctrl = vp.output_mask; data_block.vp_ctrl = vp.output_mask;
data_block.vp_texture_dimensions = vp.texture_dimensions;
data_block.vp_base_address = vp.base_address; data_block.vp_base_address = vp.base_address;
data_block.vp_entry = vp.entry; data_block.vp_entry = vp.entry;

View File

@ -563,7 +563,11 @@ namespace rsx
static void impl(thread* rsx, u32 _reg, u32 arg) static void impl(thread* rsx, u32 _reg, u32 arg)
{ {
rsx->m_textures_dirty[index] = true; rsx->m_textures_dirty[index] = true;
rsx->m_graphics_state |= rsx::pipeline_state::fragment_program_dirty;
if (rsx->current_fp_metadata.referenced_textures_mask & (1 << index))
{
rsx->m_graphics_state |= rsx::pipeline_state::fragment_program_dirty;
}
} }
}; };
@ -573,6 +577,11 @@ namespace rsx
static void impl(thread* rsx, u32 _reg, u32 arg) static void impl(thread* rsx, u32 _reg, u32 arg)
{ {
rsx->m_vertex_textures_dirty[index] = true; rsx->m_vertex_textures_dirty[index] = true;
if (rsx->current_vp_metadata.referenced_textures_mask & (1 << index))
{
rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty;
}
} }
}; };
} }