Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: Improve object reuse and lifetime management #6155

Merged
merged 6 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions rpcs3/Emu/RSX/Common/TextureUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,3 +796,17 @@ size_t get_texture_size(const rsx::vertex_texture &texture)
return get_texture_size(texture.format(), texture.width(), texture.height(), texture.depth(),
texture.pitch(), texture.get_exact_mipmap_count(), texture.cubemap() ? 6 : 1);
}

u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap)
{
u32 encode = 0;
encode |= (remap.first[0] << 0);
encode |= (remap.first[1] << 2);
encode |= (remap.first[2] << 4);
encode |= (remap.first[3] << 6);
encode |= (remap.second[0] << 8);
encode |= (remap.second[1] << 10);
encode |= (remap.second[2] << 12);
encode |= (remap.second[3] << 14);
return encode;
}
5 changes: 5 additions & 0 deletions rpcs3/Emu/RSX/Common/TextureUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,8 @@ size_t get_texture_size(const rsx::vertex_texture &texture);
* Get packed pitch
*/
u32 get_format_packed_pitch(u32 format, u16 width);

/**
* Reverse encoding
*/
u32 get_remap_encoding(const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap);
17 changes: 16 additions & 1 deletion rpcs3/Emu/RSX/Common/texture_cache_utils.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include "../rsx_cache.h"
#include "texture_cache_predictor.h"
Expand Down Expand Up @@ -1114,6 +1114,9 @@ namespace rsx
invalidate_range();
}

virtual void dma_abort()
{}

