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:
kd-11 2017-10-27 16:52:27 +03:00
commit 49f4da3016
5 changed files with 40 additions and 24 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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() {}

View file

@ -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);