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:
parent
c5b2469fe7
commit
fa55a8072c
@ -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)";
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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 });
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user