public:
/**
* Dirty/Unreleased Flag
Expand Down Expand Up @@ -1276,6 +1279,12 @@ namespace rsx

void reprotect(const utils::protection prot)
{
if (synchronized && !flushed)
{
// Abort enqueued transfer
dma_abort();
}

//Reset properties and protect again
flushed = false;
synchronized = false;
Expand All @@ -1286,6 +1295,12 @@ namespace rsx

void reprotect(const utils::protection prot, const std::pair<u32, u32>& range)
{
if (synchronized && !flushed)
{
// Abort enqueued transfer
dma_abort();
}

//Reset properties and protect again
flushed = false;
synchronized = false;
Expand Down
24 changes: 21 additions & 3 deletions rpcs3/Emu/RSX/VK/VKGSRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "VKFormats.h"
#include "VKCommonDecompiler.h"
#include "VKRenderPass.h"
#include "VKResourceManager.h"

namespace
{
Expand Down Expand Up @@ -640,7 +641,6 @@ VKGSRender::~VKGSRender()
m_rtts.destroy();
m_texture_cache.destroy();

m_resource_manager.destroy();
m_stencil_mirror_sampler.reset();

//Overlay text handler
Expand Down Expand Up @@ -1372,7 +1372,7 @@ void VKGSRender::end()

if (replace)
{
fs_sampler_handles[i] = m_resource_manager.find_sampler(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
fs_sampler_handles[i] = vk::get_resource_manager()->find_sampler(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode);
}
}
Expand Down Expand Up @@ -1422,7 +1422,7 @@ void VKGSRender::end()

if (replace)
{
vs_sampler_handles[i] = m_resource_manager.find_sampler(
vs_sampler_handles[i] = vk::get_resource_manager()->find_sampler(
*m_device,
VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
unnormalized_coords,
Expand Down Expand Up @@ -2159,6 +2159,11 @@ void VKGSRender::flush_command_queue(bool hard_sync)
m_current_cb_index = (m_current_cb_index + 1) % VK_MAX_ASYNC_CB_COUNT;
m_current_command_buffer = &m_primary_cb_list[m_current_cb_index];

if (!m_current_command_buffer->poke())
{
LOG_ERROR(RSX, "CB chain has run out of free entries!");
}

m_current_command_buffer->reset();

// Just in case a queued frame holds a ref to this cb, drain the present queue
Expand Down Expand Up @@ -2823,6 +2828,7 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
{
auto open_query = m_occlusion_map[m_active_query_info->driver_handle].indices.back();
m_occlusion_query_pool.end_query(*m_current_command_buffer, open_query);
m_current_command_buffer->flags &= ~vk::command_buffer::cb_has_open_query;
}

m_current_command_buffer->end();
Expand Down Expand Up @@ -3601,6 +3607,18 @@ void VKGSRender::discard_occlusion_query(rsx::reports::occlusion_query_info* que
data.indices.clear();
}

void VKGSRender::emergency_query_cleanup(vk::command_buffer* commands)
{
verify("Command list mismatch" HERE), commands == static_cast<vk::command_buffer*>(m_current_command_buffer);

if (m_current_command_buffer->flags & vk::command_buffer::cb_has_open_query)
{
auto open_query = m_occlusion_map[m_active_query_info->driver_handle].indices.back();
m_occlusion_query_pool.end_query(*m_current_command_buffer, open_query);
m_current_command_buffer->flags &= ~vk::command_buffer::cb_has_open_query;
}
}

bool VKGSRender::on_decompiler_task()
{
return m_prog_buffer->async_update(8, *m_device, pipeline_layout).first;
Expand Down
79 changes: 12 additions & 67 deletions rpcs3/Emu/RSX/VK/VKGSRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ struct command_buffer_chunk: public vk::command_buffer
VkDevice m_device = VK_NULL_HANDLE;

std::atomic_bool pending = { false };
std::atomic<u64> last_sync = { 0 };
u64 eid_tag = 0;
shared_mutex guard_mutex;

command_buffer_chunk() = default;
Expand All @@ -96,7 +96,7 @@ struct command_buffer_chunk: public vk::command_buffer

void tag()
{
last_sync = get_system_time();
eid_tag = vk::get_event_id();
}

void reset()
Expand All @@ -123,8 +123,11 @@ struct command_buffer_chunk: public vk::command_buffer

if (pending)
{
pending = false;
vk::reset_fence(&submit_fence);
vk::on_event_completed(eid_tag);

pending = false;
eid_tag = 0;
}
}

Expand All @@ -145,7 +148,10 @@ struct command_buffer_chunk: public vk::command_buffer
if (pending)
{
vk::reset_fence(&submit_fence);
vk::on_event_completed(eid_tag);

pending = false;
eid_tag = 0;
}

return ret;
Expand Down Expand Up @@ -288,66 +294,6 @@ struct flush_request_task
}
};

// TODO: This class will be expanded into a global allocator/collector eventually
class resource_manager
{
private:
std::unordered_multimap<u64, std::unique_ptr<vk::sampler>> m_sampler_pool;

bool value_compare(const f32& a, const f32& b)
{
return fabsf(a - b) < 0.0000001f;
}

public:

resource_manager() = default;
~resource_manager() = default;

void destroy()
{
m_sampler_pool.clear();
}

vk::sampler* find_sampler(VkDevice dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
VkBool32 depth_compare = VK_FALSE, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
{
u64 key = u16(clamp_u) | u64(clamp_v) << 3 | u64(clamp_w) << 6;
key |= u64(unnormalized_coordinates) << 9; // 1 bit
key |= u64(min_filter) << 10 | u64(mag_filter) << 11; // 1 bit each
key |= u64(mipmap_mode) << 12; // 1 bit
key |= u64(border_color) << 13; // 3 bits
key |= u64(depth_compare) << 16; // 1 bit
key |= u64(depth_compare_mode) << 17; // 3 bits

const auto found = m_sampler_pool.equal_range(key);
for (auto It = found.first; It != found.second; ++It)
{
const auto& info = It->second->info;
if (!value_compare(info.mipLodBias, mipLodBias) ||
!value_compare(info.maxAnisotropy, max_anisotropy) ||
!value_compare(info.minLod, min_lod) ||
!value_compare(info.maxLod, max_lod))
{
continue;
}

return It->second.get();
}

auto result = std::make_unique<vk::sampler>(
dev, clamp_u, clamp_v, clamp_w, unnormalized_coordinates,
mipLodBias, max_anisotropy, min_lod, max_lod,
min_filter, mag_filter, mipmap_mode, border_color,
depth_compare, depth_compare_mode);

auto It = m_sampler_pool.emplace(key, std::move(result));
return It->second.get();
}
};

class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
{
private:
Expand Down Expand Up @@ -379,8 +325,6 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
std::unique_ptr<vk::buffer_view> m_volatile_attribute_storage;
std::unique_ptr<vk::buffer_view> m_vertex_layout_storage;

resource_manager m_resource_manager;

public:
//vk::fbo draw_fbo;
std::unique_ptr<vk::vertex_cache> m_vertex_cache;
Expand Down Expand Up @@ -459,8 +403,6 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
shared_mutex m_flush_queue_mutex;
flush_request_task m_flush_requests;

std::atomic<u64> m_last_sync_event = { 0 };

bool m_render_pass_open = false;
u64 m_current_renderpass_key = 0;
VkRenderPass m_cached_renderpass = VK_NULL_HANDLE;
Expand Down Expand Up @@ -529,6 +471,9 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
void get_occlusion_query_result(rsx::reports::occlusion_query_info* query) override;
void discard_occlusion_query(rsx::reports::occlusion_query_info* query) override;

// External callback in case we need to suddenly submit a commandlist unexpectedly, e.g in a violation handler
void emergency_query_cleanup(vk::command_buffer* commands);

protected:
void begin() override;
void end() override;
Expand Down
11 changes: 11 additions & 0 deletions rpcs3/Emu/RSX/VK/VKHelpers.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "stdafx.h"
#include "VKHelpers.h"
#include "VKGSRender.h"
#include "VKCompute.h"
#include "VKRenderPass.h"
#include "VKFramebuffer.h"
#include "VKResolveHelper.h"
#include "VKResourceManager.h"
#include "Utilities/mutex.h"

namespace vk
Expand Down Expand Up @@ -247,6 +249,7 @@ namespace vk
vk::clear_renderpass_cache(dev);
vk::clear_framebuffer_cache();
vk::clear_resolve_helpers();
vk::get_resource_manager()->destroy();

g_null_texture.reset();
g_null_image_view.reset();
Expand Down Expand Up @@ -769,6 +772,14 @@ namespace vk
}
}

void do_query_cleanup(vk::command_buffer& cmd)
{
auto renderer = dynamic_cast<VKGSRender*>(rsx::get_current_renderer());
verify(HERE), renderer;

renderer->emergency_query_cleanup(&cmd);
}

void die_with_error(const char* faulting_addr, VkResult error_code)
{
std::string error_message;
Expand Down
25 changes: 20 additions & 5 deletions rpcs3/Emu/RSX/VK/VKHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ namespace vk
VkResult wait_for_fence(VkFence pFence, u64 timeout = 0ull);
VkResult wait_for_event(VkEvent pEvent, u64 timeout = 0ull);

// Handle unexpected submit with dangling occlusion query
// TODO: Move queries out of the renderer!
void do_query_cleanup(vk::command_buffer& cmd);

void die_with_error(const char* faulting_addr, VkResult error_code);

struct memory_type_mapping
Expand Down Expand Up @@ -1008,6 +1012,9 @@ namespace vk
return;
}

// Check for hanging queries to avoid driver hang
verify("close and submit of commandbuffer with a hanging query!" HERE), (flags & cb_has_open_query) == 0;

if (!fence)
{
fence = m_submit_fence;
Expand Down Expand Up @@ -1291,11 +1298,19 @@ namespace vk
}
}

VkComponentMapping real_mapping = vk::apply_swizzle_remap
(
{native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b },
remap
);
VkComponentMapping real_mapping;
if (remap_encoding == 0xAAE4)
{
real_mapping = native_component_map;
}
else
{
real_mapping = vk::apply_swizzle_remap
(
{ native_component_map.a, native_component_map.r, native_component_map.g, native_component_map.b },
remap
);
}

const auto range = vk::get_image_subresource_range(0, 0, info.arrayLayers, info.mipLevels, aspect() & mask);

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/VK/VKOverlays.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ namespace vk
return fs_inputs;
}

virtual void get_dynamic_state_entries(VkDynamicState* state_descriptors, VkPipelineDynamicStateCreateInfo& info)
virtual void get_dynamic_state_entries(VkDynamicState* /*state_descriptors*/, VkPipelineDynamicStateCreateInfo& /*info*/)
{}

virtual std::vector<VkPushConstantRange> get_push_constants()
Expand Down
29 changes: 29 additions & 0 deletions rpcs3/Emu/RSX/VK/VKResourceManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "stdafx.h"
#include "VKResourceManager.h"

namespace vk
{
resource_manager g_resource_manager;
atomic_t<u64> g_event_ctr;

resource_manager* get_resource_manager()
{
return &g_resource_manager;
}

u64 get_event_id()
{
return g_event_ctr++;
}

u64 current_event_id()
{
return g_event_ctr.load();
}

void on_event_completed(u64 event_id)
{
// TODO: Offload this to a secondary thread
g_resource_manager.eid_completed(event_id);
}
}