mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-08-09 17:49:45 +00:00
rsx: Fixes
- vk: Always reopen primary command buffers. They should only be closed in flush_command_queue - If uploading a texture and there are collisions with protected buffers, do not rebuild the cache - Perform writes via flush before reprotecting pages that were not trampled - Only flush no pages once
This commit is contained in:
parent
bf234dc668
commit
49f4da3016
5 changed files with 40 additions and 24 deletions
|
@ -273,13 +273,14 @@ namespace rsx
|
||||||
if (trampled_set.size() > 0)
|
if (trampled_set.size() > 0)
|
||||||
{
|
{
|
||||||
// Rebuild the cache by only destroying ranges that need to be destroyed to unlock this page
|
// Rebuild the cache by only destroying ranges that need to be destroyed to unlock this page
|
||||||
const auto to_reprotect = std::remove_if(trampled_set.begin(), trampled_set.end(),
|
const auto to_reprotect = !rebuild_cache? trampled_set.end() :
|
||||||
|
std::remove_if(trampled_set.begin(), trampled_set.end(),
|
||||||
[&](const std::pair<section_storage_type*, ranged_storage*>& obj)
|
[&](const std::pair<section_storage_type*, ranged_storage*>& obj)
|
||||||
{
|
{
|
||||||
if (!is_writing && obj.first->get_protection() != utils::protection::no)
|
if (!is_writing && obj.first->get_protection() != utils::protection::no)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!rebuild_cache && !obj.first->is_flushable())
|
if (!obj.first->is_flushable())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const std::pair<u32, u32> null_check = std::make_pair(UINT32_MAX, 0);
|
const std::pair<u32, u32> null_check = std::make_pair(UINT32_MAX, 0);
|
||||||
|
@ -309,6 +310,20 @@ namespace rsx
|
||||||
obj.second->remove_one();
|
obj.second->remove_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allow_flush)
|
||||||
|
{
|
||||||
|
// Flush here before 'reprotecting' since flushing will write the whole span
|
||||||
|
for (const auto &tex : sections_to_flush)
|
||||||
|
{
|
||||||
|
if (!tex->flush(std::forward<Args>(extras)...))
|
||||||
|
{
|
||||||
|
//Missed address, note this
|
||||||
|
//TODO: Lower severity when successful to keep the cache from overworking
|
||||||
|
record_cache_miss(*tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto It = to_reprotect; It != trampled_set.end(); It++)
|
for (auto It = to_reprotect; It != trampled_set.end(); It++)
|
||||||
{
|
{
|
||||||
auto obj = *It;
|
auto obj = *It;
|
||||||
|
@ -319,26 +334,9 @@ namespace rsx
|
||||||
obj.first->set_dirty(false);
|
obj.first->set_dirty(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discard_only)
|
if (discard_only || allow_flush)
|
||||||
return{ true, {} };
|
return{ true, {} };
|
||||||
|
|
||||||
//trampled_set.erase(to_reprotect, trampled_set.end());
|
|
||||||
|
|
||||||
if (allow_flush)
|
|
||||||
{
|
|
||||||
for (const auto &tex : sections_to_flush)
|
|
||||||
{
|
|
||||||
if (!tex->flush(std::forward<Args>(extras)...))
|
|
||||||
{
|
|
||||||
//Missed address, note this
|
|
||||||
//TODO: Lower severity when successful to keep the cache from overworking
|
|
||||||
record_cache_miss(*tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return{ true, {} };
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_pair(true, sections_to_flush);
|
return std::make_pair(true, sections_to_flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +346,7 @@ namespace rsx
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
|
std::pair<bool, std::vector<section_storage_type*>> invalidate_range_impl(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
|
||||||
{
|
{
|
||||||
return invalidate_range_impl_base(address, range, is_writing, discard, false, allow_flush, std::forward<Args>(extras)...);
|
return invalidate_range_impl_base(address, range, is_writing, discard, true, allow_flush, std::forward<Args>(extras)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_hw_blit_engine_compatible(const u32 format) const
|
bool is_hw_blit_engine_compatible(const u32 format) const
|
||||||
|
@ -930,7 +928,8 @@ namespace rsx
|
||||||
auto subresources_layout = get_subresources_layout(tex);
|
auto subresources_layout = get_subresources_layout(tex);
|
||||||
auto remap_vector = tex.decoded_remap();
|
auto remap_vector = tex.decoded_remap();
|
||||||
|
|
||||||
invalidate_range_impl(texaddr, tex_size, false, false, true, std::forward<Args>(extras)...);
|
//Invalidate with writing=false, discard=false, rebuild=false, native_flush=true
|
||||||
|
invalidate_range_impl_base(texaddr, tex_size, false, false, false, true, std::forward<Args>(extras)...);
|
||||||
|
|
||||||
m_texture_memory_in_use += (tex_pitch * tex_height);
|
m_texture_memory_in_use += (tex_pitch * tex_height);
|
||||||
return upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
|
return upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
|
||||||
|
|
|
@ -386,6 +386,8 @@ namespace gl
|
||||||
|
|
||||||
bool flush()
|
bool flush()
|
||||||
{
|
{
|
||||||
|
if (flushed) return true; //Already written, ignore
|
||||||
|
|
||||||
if (!copied)
|
if (!copied)
|
||||||
{
|
{
|
||||||
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
|
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
|
||||||
|
@ -399,7 +401,6 @@ namespace gl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protect(utils::protection::rw);
|
|
||||||
m_fence.wait_for_signal();
|
m_fence.wait_for_signal();
|
||||||
flushed = true;
|
flushed = true;
|
||||||
|
|
||||||
|
|
|
@ -567,6 +567,7 @@ VKGSRender::VKGSRender() : GSRender()
|
||||||
//Create secondary command_buffer for parallel operations
|
//Create secondary command_buffer for parallel operations
|
||||||
m_secondary_command_buffer_pool.create((*m_device));
|
m_secondary_command_buffer_pool.create((*m_device));
|
||||||
m_secondary_command_buffer.create(m_secondary_command_buffer_pool);
|
m_secondary_command_buffer.create(m_secondary_command_buffer_pool);
|
||||||
|
m_secondary_command_buffer.access_hint = vk::command_buffer::access_type_hint::all;
|
||||||
|
|
||||||
//Precalculated stuff
|
//Precalculated stuff
|
||||||
m_render_passes = get_precomputed_render_passes(*m_device, m_optimal_tiling_supported_formats);
|
m_render_passes = get_precomputed_render_passes(*m_device, m_optimal_tiling_supported_formats);
|
||||||
|
|
|
@ -1013,6 +1013,14 @@ namespace vk
|
||||||
vk::command_pool *pool = nullptr;
|
vk::command_pool *pool = nullptr;
|
||||||
VkCommandBuffer commands = nullptr;
|
VkCommandBuffer commands = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum access_type_hint
|
||||||
|
{
|
||||||
|
flush_only, //Only to be submitted/opened/closed via command flush
|
||||||
|
all //Auxilliary, can be sumitted/opened/closed at any time
|
||||||
|
}
|
||||||
|
access_hint = flush_only;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
command_buffer() {}
|
command_buffer() {}
|
||||||
~command_buffer() {}
|
~command_buffer() {}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace vk
|
||||||
//DMA relevant data
|
//DMA relevant data
|
||||||
VkFence dma_fence = VK_NULL_HANDLE;
|
VkFence dma_fence = VK_NULL_HANDLE;
|
||||||
bool synchronized = false;
|
bool synchronized = false;
|
||||||
|
bool flushed = false;
|
||||||
u64 sync_timestamp = 0;
|
u64 sync_timestamp = 0;
|
||||||
u64 last_use_timestamp = 0;
|
u64 last_use_timestamp = 0;
|
||||||
vk::render_device* m_device = nullptr;
|
vk::render_device* m_device = nullptr;
|
||||||
|
@ -62,6 +63,7 @@ namespace vk
|
||||||
//Even if we are managing the same vram section, we cannot guarantee contents are static
|
//Even if we are managing the same vram section, we cannot guarantee contents are static
|
||||||
//The create method is only invoked when a new mangaged session is required
|
//The create method is only invoked when a new mangaged session is required
|
||||||
synchronized = false;
|
synchronized = false;
|
||||||
|
flushed = false;
|
||||||
sync_timestamp = 0ull;
|
sync_timestamp = 0ull;
|
||||||
last_use_timestamp = get_system_time();
|
last_use_timestamp = get_system_time();
|
||||||
}
|
}
|
||||||
|
@ -179,6 +181,9 @@ namespace vk
|
||||||
CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX));
|
CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX));
|
||||||
CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
|
CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
|
||||||
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
|
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
|
||||||
|
|
||||||
|
if (cmd.access_hint != vk::command_buffer::access_type_hint::all)
|
||||||
|
cmd.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized = true;
|
synchronized = true;
|
||||||
|
@ -204,6 +209,8 @@ namespace vk
|
||||||
|
|
||||||
bool flush(vk::render_device& dev, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue)
|
bool flush(vk::render_device& dev, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue)
|
||||||
{
|
{
|
||||||
|
if (flushed) return true;
|
||||||
|
|
||||||
if (m_device == nullptr)
|
if (m_device == nullptr)
|
||||||
m_device = &dev;
|
m_device = &dev;
|
||||||
|
|
||||||
|
@ -217,7 +224,7 @@ namespace vk
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protect(utils::protection::rw);
|
flushed = true;
|
||||||
|
|
||||||
void* pixels_src = dma_buffer->map(0, cpu_address_range);
|
void* pixels_src = dma_buffer->map(0, cpu_address_range);
|
||||||
void* pixels_dst = vm::base(cpu_address_base);
|
void* pixels_dst = vm::base(cpu_address_base);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue