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
parent bf234dc668
commit 49f4da3016
5 changed files with 40 additions and 24 deletions

View file

@ -273,13 +273,14 @@ namespace rsx
if (trampled_set.size() > 0)
{
// 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)
{
if (!is_writing && obj.first->get_protection() != utils::protection::no)
return true;
if (!rebuild_cache && !obj.first->is_flushable())
if (!obj.first->is_flushable())
return false;
const std::pair<u32, u32> null_check = std::make_pair(UINT32_MAX, 0);
@ -309,6 +310,20 @@ namespace rsx
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++)
{
auto obj = *It;
@ -319,26 +334,9 @@ namespace rsx
obj.first->set_dirty(false);
}
if (discard_only)
if (discard_only || allow_flush)
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);
}
@ -348,7 +346,7 @@ namespace rsx
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)
{
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
@ -930,7 +928,8 @@ namespace rsx
auto subresources_layout = get_subresources_layout(tex);
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);
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()
{
if (flushed) return true; //Already written, ignore
if (!copied)
{
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();
flushed = true;

View file

@ -567,6 +567,7 @@ VKGSRender::VKGSRender() : GSRender()
//Create secondary command_buffer for parallel operations
m_secondary_command_buffer_pool.create((*m_device));
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
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;
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:
command_buffer() {}
~command_buffer() {}

View file

@ -20,6 +20,7 @@ namespace vk
//DMA relevant data
VkFence dma_fence = VK_NULL_HANDLE;
bool synchronized = false;
bool flushed = false;
u64 sync_timestamp = 0;
u64 last_use_timestamp = 0;
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
//The create method is only invoked when a new mangaged session is required
synchronized = false;
flushed = false;
sync_timestamp = 0ull;
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(vkResetCommandBuffer(cmd, 0));
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
if (cmd.access_hint != vk::command_buffer::access_type_hint::all)
cmd.begin();
}
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)
{
if (flushed) return true;
if (m_device == nullptr)
m_device = &dev;
@ -217,7 +224,7 @@ namespace vk
result = false;
}
protect(utils::protection::rw);
flushed = true;
void* pixels_src = dma_buffer->map(0, cpu_address_range);
void* pixels_dst = vm::base(cpu_address_base);