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

vk: Resource management improvements #5988

Merged
merged 4 commits into from May 19, 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
3 changes: 2 additions & 1 deletion rpcs3/Emu/RSX/RSXThread.h
Expand Up @@ -208,7 +208,7 @@ namespace rsx
}

const u32 max_index = (first + count) - 1;
u32 _max_index = first;
u32 _max_index = 0;
u32 _min_index = first;

for (const auto &attrib : locations)
Expand Down Expand Up @@ -242,6 +242,7 @@ namespace rsx
}
}

verify(HERE), _max_index >= _min_index;
return { _min_index, (_max_index - _min_index) + 1 };
}
};
Expand Down
131 changes: 76 additions & 55 deletions rpcs3/Emu/RSX/VK/VKGSRender.cpp
Expand Up @@ -1042,15 +1042,32 @@ void VKGSRender::check_heap_status(u32 flags)
}
}

void VKGSRender::check_present_status()
{
if (!m_queued_frames.empty())
{
auto ctx = m_queued_frames.front();
if (ctx->swap_command_buffer->pending)
{
if (!ctx->swap_command_buffer->poke())
{
return;
}
}

process_swap_request(ctx, true);
}
}

void VKGSRender::check_descriptors()
{
// Ease resource pressure if the number of draw calls becomes too high or we are running low on memory resources
const auto required_descriptors = rsx::method_registers.current_draw_clause.pass_count();
verify(HERE), required_descriptors < DESCRIPTOR_MAX_DRAW_CALLS;
if ((required_descriptors + m_current_frame->used_descriptors) > DESCRIPTOR_MAX_DRAW_CALLS)
{
//No need to stall if we have more than one frame queue anyway
flush_command_queue();
// Should hard sync before resetting descriptors for spec compliance
flush_command_queue(true);

CHECK_RESULT(vkResetDescriptorPool(*m_device, m_current_frame->descriptor_pool, 0));
m_current_frame->used_descriptors = 0;
Expand Down Expand Up @@ -1193,6 +1210,27 @@ void VKGSRender::begin()

if (!framebuffer_status_valid)
return;

if (m_current_frame->flags & frame_context_state::dirty)
{
check_present_status();

if (m_current_frame->swap_command_buffer)
{
// Borrow time by using the auxilliary context
m_aux_frame_context.grab_resources(*m_current_frame);
m_current_frame = &m_aux_frame_context;
}

verify(HERE), !m_current_frame->swap_command_buffer;
if (m_current_frame->used_descriptors)
{
CHECK_RESULT(vkResetDescriptorPool(*m_device, m_current_frame->descriptor_pool, 0));
m_current_frame->used_descriptors = 0;
}

m_current_frame->flags &= ~frame_context_state::dirty;
}
}

void VKGSRender::update_draw_state()
Expand Down Expand Up @@ -2276,7 +2314,7 @@ void VKGSRender::flush_command_queue(bool hard_sync)

if (hard_sync)
{
//swap handler checks the pending flag, so call it here
// swap handler checks the pending flag, so call it here
process_swap_request(m_current_frame);

//wait for the latest instruction to execute
Expand All @@ -2294,14 +2332,14 @@ void VKGSRender::flush_command_queue(bool hard_sync)
}
else
{
//Mark this queue as pending
// Mark this queue as pending
m_current_command_buffer->pending = true;

//Grab next cb in line and make it usable
// Grab next cb in line and make it usable
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];

//Soft sync if a present has not yet occured before consuming the wait event
// Soft sync if a present has not yet occured before consuming the wait event
for (auto &ctx : frame_context_storage)
{
if (ctx.swap_command_buffer == m_current_command_buffer)
Expand Down Expand Up @@ -2332,22 +2370,8 @@ void VKGSRender::sync_hint(rsx::FIFO_hint hint)

void VKGSRender::advance_queued_frames()
{
//Check all other frames for completion and clear resources
for (auto &ctx : frame_context_storage)
{
if (&ctx == m_current_frame)
continue;

if (ctx.swap_command_buffer)
{
ctx.swap_command_buffer->poke();
if (ctx.swap_command_buffer->pending)
continue;

//Present the bound image
process_swap_request(&ctx, true);
}
}
// Check all other frames for completion and clear resources
check_present_status();

//m_rtts storage is double buffered and should be safe to tag on frame boundary
m_rtts.free_invalidated();
Expand All @@ -2374,8 +2398,12 @@ void VKGSRender::advance_queued_frames()
m_index_buffer_ring_info.get_current_put_pos_minus_one(),
m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one());

m_queued_frames.push_back(m_current_frame);
verify(HERE), m_queued_frames.size() <= VK_MAX_ASYNC_FRAMES;

m_current_queue_index = (m_current_queue_index + 1) % VK_MAX_ASYNC_FRAMES;
m_current_frame = &frame_context_storage[m_current_queue_index];
m_current_frame->flags |= frame_context_state::dirty;

vk::advance_frame_counter();
}
Expand All @@ -2400,19 +2428,31 @@ void VKGSRender::present(frame_context_t *ctx)
}
}

//Presentation image released; reset value
// Presentation image released; reset value
ctx->present_image = UINT32_MAX;

// Remove from queued list
while (!m_queued_frames.empty())
{
auto frame = m_queued_frames.front();
m_queued_frames.pop_front();

if (frame == ctx)
{
break;
}
}

vk::advance_completed_frame_counter();
}

void VKGSRender::queue_swap_request()
{
//buffer the swap request and return
// Buffer the swap request and return
if (m_current_frame->swap_command_buffer &&
m_current_frame->swap_command_buffer->pending)
{
//Its probable that no actual drawing took place
// Its probable that no actual drawing took place
process_swap_request(m_current_frame);
}

Expand Down Expand Up @@ -2553,10 +2593,18 @@ void VKGSRender::do_local_task(rsx::FIFO_state state)

rsx::thread::do_local_task(state);

if (state == rsx::FIFO_state::lock_wait)
switch (state)
{
case rsx::FIFO_state::lock_wait:
// Critical check finished
return;
case rsx::FIFO_state::spinning:
case rsx::FIFO_state::empty:
// We have some time, check the present queue
check_present_status();
break;
default:
break;
}

check_window_status();
Expand Down Expand Up @@ -2874,33 +2922,6 @@ void VKGSRender::update_vertex_env(const vk::vertex_upload_info& vertex_info)

void VKGSRender::init_buffers(rsx::framebuffer_creation_context context, bool skip_reading)
{
// Clear any pending swap requests
// TODO: Decide on what to do if we circle back to a new frame before the previous frame waiting on it is still pending
// Dropping the frame would in theory allow the thread to advance faster
for (auto &ctx : frame_context_storage)
{
if (ctx.swap_command_buffer)
{
if (ctx.swap_command_buffer->pending)
{
ctx.swap_command_buffer->poke();

if (&ctx == m_current_frame && ctx.swap_command_buffer->pending)
{
//Instead of stopping to wait, use the aux storage to ease pressure
m_aux_frame_context.grab_resources(*m_current_frame);
m_current_frame = &m_aux_frame_context;
}
}

if (!ctx.swap_command_buffer->pending)
{
//process swap without advancing the frame base
process_swap_request(&ctx, true);
}
}
}

prepare_rtts(context);

if (!skip_reading)
Expand Down Expand Up @@ -3342,8 +3363,8 @@ void VKGSRender::flip(int buffer, bool emu_flip)
m_current_frame = &frame_context_storage[m_current_queue_index];
if (m_current_frame->swap_command_buffer)
{
//Always present if pending swap is present.
//Its possible this flip request is triggered by overlays and the flip queue is in undefined state
// Always present if pending swap is present.
// Its possible this flip request is triggered by overlays and the flip queue is in undefined state
process_swap_request(m_current_frame, true);
}

Expand Down
12 changes: 12 additions & 0 deletions rpcs3/Emu/RSX/VK/VKGSRender.h
Expand Up @@ -46,6 +46,7 @@ namespace vk
#define VK_MAX_ASYNC_CB_COUNT 64
#define VK_MAX_ASYNC_FRAMES 2

using rsx::flags32_t;
extern u64 get_system_time();

enum
Expand Down Expand Up @@ -156,13 +157,21 @@ struct occlusion_data
command_buffer_chunk* command_buffer_to_wait = nullptr;
};

enum frame_context_state : u32
{
dirty = 1
};

struct frame_context_t
{
VkSemaphore present_semaphore = VK_NULL_HANDLE;
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;

vk::descriptor_pool descriptor_pool;
u32 used_descriptors = 0;

flags32_t flags = 0;

std::vector<std::unique_ptr<vk::buffer_view>> buffer_views_to_clean;

u32 present_image = UINT32_MAX;
Expand All @@ -188,6 +197,7 @@ struct frame_context_t
descriptor_set = other.descriptor_set;
descriptor_pool = other.descriptor_pool;
used_descriptors = other.used_descriptors;
flags = other.flags;

attrib_heap_ptr = other.attrib_heap_ptr;
vtx_env_heap_ptr = other.vtx_env_heap_ptr;
Expand Down Expand Up @@ -435,6 +445,7 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control

u32 m_current_queue_index = 0;
frame_context_t* m_current_frame = nullptr;
std::deque<frame_context_t*> m_queued_frames;

u32 m_client_width = 0;
u32 m_client_height = 0;
Expand Down Expand Up @@ -510,6 +521,7 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control
void bind_viewport();

void check_window_status();
void check_present_status();

void sync_hint(rsx::FIFO_hint hint) override;

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/VK/VKHelpers.cpp
Expand Up @@ -208,7 +208,7 @@ namespace vk
if (!g_scratch_buffer)
{
// 32M disposable scratch memory
g_scratch_buffer = std::make_unique<vk::buffer>(*g_current_renderer, 64 * 0x100000,
g_scratch_buffer = std::make_unique<vk::buffer>(*g_current_renderer, 128 * 0x100000,
g_current_renderer->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0);
}
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/RSX/VK/VKHelpers.h
Expand Up @@ -31,8 +31,8 @@
#define VK_DISABLE_COMPONENT_SWIZZLE 0
#endif

#define DESCRIPTOR_MAX_DRAW_CALLS 4096
#define OCCLUSION_MAX_POOL_SIZE 8192
#define DESCRIPTOR_MAX_DRAW_CALLS 16384
#define OCCLUSION_MAX_POOL_SIZE DESCRIPTOR_MAX_DRAW_CALLS

#define VERTEX_PARAMS_BIND_SLOT 0
#define VERTEX_LAYOUT_BIND_SLOT 1
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/RSX/VK/VKTexture.cpp
Expand Up @@ -143,7 +143,7 @@ namespace vk
const u32 in_stencil_size = out_w * out_h;

const auto allocation_end = region.bufferOffset + packed_length + in_depth_size + in_stencil_size;
verify(HERE), src->size() >= allocation_end;
verify("Out of memory (compute heap). Lower your resolution scale setting." HERE), src->size() >= allocation_end;

const VkDeviceSize z_offset = align<VkDeviceSize>(region.bufferOffset + packed_length, 256);
const VkDeviceSize s_offset = align<VkDeviceSize>(z_offset + in_depth_size, 256);
Expand Down