mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
rsx: Invalidate program cache hint if the current vertex or fragment program is re-evaluated
This commit is contained in:
parent
ec5b2bc8d2
commit
b2ed787c3a
3 changed files with 113 additions and 47 deletions
|
@ -533,16 +533,16 @@ AVX512_ICL_FUNC bool vertex_program_compare_512(const RSXVertexProgram &binary1,
|
||||||
|
|
||||||
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
|
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
|
||||||
{
|
{
|
||||||
if (binary1.output_mask != binary2.output_mask)
|
if (!compare_properties(binary1, binary2))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
if (binary1.ctrl != binary2.ctrl)
|
}
|
||||||
return false;
|
|
||||||
if (binary1.texture_state != binary2.texture_state)
|
if (binary1.data.size() != binary2.data.size() ||
|
||||||
return false;
|
binary1.jump_table != binary2.jump_table)
|
||||||
if (binary1.data.size() != binary2.data.size())
|
{
|
||||||
return false;
|
|
||||||
if (binary1.jump_table != binary2.jump_table)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ARCH_X64
|
#ifdef ARCH_X64
|
||||||
if (utils::has_avx512_icl())
|
if (utils::has_avx512_icl())
|
||||||
|
@ -572,6 +572,13 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vertex_program_compare::compare_properties(const RSXVertexProgram& binary1, const RSXVertexProgram& binary2)
|
||||||
|
{
|
||||||
|
return binary1.output_mask == binary2.output_mask &&
|
||||||
|
binary1.ctrl == binary2.ctrl &&
|
||||||
|
binary1.texture_state == binary2.texture_state;
|
||||||
|
}
|
||||||
|
|
||||||
bool fragment_program_utils::is_any_src_constant(v128 sourceOperand)
|
bool fragment_program_utils::is_any_src_constant(v128 sourceOperand)
|
||||||
{
|
{
|
||||||
const u64 masked = sourceOperand._u64[1] & 0x30000000300;
|
const u64 masked = sourceOperand._u64[1] & 0x30000000300;
|
||||||
|
@ -741,12 +748,7 @@ usz fragment_program_storage_hash::operator()(const RSXFragmentProgram& program)
|
||||||
|
|
||||||
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
|
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
|
||||||
{
|
{
|
||||||
if (binary1.ucode_length != binary2.ucode_length ||
|
if (!compare_properties(binary1, binary2))
|
||||||
binary1.ctrl != binary2.ctrl ||
|
|
||||||
binary1.texture_state != binary2.texture_state ||
|
|
||||||
binary1.texcoord_control_mask != binary2.texcoord_control_mask ||
|
|
||||||
binary1.two_sided_lighting != binary2.two_sided_lighting ||
|
|
||||||
binary1.mrt_buffers_count != binary2.mrt_buffers_count)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -771,19 +773,14 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fragment_program_compare::config_only(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2)
|
bool fragment_program_compare::compare_properties(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2)
|
||||||
{
|
{
|
||||||
if (binary1.ucode_length != binary2.ucode_length ||
|
return binary1.ucode_length == binary2.ucode_length &&
|
||||||
binary1.ctrl != binary2.ctrl ||
|
binary1.ctrl == binary2.ctrl &&
|
||||||
binary1.texture_state != binary2.texture_state ||
|
binary1.texture_state == binary2.texture_state &&
|
||||||
binary1.texcoord_control_mask != binary2.texcoord_control_mask ||
|
binary1.texcoord_control_mask == binary2.texcoord_control_mask &&
|
||||||
binary1.two_sided_lighting != binary2.two_sided_lighting ||
|
binary1.two_sided_lighting == binary2.two_sided_lighting &&
|
||||||
binary1.mrt_buffers_count != binary2.mrt_buffers_count)
|
binary1.mrt_buffers_count == binary2.mrt_buffers_count;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
|
@ -857,12 +854,68 @@ namespace rsx
|
||||||
{
|
{
|
||||||
if (flags & rsx::vertex_program_dirty)
|
if (flags & rsx::vertex_program_dirty)
|
||||||
{
|
{
|
||||||
cached_vertex_program = nullptr;
|
m_cached_vertex_program = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & rsx::fragment_program_dirty)
|
if (flags & rsx::fragment_program_dirty)
|
||||||
{
|
{
|
||||||
cached_fragment_program = nullptr;
|
m_cached_fragment_program = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void program_cache_hint_t::invalidate_vertex_program(const RSXVertexProgram& p)
|
||||||
|
{
|
||||||
|
if (!m_cached_vertex_program)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vertex_program_compare::compare_properties(m_cached_vp_properties, p))
|
||||||
|
{
|
||||||
|
m_cached_vertex_program = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_cache_hint_t::invalidate_fragment_program(const RSXFragmentProgram& p)
|
||||||
|
{
|
||||||
|
if (!m_cached_fragment_program)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fragment_program_compare::compare_properties(m_cached_fp_properties, p))
|
||||||
|
{
|
||||||
|
m_cached_fragment_program = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_cache_hint_t::cache_vertex_program(program_cache_hint_t* cache, const RSXVertexProgram& ref, void* vertex_program)
|
||||||
|
{
|
||||||
|
if (!cache)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->m_cached_vertex_program = vertex_program;
|
||||||
|
cache->m_cached_vp_properties.output_mask = ref.output_mask;
|
||||||
|
cache->m_cached_vp_properties.ctrl = ref.ctrl;
|
||||||
|
cache->m_cached_vp_properties.texture_state = ref.texture_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_cache_hint_t::cache_fragment_program(program_cache_hint_t* cache, const RSXFragmentProgram& ref, void* fragment_program)
|
||||||
|
{
|
||||||
|
if (!cache)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->m_cached_fragment_program = fragment_program;
|
||||||
|
cache->m_cached_fp_properties.ucode_length = ref.ucode_length;
|
||||||
|
cache->m_cached_fp_properties.ctrl = ref.ctrl;
|
||||||
|
cache->m_cached_fp_properties.texture_state = ref.texture_state;
|
||||||
|
cache->m_cached_fp_properties.texcoord_control_mask = ref.texcoord_control_mask;
|
||||||
|
cache->m_cached_fp_properties.two_sided_lighting = ref.two_sided_lighting;
|
||||||
|
cache->m_cached_fp_properties.mrt_buffers_count = ref.mrt_buffers_count;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ namespace program_hash_util
|
||||||
|
|
||||||
struct vertex_program_compare
|
struct vertex_program_compare
|
||||||
{
|
{
|
||||||
|
static bool compare_properties(const RSXVertexProgram& binary1, const RSXVertexProgram& binary2);
|
||||||
|
|
||||||
bool operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const;
|
bool operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,8 +82,9 @@ namespace program_hash_util
|
||||||
|
|
||||||
struct fragment_program_compare
|
struct fragment_program_compare
|
||||||
{
|
{
|
||||||
|
static bool compare_properties(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2);
|
||||||
|
|
||||||
bool operator()(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2) const;
|
bool operator()(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2) const;
|
||||||
static bool config_only(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,40 +95,46 @@ namespace rsx
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* get_fragment_program() const
|
T* get_fragment_program() const
|
||||||
{
|
{
|
||||||
return utils::bless<T>(cached_fragment_program);
|
return utils::bless<T>(m_cached_fragment_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* get_vertex_program() const
|
T* get_vertex_program() const
|
||||||
{
|
{
|
||||||
return utils::bless<T>(cached_vertex_program);
|
return utils::bless<T>(m_cached_vertex_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_vertex_program() const
|
bool has_vertex_program() const
|
||||||
{
|
{
|
||||||
return cached_vertex_program != nullptr;
|
return m_cached_vertex_program != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_fragment_program() const
|
bool has_fragment_program() const
|
||||||
{
|
{
|
||||||
return cached_fragment_program != nullptr;
|
return m_cached_fragment_program != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invalidate caches if the renderer state shows they are out of date
|
||||||
void invalidate(u32 flags);
|
void invalidate(u32 flags);
|
||||||
|
|
||||||
static inline void cache_vertex_program(program_cache_hint_t* cache, void* vertex_program)
|
// Invalidate vertex program if the cached program is not compatible with the incoming
|
||||||
{
|
void invalidate_vertex_program(const RSXVertexProgram& p);
|
||||||
if (cache) cache->cached_vertex_program = vertex_program;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cache_fragment_program(program_cache_hint_t* cache, void* fragment_program)
|
// Invalidate fragment program if the cached program is not compatible with the incoming
|
||||||
{
|
void invalidate_fragment_program(const RSXFragmentProgram& p);
|
||||||
if (cache) cache->cached_fragment_program = fragment_program;
|
|
||||||
}
|
// Helper - optionally cache the vertex program if possible
|
||||||
|
static void cache_vertex_program(program_cache_hint_t* cache, const RSXVertexProgram& ref, void* vertex_program);
|
||||||
|
|
||||||
|
// Helper - optionally cache the fragment program if possible
|
||||||
|
static void cache_fragment_program(program_cache_hint_t* cache, const RSXFragmentProgram& ref, void* fragment_program);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void* cached_fragment_program = nullptr;
|
void* m_cached_fragment_program = nullptr;
|
||||||
void* cached_vertex_program = nullptr;
|
void* m_cached_vertex_program = nullptr;
|
||||||
|
|
||||||
|
RSXFragmentProgram m_cached_fp_properties;
|
||||||
|
RSXVertexProgram m_cached_vp_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
void write_fragment_constants_to_buffer(const std::span<f32>& buffer, const RSXFragmentProgram& rsx_prog, const std::vector<usz>& offsets_cache, bool sanitize = true);
|
void write_fragment_constants_to_buffer(const std::span<f32>& buffer, const RSXFragmentProgram& rsx_prog, const std::vector<usz>& offsets_cache, bool sanitize = true);
|
||||||
|
@ -228,7 +237,7 @@ protected:
|
||||||
const auto& I = m_vertex_shader_cache.find(rsx_vp);
|
const auto& I = m_vertex_shader_cache.find(rsx_vp);
|
||||||
if (I != m_vertex_shader_cache.end())
|
if (I != m_vertex_shader_cache.end())
|
||||||
{
|
{
|
||||||
rsx::program_cache_hint_t::cache_vertex_program(cache_hint, &(I->second));
|
rsx::program_cache_hint_t::cache_vertex_program(cache_hint, rsx_vp, &(I->second));
|
||||||
return std::forward_as_tuple(I->second, true);
|
return std::forward_as_tuple(I->second, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +254,7 @@ protected:
|
||||||
backend_traits::recompile_vertex_program(rsx_vp, *new_shader, m_next_id++);
|
backend_traits::recompile_vertex_program(rsx_vp, *new_shader, m_next_id++);
|
||||||
}
|
}
|
||||||
|
|
||||||
rsx::program_cache_hint_t::cache_vertex_program(cache_hint, new_shader);
|
rsx::program_cache_hint_t::cache_vertex_program(cache_hint, rsx_vp, new_shader);
|
||||||
return std::forward_as_tuple(*new_shader, false);
|
return std::forward_as_tuple(*new_shader, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +276,7 @@ protected:
|
||||||
const auto& I = m_fragment_shader_cache.find(rsx_fp);
|
const auto& I = m_fragment_shader_cache.find(rsx_fp);
|
||||||
if (I != m_fragment_shader_cache.end())
|
if (I != m_fragment_shader_cache.end())
|
||||||
{
|
{
|
||||||
rsx::program_cache_hint_t::cache_fragment_program(cache_hint, &(I->second));
|
rsx::program_cache_hint_t::cache_fragment_program(cache_hint, rsx_fp, &(I->second));
|
||||||
return std::forward_as_tuple(I->second, true);
|
return std::forward_as_tuple(I->second, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +293,7 @@ protected:
|
||||||
backend_traits::recompile_fragment_program(rsx_fp, *new_shader, m_next_id++);
|
backend_traits::recompile_fragment_program(rsx_fp, *new_shader, m_next_id++);
|
||||||
}
|
}
|
||||||
|
|
||||||
rsx::program_cache_hint_t::cache_fragment_program(cache_hint, new_shader);
|
rsx::program_cache_hint_t::cache_fragment_program(cache_hint, rsx_fp, new_shader);
|
||||||
return std::forward_as_tuple(*new_shader, false);
|
return std::forward_as_tuple(*new_shader, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2034,6 +2034,8 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
current_vertex_program.texture_state.import(current_vp_texture_state, current_vp_metadata.referenced_textures_mask);
|
current_vertex_program.texture_state.import(current_vp_texture_state, current_vp_metadata.referenced_textures_mask);
|
||||||
|
|
||||||
|
m_program_cache_hint.invalidate_vertex_program(current_vertex_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
|
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
|
||||||
|
@ -2275,6 +2277,8 @@ namespace rsx
|
||||||
rsx_log.trace("FS exports depth component but depth test is disabled (INVALID_OPERATION)");
|
rsx_log.trace("FS exports depth component but depth test is disabled (INVALID_OPERATION)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_program_cache_hint.invalidate_fragment_program(current_fragment_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thread::invalidate_fragment_program(u32 dst_dma, u32 dst_offset, u32 size)
|
bool thread::invalidate_fragment_program(u32 dst_dma, u32 dst_offset, u32 size)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue