mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 14:31:24 +12:00
rsx/prog: Use a proper cache hint key instead of disjointed counters
This commit is contained in:
parent
26495a8455
commit
a1c8f3a528
9 changed files with 110 additions and 101 deletions
|
@ -782,8 +782,9 @@ bool GLGSRender::load_program()
|
||||||
{
|
{
|
||||||
void* pipeline_properties = nullptr;
|
void* pipeline_properties = nullptr;
|
||||||
std::tie(m_program, m_vertex_prog, m_fragment_prog) = m_prog_buffer.get_graphics_pipeline(
|
std::tie(m_program, m_vertex_prog, m_fragment_prog) = m_prog_buffer.get_graphics_pipeline(
|
||||||
current_vertex_program, vertex_program_invalidation_count,
|
&m_program_cache_hint,
|
||||||
current_fragment_program, fragment_program_invalidation_count,
|
current_vertex_program,
|
||||||
|
current_fragment_program,
|
||||||
pipeline_properties,
|
pipeline_properties,
|
||||||
shadermode != shader_mode::recompiler, true);
|
shadermode != shader_mode::recompiler, true);
|
||||||
|
|
||||||
|
|
|
@ -135,13 +135,13 @@ struct GLProgramBuffer : public program_state_cache<GLTraits>
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void add_pipeline_entry(const RSXVertexProgram& vp, const RSXFragmentProgram& fp, void* &props, Args&& ...args)
|
void add_pipeline_entry(const RSXVertexProgram& vp, const RSXFragmentProgram& fp, void* &props, Args&& ...args)
|
||||||
{
|
{
|
||||||
get_graphics_pipeline(vp, umax, fp, umax, props, false, false, std::forward<Args>(args)...);
|
get_graphics_pipeline(nullptr, vp, fp, props, false, false, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void preload_programs(const RSXVertexProgram& vp, const RSXFragmentProgram& fp)
|
void preload_programs(rsx::program_cache_hint_t* cache_hint, const RSXVertexProgram& vp, const RSXFragmentProgram& fp)
|
||||||
{
|
{
|
||||||
search_vertex_program(vp, umax);
|
search_vertex_program(cache_hint, vp);
|
||||||
search_fragment_program(fp, umax);
|
search_fragment_program(cache_hint, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_cache_missed() const
|
bool check_cache_missed() const
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "ProgramStateCache.h"
|
#include "ProgramStateCache.h"
|
||||||
#include "Emu/system_config.h"
|
#include "Emu/system_config.h"
|
||||||
|
#include "Emu/RSX/Core/RSXDriverState.h"
|
||||||
#include "util/sysinfo.hpp"
|
#include "util/sysinfo.hpp"
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
@ -851,4 +852,17 @@ namespace rsx
|
||||||
write_fragment_constants_to_buffer_fallback(buffer, rsx_prog, offsets_cache, sanitize);
|
write_fragment_constants_to_buffer_fallback(buffer, rsx_prog, offsets_cache, sanitize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void program_cache_hint_t::invalidate(u32 flags)
|
||||||
|
{
|
||||||
|
if (flags & rsx::vertex_program_dirty)
|
||||||
|
{
|
||||||
|
cached_vertex_program = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & rsx::fragment_program_dirty)
|
||||||
|
{
|
||||||
|
cached_fragment_program = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "util/logs.hpp"
|
#include "util/logs.hpp"
|
||||||
#include "util/fnv_hash.hpp"
|
#include "util/fnv_hash.hpp"
|
||||||
#include "util/v128.hpp"
|
#include "util/v128.hpp"
|
||||||
|
#include <util/bless.hpp>
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -86,6 +87,47 @@ namespace program_hash_util
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
|
struct program_cache_hint_t
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
T* get_fragment_program() const
|
||||||
|
{
|
||||||
|
return utils::bless<T>(cached_fragment_program);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* get_vertex_program() const
|
||||||
|
{
|
||||||
|
return utils::bless<T>(cached_vertex_program);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_vertex_program() const
|
||||||
|
{
|
||||||
|
return cached_vertex_program != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_fragment_program() const
|
||||||
|
{
|
||||||
|
return cached_fragment_program != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate(u32 flags);
|
||||||
|
|
||||||
|
static inline void cache_vertex_program(program_cache_hint_t* cache, void* vertex_program)
|
||||||
|
{
|
||||||
|
if (cache) cache->cached_vertex_program = vertex_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cache_fragment_program(program_cache_hint_t* cache, void* fragment_program)
|
||||||
|
{
|
||||||
|
if (cache) cache->cached_fragment_program = fragment_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void* cached_fragment_program = nullptr;
|
||||||
|
void* cached_vertex_program = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,13 +139,13 @@ namespace rsx
|
||||||
* - a typedef VertexProgramData to a type that encapsulate vertex program info. It should provide an Id member.
|
* - a typedef VertexProgramData to a type that encapsulate vertex program info. It should provide an Id member.
|
||||||
* - a typedef FragmentProgramData to a types that encapsulate fragment program info. It should provide an Id member and a fragment constant offset vector.
|
* - a typedef FragmentProgramData to a types that encapsulate fragment program info. It should provide an Id member and a fragment constant offset vector.
|
||||||
* - a typedef PipelineData encapsulating monolithic program.
|
* - a typedef PipelineData encapsulating monolithic program.
|
||||||
* - a typedef PipelineProperties to a type that encapsulate various state info relevant to program compilation (alpha test, primitive type,...)
|
* - a typedef pipeline_properties to a type that encapsulate various state info relevant to program compilation (alpha test, primitive type,...)
|
||||||
* - a typedef ExtraData type that will be passed to the buildProgram function.
|
* - a typedef ExtraData type that will be passed to the buildProgram function.
|
||||||
* It should also contains the following function member :
|
* It should also contains the following function member :
|
||||||
* - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, usz ID);
|
* - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, usz ID);
|
||||||
* - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, usz ID);
|
* - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, usz ID);
|
||||||
* - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData);
|
* - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const pipeline_properties &pipeline_properties, const ExtraData& extraData);
|
||||||
* - static void validate_pipeline_properties(const VertexProgramData &vertexProgramData, const FragmentProgramData &fragmentProgramData, PipelineProperties& props);
|
* - static void validate_pipeline_properties(const VertexProgramData &vertexProgramData, const FragmentProgramData &fragmentProgramData, pipeline_properties& props);
|
||||||
*/
|
*/
|
||||||
template<typename backend_traits>
|
template<typename backend_traits>
|
||||||
class program_state_cache
|
class program_state_cache
|
||||||
|
@ -168,41 +210,25 @@ protected:
|
||||||
pipeline_storage_type __null_pipeline_handle;
|
pipeline_storage_type __null_pipeline_handle;
|
||||||
|
|
||||||
/// bool here to inform that the program was preexisting.
|
/// bool here to inform that the program was preexisting.
|
||||||
std::tuple<const vertex_program_type&, bool> search_vertex_program(const RSXVertexProgram& rsx_vp, usz rsx_vp_invalidation_count)
|
std::tuple<const vertex_program_type&, bool> search_vertex_program(
|
||||||
|
rsx::program_cache_hint_t* cache_hint,
|
||||||
|
const RSXVertexProgram& rsx_vp)
|
||||||
{
|
{
|
||||||
|
if (cache_hint && cache_hint->has_vertex_program())
|
||||||
|
{
|
||||||
|
// The caller guarantees that the cached vertex program is correct.
|
||||||
|
return std::forward_as_tuple(*cache_hint->get_vertex_program<vertex_program_type>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool recompile = false;
|
bool recompile = false;
|
||||||
vertex_program_type* new_shader;
|
vertex_program_type* new_shader;
|
||||||
{
|
{
|
||||||
thread_local const std::pair<const RSXVertexProgram, vertex_program_type>* prev_vp = nullptr;
|
|
||||||
thread_local usz prev_map_count = umax, prev_rsx_count = umax;
|
|
||||||
static atomic_t<usz> map_invl_count = 0;
|
|
||||||
|
|
||||||
reader_lock lock(m_vertex_mutex);
|
reader_lock lock(m_vertex_mutex);
|
||||||
|
|
||||||
if (prev_map_count == map_invl_count)
|
|
||||||
{
|
|
||||||
// prev_vp must be non-null here
|
|
||||||
if (prev_vp->first.data.size() == rsx_vp.data.size() && prev_vp->first.output_mask == rsx_vp.output_mask)
|
|
||||||
{
|
|
||||||
if (rsx_vp_invalidation_count != umax && prev_rsx_count == rsx_vp_invalidation_count)
|
|
||||||
{
|
|
||||||
return std::forward_as_tuple(prev_vp->second, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (program_hash_util::vertex_program_compare()(prev_vp->first, rsx_vp))
|
|
||||||
{
|
|
||||||
prev_rsx_count = rsx_vp_invalidation_count;
|
|
||||||
return std::forward_as_tuple(prev_vp->second, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
||||||
{
|
{
|
||||||
prev_vp = &*I;
|
rsx::program_cache_hint_t::cache_vertex_program(cache_hint, &(I->second));
|
||||||
prev_map_count = map_invl_count;
|
|
||||||
prev_rsx_count = rsx_vp_invalidation_count;
|
|
||||||
return std::forward_as_tuple(I->second, true);
|
return std::forward_as_tuple(I->second, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,10 +238,6 @@ protected:
|
||||||
auto [it, inserted] = m_vertex_shader_cache.try_emplace(rsx_vp);
|
auto [it, inserted] = m_vertex_shader_cache.try_emplace(rsx_vp);
|
||||||
new_shader = &(it->second);
|
new_shader = &(it->second);
|
||||||
recompile = inserted;
|
recompile = inserted;
|
||||||
prev_map_count = umax;
|
|
||||||
prev_rsx_count = umax;
|
|
||||||
prev_vp = nullptr;
|
|
||||||
map_invl_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recompile)
|
if (recompile)
|
||||||
|
@ -223,51 +245,29 @@ 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);
|
||||||
return std::forward_as_tuple(*new_shader, false);
|
return std::forward_as_tuple(*new_shader, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// bool here to inform that the program was preexisting.
|
/// bool here to inform that the program was preexisting.
|
||||||
std::tuple<const fragment_program_type&, bool> search_fragment_program(const RSXFragmentProgram& rsx_fp, usz rsx_fp_invalidation_count)
|
std::tuple<const fragment_program_type&, bool> search_fragment_program(rsx::program_cache_hint_t* cache_hint, const RSXFragmentProgram& rsx_fp)
|
||||||
{
|
{
|
||||||
|
if (cache_hint && cache_hint->has_fragment_program())
|
||||||
|
{
|
||||||
|
// The caller guarantees that the cached fragemnt program is correct.
|
||||||
|
return std::forward_as_tuple(*cache_hint->get_fragment_program<fragment_program_type>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool recompile = false;
|
bool recompile = false;
|
||||||
typename binary_to_fragment_program::iterator it;
|
typename binary_to_fragment_program::iterator it;
|
||||||
fragment_program_type* new_shader;
|
fragment_program_type* new_shader;
|
||||||
{
|
{
|
||||||
thread_local const std::pair<const RSXFragmentProgram, fragment_program_type>* prev_fp = nullptr;
|
|
||||||
thread_local usz prev_map_count = umax, prev_rsx_count = umax;
|
|
||||||
static atomic_t<usz> map_invl_count = 0;
|
|
||||||
|
|
||||||
reader_lock lock(m_fragment_mutex);
|
reader_lock lock(m_fragment_mutex);
|
||||||
|
|
||||||
if (prev_map_count == map_invl_count)
|
|
||||||
{
|
|
||||||
// prev_vp must be non-null here
|
|
||||||
if (prev_fp->first.ucode_length == rsx_fp.ucode_length && prev_fp->first.texcoord_control_mask == rsx_fp.texcoord_control_mask)
|
|
||||||
{
|
|
||||||
if (rsx_fp_invalidation_count != umax && prev_rsx_count == rsx_fp_invalidation_count)
|
|
||||||
{
|
|
||||||
// Shader UCODE must be the same.
|
|
||||||
// Shader config changes are not tracked at the moment
|
|
||||||
// Compare manually
|
|
||||||
if (program_hash_util::fragment_program_compare::config_only(prev_fp->first, rsx_fp))
|
|
||||||
{
|
|
||||||
return std::forward_as_tuple(prev_fp->second, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (program_hash_util::fragment_program_compare()(prev_fp->first, rsx_fp))
|
|
||||||
{
|
|
||||||
prev_rsx_count = rsx_fp_invalidation_count;
|
|
||||||
return std::forward_as_tuple(prev_fp->second, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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())
|
||||||
{
|
{
|
||||||
prev_fp = &*I;
|
rsx::program_cache_hint_t::cache_fragment_program(cache_hint, &(I->second));
|
||||||
prev_rsx_count = rsx_fp_invalidation_count;
|
|
||||||
prev_map_count = map_invl_count;
|
|
||||||
return std::forward_as_tuple(I->second, true);
|
return std::forward_as_tuple(I->second, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,10 +276,6 @@ protected:
|
||||||
lock.upgrade();
|
lock.upgrade();
|
||||||
std::tie(it, recompile) = m_fragment_shader_cache.try_emplace(rsx_fp);
|
std::tie(it, recompile) = m_fragment_shader_cache.try_emplace(rsx_fp);
|
||||||
new_shader = &(it->second);
|
new_shader = &(it->second);
|
||||||
prev_map_count = umax;
|
|
||||||
prev_rsx_count = umax;
|
|
||||||
prev_fp = nullptr;
|
|
||||||
map_invl_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recompile)
|
if (recompile)
|
||||||
|
@ -288,6 +284,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);
|
||||||
return std::forward_as_tuple(*new_shader, false);
|
return std::forward_as_tuple(*new_shader, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,31 +339,30 @@ public:
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
pipeline_data_type get_graphics_pipeline(
|
pipeline_data_type get_graphics_pipeline(
|
||||||
const RSXVertexProgram& vertexShader,
|
rsx::program_cache_hint_t* cache_hint,
|
||||||
usz vertexShaderInvalidationCount,
|
const RSXVertexProgram& vertex_shader,
|
||||||
const RSXFragmentProgram& fragmentShader,
|
const RSXFragmentProgram& fragment_shader,
|
||||||
usz fragmentShaderInvalidationCount,
|
pipeline_properties& pipeline_properties,
|
||||||
pipeline_properties& pipelineProperties,
|
|
||||||
bool compile_async,
|
bool compile_async,
|
||||||
bool allow_notification,
|
bool allow_notification,
|
||||||
Args&& ...args
|
Args&& ...args
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const auto& vp_search = search_vertex_program(vertexShader, vertexShaderInvalidationCount);
|
const auto& vp_search = search_vertex_program(cache_hint, vertex_shader);
|
||||||
const auto& fp_search = search_fragment_program(fragmentShader, fragmentShaderInvalidationCount);
|
const auto& fp_search = search_fragment_program(cache_hint, fragment_shader);
|
||||||
|
|
||||||
const bool already_existing_fragment_program = std::get<1>(fp_search);
|
const bool already_existing_fragment_program = std::get<1>(fp_search);
|
||||||
const bool already_existing_vertex_program = std::get<1>(vp_search);
|
const bool already_existing_vertex_program = std::get<1>(vp_search);
|
||||||
const vertex_program_type& vertex_program = std::get<0>(vp_search);
|
const vertex_program_type& vertex_program = std::get<0>(vp_search);
|
||||||
const fragment_program_type& fragment_program = std::get<0>(fp_search);
|
const fragment_program_type& fragment_program = std::get<0>(fp_search);
|
||||||
const pipeline_key key = { vertex_program.id, fragment_program.id, pipelineProperties };
|
const pipeline_key key = { vertex_program.id, fragment_program.id, pipeline_properties };
|
||||||
|
|
||||||
m_cache_miss_flag = true;
|
m_cache_miss_flag = true;
|
||||||
|
|
||||||
if (already_existing_vertex_program && already_existing_fragment_program)
|
if (already_existing_vertex_program && already_existing_fragment_program)
|
||||||
{
|
{
|
||||||
// There is a high chance the pipeline object was compiled if the two shaders already existed before
|
// There is a high chance the pipeline object was compiled if the two shaders already existed before
|
||||||
backend_traits::validate_pipeline_properties(vertex_program, fragment_program, pipelineProperties);
|
backend_traits::validate_pipeline_properties(vertex_program, fragment_program, pipeline_properties);
|
||||||
|
|
||||||
reader_lock lock(m_pipeline_mutex);
|
reader_lock lock(m_pipeline_mutex);
|
||||||
if (const auto I = m_storage.find(key); I != m_storage.end())
|
if (const auto I = m_storage.find(key); I != m_storage.end())
|
||||||
|
@ -396,7 +392,7 @@ public:
|
||||||
|
|
||||||
if (allow_notification)
|
if (allow_notification)
|
||||||
{
|
{
|
||||||
callback = [this, vertexShader, fragmentShader_ = RSXFragmentProgram::clone(fragmentShader), key]
|
callback = [this, vertex_shader, fragment_shader_ = RSXFragmentProgram::clone(fragment_shader), key]
|
||||||
(pipeline_storage_type& pipeline) -> pipeline_type*
|
(pipeline_storage_type& pipeline) -> pipeline_type*
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
|
@ -405,7 +401,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
rsx_log.success("Program compiled successfully");
|
rsx_log.success("Program compiled successfully");
|
||||||
notify_pipeline_compiled(key.properties, vertexShader, fragmentShader_);
|
notify_pipeline_compiled(key.properties, vertex_shader, fragment_shader_);
|
||||||
|
|
||||||
std::lock_guard lock(m_pipeline_mutex);
|
std::lock_guard lock(m_pipeline_mutex);
|
||||||
auto& pipe_result = m_storage[key];
|
auto& pipe_result = m_storage[key];
|
||||||
|
@ -432,7 +428,7 @@ public:
|
||||||
auto result = backend_traits::build_pipeline(
|
auto result = backend_traits::build_pipeline(
|
||||||
vertex_program, // VS, must already be decompiled and recompiled above
|
vertex_program, // VS, must already be decompiled and recompiled above
|
||||||
fragment_program, // FS, must already be decompiled and recompiled above
|
fragment_program, // FS, must already be decompiled and recompiled above
|
||||||
pipelineProperties, // Pipeline state
|
pipeline_properties, // Pipeline state
|
||||||
compile_async, // Allow asynchronous compilation
|
compile_async, // Allow asynchronous compilation
|
||||||
callback, // Insertion and notification callback
|
callback, // Insertion and notification callback
|
||||||
std::forward<Args>(args)...); // Other arguments
|
std::forward<Args>(args)...); // Other arguments
|
||||||
|
|
|
@ -1904,7 +1904,6 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphics_state.clear(rsx::pipeline_state::fragment_program_ucode_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::fragment_program_ucode_dirty);
|
||||||
fragment_program_invalidation_count++;
|
|
||||||
|
|
||||||
// Request for update of fragment constants if the program block is invalidated
|
// Request for update of fragment constants if the program block is invalidated
|
||||||
m_graphics_state |= rsx::pipeline_state::fragment_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::fragment_constants_dirty;
|
||||||
|
@ -1954,7 +1953,6 @@ namespace rsx
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphics_state.clear(rsx::pipeline_state::vertex_program_ucode_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::vertex_program_ucode_dirty);
|
||||||
vertex_program_invalidation_count++;
|
|
||||||
|
|
||||||
// Reload transform constants unconditionally for now
|
// Reload transform constants unconditionally for now
|
||||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||||
|
@ -1990,6 +1988,8 @@ namespace rsx
|
||||||
|
|
||||||
void thread::analyse_current_rsx_pipeline()
|
void thread::analyse_current_rsx_pipeline()
|
||||||
{
|
{
|
||||||
|
m_program_cache_hint.invalidate(m_graphics_state.load());
|
||||||
|
|
||||||
prefetch_vertex_program();
|
prefetch_vertex_program();
|
||||||
prefetch_fragment_program();
|
prefetch_fragment_program();
|
||||||
}
|
}
|
||||||
|
@ -2012,7 +2012,6 @@ namespace rsx
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex_program_invalidation_count++;
|
|
||||||
ensure(!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty));
|
ensure(!m_graphics_state.test(rsx::pipeline_state::vertex_program_ucode_dirty));
|
||||||
current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask();
|
current_vertex_program.output_mask = rsx::method_registers.vertex_attrib_output_mask();
|
||||||
|
|
||||||
|
@ -2048,9 +2047,6 @@ namespace rsx
|
||||||
|
|
||||||
m_graphics_state.clear(rsx::pipeline_state::fragment_program_dirty);
|
m_graphics_state.clear(rsx::pipeline_state::fragment_program_dirty);
|
||||||
|
|
||||||
// FP config is always checked for now (see get_graphics_pipeline)
|
|
||||||
//fragment_program_invalidation_count++;
|
|
||||||
|
|
||||||
current_fragment_program.ctrl = m_ctx->register_state->shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
|
current_fragment_program.ctrl = m_ctx->register_state->shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
|
||||||
current_fragment_program.texcoord_control_mask = m_ctx->register_state->texcoord_control_mask();
|
current_fragment_program.texcoord_control_mask = m_ctx->register_state->texcoord_control_mask();
|
||||||
current_fragment_program.two_sided_lighting = m_ctx->register_state->two_side_light_en();
|
current_fragment_program.two_sided_lighting = m_ctx->register_state->two_side_light_en();
|
||||||
|
|
|
@ -242,8 +242,7 @@ namespace rsx
|
||||||
|
|
||||||
rsx::atomic_bitmask_t<rsx::eng_interrupt_reason> m_eng_interrupt_mask;
|
rsx::atomic_bitmask_t<rsx::eng_interrupt_reason> m_eng_interrupt_mask;
|
||||||
rsx::bitmask_t<rsx::pipeline_state> m_graphics_state;
|
rsx::bitmask_t<rsx::pipeline_state> m_graphics_state;
|
||||||
u64 fragment_program_invalidation_count = umax;
|
|
||||||
u64 vertex_program_invalidation_count = umax;
|
|
||||||
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::fragment_program_utils::fragment_program_metadata current_fp_metadata = {};
|
||||||
|
@ -262,6 +261,8 @@ namespace rsx
|
||||||
vertex_program_texture_state current_vp_texture_state = {};
|
vertex_program_texture_state current_vp_texture_state = {};
|
||||||
fragment_program_texture_state current_fp_texture_state = {};
|
fragment_program_texture_state current_fp_texture_state = {};
|
||||||
|
|
||||||
|
program_cache_hint_t m_program_cache_hint;
|
||||||
|
|
||||||
// Runs shader prefetch and resolves pipeline status flags
|
// Runs shader prefetch and resolves pipeline status flags
|
||||||
void analyse_current_rsx_pipeline();
|
void analyse_current_rsx_pipeline();
|
||||||
|
|
||||||
|
|
|
@ -1961,8 +1961,9 @@ bool VKGSRender::load_program()
|
||||||
|
|
||||||
// Load current program from cache
|
// Load current program from cache
|
||||||
std::tie(m_program, m_vertex_prog, m_fragment_prog) = m_prog_buffer->get_graphics_pipeline(
|
std::tie(m_program, m_vertex_prog, m_fragment_prog) = m_prog_buffer->get_graphics_pipeline(
|
||||||
vertex_program, vertex_program_invalidation_count,
|
&m_program_cache_hint,
|
||||||
fragment_program, fragment_program_invalidation_count,
|
vertex_program,
|
||||||
|
fragment_program,
|
||||||
m_pipeline_properties,
|
m_pipeline_properties,
|
||||||
shadermode != shader_mode::recompiler, true, m_pipeline_layout);
|
shadermode != shader_mode::recompiler, true, m_pipeline_layout);
|
||||||
|
|
||||||
|
|
|
@ -88,13 +88,13 @@ namespace vk
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void add_pipeline_entry(RSXVertexProgram& vp, RSXFragmentProgram& fp, vk::pipeline_props& props, Args&& ...args)
|
void add_pipeline_entry(RSXVertexProgram& vp, RSXFragmentProgram& fp, vk::pipeline_props& props, Args&& ...args)
|
||||||
{
|
{
|
||||||
get_graphics_pipeline(vp, umax, fp, umax, props, false, false, std::forward<Args>(args)...);
|
get_graphics_pipeline(nullptr, vp, fp, props, false, false, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void preload_programs(const RSXVertexProgram& vp, const RSXFragmentProgram& fp)
|
void preload_programs(rsx::program_cache_hint_t* cache_hint, const RSXVertexProgram& vp, const RSXFragmentProgram& fp)
|
||||||
{
|
{
|
||||||
search_vertex_program(vp, umax);
|
search_vertex_program(cache_hint, vp);
|
||||||
search_fragment_program(fp, umax);
|
search_fragment_program(cache_hint, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_cache_missed() const
|
bool check_cache_missed() const
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace rsx
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_storage.preload_programs(std::get<1>(entry), std::get<2>(entry));
|
m_storage.preload_programs(nullptr, std::get<1>(entry), std::get<2>(entry));
|
||||||
|
|
||||||
unpacked[unpacked.push_begin()] = std::move(entry);
|
unpacked[unpacked.push_begin()] = std::move(entry);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue