Skip to content

Commit

Permalink
vk: Check for heap change events after a grow to avoid spec violations
Browse files Browse the repository at this point in the history
- Avoid referencing the old buffer in stale views. Status can be set
globally if requested during heap creation.
  • Loading branch information
kd-11 committed Nov 10, 2019
1 parent d1a308b commit 6bac3ce
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 9 deletions.
20 changes: 15 additions & 5 deletions rpcs3/Emu/RSX/VK/VKGSRender.cpp
Expand Up @@ -448,11 +448,11 @@ VKGSRender::VKGSRender() : GSRender()
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

//VRAM allocation
m_attrib_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000, "attrib buffer", 0x400000);
m_attrib_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_ATTRIB_RING_BUFFER_SIZE_M * 0x100000, "attrib buffer", 0x400000, VK_TRUE);
m_fragment_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment env buffer");
m_vertex_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex env buffer");
m_fragment_texture_params_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment texture params buffer");
m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer");
m_vertex_layout_ring_info.create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "vertex layout buffer", 0x10000, VK_TRUE);
m_fragment_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "fragment constants buffer");
m_transform_constants_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "transform constants buffer");
m_index_buffer_ring_info.create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_INDEX_RING_BUFFER_SIZE_M * 0x100000, "index buffer");
Expand Down Expand Up @@ -1092,7 +1092,17 @@ void VKGSRender::emit_geometry(u32 sub_index)
// Allocate stream layout memory for this batch
m_vertex_layout_stream_info.range = rsx::method_registers.current_draw_clause.pass_count() * 128;
m_vertex_layout_stream_info.offset = m_vertex_layout_ring_info.alloc<256>(m_vertex_layout_stream_info.range);
// m_vertex_layout_stream_info.buffer = m_vertex_layout_ring_info.heap->value;

if (vk::test_status_interrupt(vk::heap_changed))
{
if (m_vertex_layout_storage &&
m_vertex_layout_storage->info.buffer != m_vertex_layout_ring_info.heap->value)
{
m_current_frame->buffer_views_to_clean.push_back(std::move(m_vertex_layout_storage));
}

vk::clear_status_interrupt(vk::heap_changed);
}
}
else if (persistent_buffer != old_persistent_buffer || volatile_buffer != old_volatile_buffer)
{
Expand Down Expand Up @@ -2833,7 +2843,7 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
// Wait before sync block below
rsx::g_dma_manager.sync();

if (vk::test_status_interrupt(vk::heap_check))
if (vk::test_status_interrupt(vk::heap_dirty))
{
if (m_attrib_ring_info.dirty() ||
m_fragment_env_ring_info.dirty() ||
Expand Down Expand Up @@ -2864,7 +2874,7 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
}

vk::clear_status_interrupt(vk::heap_check);
vk::clear_status_interrupt(vk::heap_dirty);
}

// End any active renderpasses; the caller should handle reopening
Expand Down
7 changes: 6 additions & 1 deletion rpcs3/Emu/RSX/VK/VKHelpers.cpp
Expand Up @@ -169,6 +169,11 @@ namespace vk
get_resource_manager()->dispose(heap);
heap = std::make_unique<buffer>(*device, aligned_new_size, memory_index, memory_flags, usage, 0);

if (notify_on_grow)
{
raise_status_interrupt(vk::heap_changed);
}

return true;
}

Expand Down Expand Up @@ -338,7 +343,7 @@ namespace vk
{
if (!g_upload_heap.heap)
{
g_upload_heap.create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 64 * 0x100000, "auxilliary upload heap");
g_upload_heap.create(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 64 * 0x100000, "auxilliary upload heap", 0x100000);
}

return &g_upload_heap;
Expand Down
11 changes: 8 additions & 3 deletions rpcs3/Emu/RSX/VK/VKHelpers.h
Expand Up @@ -73,7 +73,8 @@ namespace vk
enum runtime_state
{
uninterruptible = 1,
heap_check = 2
heap_dirty = 2,
heap_changed = 3
};

enum class driver_vendor
Expand Down Expand Up @@ -3407,6 +3408,8 @@ namespace vk
bool mapped = false;
void *_ptr = nullptr;

bool notify_on_grow = false;

std::unique_ptr<buffer> shadow;
std::vector<VkBufferCopy> dirty_ranges;

Expand All @@ -3420,7 +3423,7 @@ namespace vk
// Avoid mapping/unmapping to keep these drivers from stalling
// NOTE2: HOST_CACHED flag does not keep the mapped ptr around in the driver either

void create(VkBufferUsageFlags usage, size_t size, const char *name = "unnamed", size_t guard = 0x10000)
void create(VkBufferUsageFlags usage, size_t size, const char *name, size_t guard = 0x10000, VkBool32 notify = VK_FALSE)
{
::data_heap::init(size, name, guard);

Expand All @@ -3441,7 +3444,9 @@ namespace vk
}

heap = std::make_unique<buffer>(*device, size, memory_index, memory_flags, usage, 0);

initial_size = size;
notify_on_grow = bool(notify);
}

void destroy()
Expand Down Expand Up @@ -3470,7 +3475,7 @@ namespace vk
if (shadow)
{
dirty_ranges.push_back({offset, offset, size});
raise_status_interrupt(runtime_state::heap_check);
raise_status_interrupt(runtime_state::heap_dirty);
}

return (u8*)_ptr + offset;
Expand Down
18 changes: 18 additions & 0 deletions rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp
Expand Up @@ -318,6 +318,24 @@ vk::vertex_upload_info VKGSRender::upload_vertex_data()
}
}

if (vk::test_status_interrupt(vk::heap_changed))
{
// Check for validity
if (m_persistent_attribute_storage &&
m_persistent_attribute_storage->info.buffer != m_attrib_ring_info.heap->value)
{
m_current_frame->buffer_views_to_clean.push_back(std::move(m_persistent_attribute_storage));
}

if (m_volatile_attribute_storage &&
m_volatile_attribute_storage->info.buffer != m_attrib_ring_info.heap->value)
{
m_current_frame->buffer_views_to_clean.push_back(std::move(m_volatile_attribute_storage));
}

vk::clear_status_interrupt(vk::heap_changed);
}

if (persistent_range_base != UINT32_MAX)
{
if (!m_persistent_attribute_storage || !m_persistent_attribute_storage->in_range(persistent_range_base, required.first, persistent_range_base))
Expand Down

0 comments on commit 6bac3ce

Please sign in to comment.