rsx/common/d3d12/vulkan: Factorise data_heap between vulkan and d3d12.

This commit is contained in:
Vincent Lejeune 2016-04-02 00:18:20 +02:00
parent cbe119b457
commit 2e17ea1490
15 changed files with 171 additions and 216 deletions

View File

@ -0,0 +1,86 @@
#pragma once
/**
* Ring buffer memory helper :
* There are 2 "pointers" (offset inside a memory buffer to be provided by class derrivative)
* PUT pointer "points" to the start of allocatable space.
* GET pointer "points" to the start of memory in use by the GPU.
* Space between GET and PUT is used by the GPU ; this structure check that this memory is not overwritten.
* User has to update the GET pointer when synchronisation happens.
*/
struct data_heap
{
/**
* Does alloc cross get position ?
*/
template<int Alignement>
bool can_alloc(size_t size) const
{
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
// range before get
if (aligned_put_pos + alloc_size < m_get_pos)
return true;
// range after get
if (aligned_put_pos > m_get_pos)
return true;
return false;
}
else
{
// ..]....[..get..
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (alloc_size > m_get_pos)
return false;
return true;
}
}
size_t m_size;
size_t m_put_pos; // Start of free space
public:
data_heap() = default;
~data_heap() = default;
data_heap(const data_heap&) = delete;
data_heap(data_heap&&) = delete;
size_t m_get_pos; // End of free space
void init(size_t heap_size)
{
m_size = heap_size;
m_put_pos = 0;
m_get_pos = heap_size - 1;
}
template<int Alignement>
size_t alloc(size_t size)
{
if (!can_alloc<Alignement>(size)) throw EXCEPTION("Working buffer not big enough");
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
m_put_pos = aligned_put_pos + alloc_size;
return aligned_put_pos;
}
else
{
m_put_pos = alloc_size;
return 0;
}
}
/**
* return current putpos - 1
*/
size_t get_current_put_pos_minus_one() const
{
return (m_put_pos - 1 > 0) ? m_put_pos - 1 : m_size - 1;
}
};

View File

@ -146,7 +146,7 @@ namespace
std::tuple<std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>, size_t> upload_inlined_vertex_array( std::tuple<std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>, size_t> upload_inlined_vertex_array(
gsl::span<const rsx::data_array_format_info, 16> vertex_attribute_infos, gsl::span<const rsx::data_array_format_info, 16> vertex_attribute_infos,
gsl::span<const gsl::byte> inlined_array_raw_data, gsl::span<const gsl::byte> inlined_array_raw_data,
data_heap& ring_buffer_data, d3d12_data_heap& ring_buffer_data,
ID3D12Resource* vertex_buffer_placement, ID3D12Resource* vertex_buffer_placement,
ID3D12GraphicsCommandList* command_list ID3D12GraphicsCommandList* command_list
) )

View File

@ -106,8 +106,8 @@ private:
resource_storage &get_non_current_resource_storage(); resource_storage &get_non_current_resource_storage();
// Textures, constants, index and vertex buffers storage // Textures, constants, index and vertex buffers storage
data_heap m_buffer_data; d3d12_data_heap m_buffer_data;
data_heap m_readback_resources; d3d12_data_heap m_readback_resources;
ComPtr<ID3D12Resource> m_vertex_buffer_data; ComPtr<ID3D12Resource> m_vertex_buffer_data;
rsx::render_targets m_rtts; rsx::render_targets m_rtts;

View File

@ -1,58 +1,16 @@
#pragma once #pragma once
#include "D3D12Utils.h" #include "D3D12Utils.h"
#include "d3dx12.h" #include "d3dx12.h"
#include "../Common/ring_buffer_helper.h"
struct d3d12_data_heap : public data_heap
/**
* Wrapper around a ID3D12Resource or a ID3D12Heap.
* Acts as a ring buffer : hold a get and put pointers,
* put pointer is used as storage space offset
* and get is used as beginning of in use data space.
* This wrapper checks that put pointer doesn't cross get one.
*/
class data_heap
{ {
/**
* Does alloc cross get position ?
*/
template<int Alignement>
bool can_alloc(size_t size) const
{
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
// range before get
if (aligned_put_pos + alloc_size < m_get_pos)
return true;
// range after get
if (aligned_put_pos > m_get_pos)
return true;
return false;
}
else
{
// ..]....[..get..
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (alloc_size > m_get_pos)
return false;
return true;
}
}
size_t m_size;
size_t m_put_pos; // Start of free space
ComPtr<ID3D12Resource> m_heap; ComPtr<ID3D12Resource> m_heap;
public: public:
data_heap() = default; d3d12_data_heap() = default;
~data_heap() = default; ~d3d12_data_heap() = default;
data_heap(const data_heap&) = delete; d3d12_data_heap(const d3d12_data_heap&) = delete;
data_heap(data_heap&&) = delete; d3d12_data_heap(d3d12_data_heap&&) = delete;
size_t m_get_pos; // End of free space
template <typename... arg_type> template <typename... arg_type>
void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_RESOURCE_STATES state) void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_RESOURCE_STATES state)
@ -72,24 +30,6 @@ public:
); );
} }
template<int Alignement>
size_t alloc(size_t size)
{
if (!can_alloc<Alignement>(size)) throw EXCEPTION("Working buffer not big enough");
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
m_put_pos = aligned_put_pos + alloc_size;
return aligned_put_pos;
}
else
{
m_put_pos = alloc_size;
return 0;
}
}
template<typename T> template<typename T>
T* map(const D3D12_RANGE &range) T* map(const D3D12_RANGE &range)
{ {
@ -122,14 +62,6 @@ public:
{ {
return m_heap.Get(); return m_heap.Get();
} }
/**
* return current putpos - 1
*/
size_t get_current_put_pos_minus_one() const
{
return (m_put_pos - 1 > 0) ? m_put_pos - 1 : m_size - 1;
}
}; };
struct texture_entry struct texture_entry

View File

@ -240,7 +240,7 @@ namespace
size_t download_to_readback_buffer( size_t download_to_readback_buffer(
ID3D12Device *device, ID3D12Device *device,
ID3D12GraphicsCommandList * command_list, ID3D12GraphicsCommandList * command_list,
data_heap &readback_heap, d3d12_data_heap &readback_heap,
ID3D12Resource * color_surface, ID3D12Resource * color_surface,
rsx::surface_color_format color_surface_format rsx::surface_color_format color_surface_format
) )
@ -262,7 +262,7 @@ namespace
return heap_offset; return heap_offset;
} }
void copy_readback_buffer_to_dest(void *dest, data_heap &readback_heap, size_t offset_in_heap, size_t dst_pitch, size_t src_pitch, size_t height) void copy_readback_buffer_to_dest(void *dest, d3d12_data_heap &readback_heap, size_t offset_in_heap, size_t dst_pitch, size_t src_pitch, size_t height)
{ {
// TODO: Use exact range // TODO: Use exact range
void *mapped_buffer = readback_heap.map<void>(offset_in_heap); void *mapped_buffer = readback_heap.map<void>(offset_in_heap);

View File

@ -130,7 +130,7 @@ struct render_target_traits
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_download_command( std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_download_command(
gsl::not_null<ID3D12Resource*> rtt, gsl::not_null<ID3D12Resource*> rtt,
surface_color_format color_format, size_t width, size_t height, surface_color_format color_format, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store
) )
{ {
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
@ -163,7 +163,7 @@ struct render_target_traits
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_depth_download_command( std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_depth_download_command(
gsl::not_null<ID3D12Resource*> ds, gsl::not_null<ID3D12Resource*> ds,
surface_depth_format depth_format, size_t width, size_t height, surface_depth_format depth_format, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store
) )
{ {
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
@ -196,7 +196,7 @@ struct render_target_traits
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_stencil_download_command( std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_stencil_download_command(
gsl::not_null<ID3D12Resource*> stencil, gsl::not_null<ID3D12Resource*> stencil,
size_t width, size_t height, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store
) )
{ {
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get(); ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
@ -226,7 +226,7 @@ struct render_target_traits
static static
gsl::span<const gsl::byte> map_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data, gsl::span<const gsl::byte> map_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store) gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store)
{ {
size_t offset; size_t offset;
size_t buffer_size; size_t buffer_size;
@ -243,7 +243,7 @@ struct render_target_traits
static static
void unmap_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data, void unmap_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store) gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, d3d12_data_heap &readback_heap, resource_storage &res_store)
{ {
readback_heap.unmap(); readback_heap.unmap();
} }

View File

@ -69,7 +69,7 @@ namespace {
void update_existing_texture( void update_existing_texture(
const rsx::texture &texture, const rsx::texture &texture,
ID3D12GraphicsCommandList *command_list, ID3D12GraphicsCommandList *command_list,
data_heap &texture_buffer_heap, d3d12_data_heap &texture_buffer_heap,
ID3D12Resource *existing_texture) ID3D12Resource *existing_texture)
{ {
size_t w = texture.width(), h = texture.height(); size_t w = texture.width(), h = texture.height();
@ -123,7 +123,7 @@ ComPtr<ID3D12Resource> upload_single_texture(
const rsx::texture &texture, const rsx::texture &texture,
ID3D12Device *device, ID3D12Device *device,
ID3D12GraphicsCommandList *command_list, ID3D12GraphicsCommandList *command_list,
data_heap &texture_buffer_heap) d3d12_data_heap &texture_buffer_heap)
{ {
ComPtr<ID3D12Resource> result; ComPtr<ID3D12Resource> result;
CHECK_HRESULT(device->CreateCommittedResource( CHECK_HRESULT(device->CreateCommittedResource(

View File

@ -403,11 +403,11 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
#define RING_BUFFER_SIZE 16 * 1024 * 1024 #define RING_BUFFER_SIZE 16 * 1024 * 1024
m_uniform_buffer_ring_info.init(RING_BUFFER_SIZE); m_uniform_buffer_ring_info.init(RING_BUFFER_SIZE);
m_uniform_buffer.reset(new vk::buffer(*m_device, RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0)); m_uniform_buffer_ring_info.heap.reset(new vk::buffer(*m_device, RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0));
m_index_buffer_ring_info.init(RING_BUFFER_SIZE); m_index_buffer_ring_info.init(RING_BUFFER_SIZE);
m_index_buffer.reset(new vk::buffer(*m_device, RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 0)); m_index_buffer_ring_info.heap.reset(new vk::buffer(*m_device, RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 0));
m_texture_upload_buffer_ring_info.init(8 * RING_BUFFER_SIZE); m_texture_upload_buffer_ring_info.init(8 * RING_BUFFER_SIZE);
m_texture_upload_buffer.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0)); m_texture_upload_buffer_ring_info.heap.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0));
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);
@ -451,10 +451,10 @@ VKGSRender::~VKGSRender()
//TODO: Properly destroy shader modules instead of calling clear... //TODO: Properly destroy shader modules instead of calling clear...
m_prog_buffer.clear(); m_prog_buffer.clear();
m_index_buffer.release(); m_index_buffer_ring_info.heap.release();
m_uniform_buffer.release(); m_uniform_buffer_ring_info.heap.release();
m_attrib_buffers.release(); m_attrib_ring_info.heap.release();
m_texture_upload_buffer.release(); m_texture_upload_buffer_ring_info.heap.release();
null_buffer.release(); null_buffer.release();
null_buffer_view.release(); null_buffer_view.release();
m_buffer_view_to_clean.clear(); m_buffer_view_to_clean.clear();
@ -562,7 +562,7 @@ void VKGSRender::end()
m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets); m_program->bind_uniform({ vk::null_sampler(), vk::null_image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets);
continue; continue;
} }
vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer.get()); vk::image_view *texture0 = m_texture_cache.upload_texture(m_command_buffer, textures[i], m_rtts, m_memory_type_mapping, m_texture_upload_buffer_ring_info, m_texture_upload_buffer_ring_info.heap.get());
VkFilter min_filter; VkFilter min_filter;
VkSamplerMipmapMode mip_mode; VkSamplerMipmapMode mip_mode;
@ -603,7 +603,7 @@ void VKGSRender::end()
VkDeviceSize offset; VkDeviceSize offset;
std::tie(std::ignore, std::ignore, index_count, offset, index_type) = upload_info; std::tie(std::ignore, std::ignore, index_count, offset, index_type) = upload_info;
vkCmdBindIndexBuffer(m_command_buffer, m_index_buffer->value, offset, index_type); vkCmdBindIndexBuffer(m_command_buffer, m_index_buffer_ring_info.heap->value, offset, index_type);
vkCmdDrawIndexed(m_command_buffer, index_count, 1, 0, 0, 0); vkCmdDrawIndexed(m_command_buffer, index_count, 1, 0, 0, 0);
} }
@ -656,7 +656,7 @@ void VKGSRender::on_init_thread()
{ {
GSRender::on_init_thread(); GSRender::on_init_thread();
m_attrib_ring_info.init(8 * RING_BUFFER_SIZE); m_attrib_ring_info.init(8 * RING_BUFFER_SIZE);
m_attrib_buffers.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0)); m_attrib_ring_info.heap.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0));
} }
void VKGSRender::on_exit() void VKGSRender::on_exit()
@ -893,7 +893,7 @@ bool VKGSRender::load_program()
//3. Update fragment constants //3. Update fragment constants
const size_t scale_offset_offset = m_uniform_buffer_ring_info.alloc<256>(256); const size_t scale_offset_offset = m_uniform_buffer_ring_info.alloc<256>(256);
u8 *buf = (u8*)m_uniform_buffer->map(scale_offset_offset, 256); u8 *buf = (u8*)m_uniform_buffer_ring_info.map(scale_offset_offset, 256);
//TODO: Add case for this in RSXThread //TODO: Add case for this in RSXThread
/** /**
@ -926,22 +926,22 @@ bool VKGSRender::load_program()
memset((char*)buf+64, 0, 8); memset((char*)buf+64, 0, 8);
memcpy((char*)buf + 64, &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float)); memcpy((char*)buf + 64, &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float));
memcpy((char*)buf + 68, &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float)); memcpy((char*)buf + 68, &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float));
m_uniform_buffer->unmap(); m_uniform_buffer_ring_info.unmap();
const size_t vertex_constants_offset = m_uniform_buffer_ring_info.alloc<256>(512 * 4 * sizeof(float)); const size_t vertex_constants_offset = m_uniform_buffer_ring_info.alloc<256>(512 * 4 * sizeof(float));
buf = (u8*)m_uniform_buffer->map(vertex_constants_offset, 512 * 4 * sizeof(float)); buf = (u8*)m_uniform_buffer_ring_info.map(vertex_constants_offset, 512 * 4 * sizeof(float));
fill_vertex_program_constants_data(buf); fill_vertex_program_constants_data(buf);
m_uniform_buffer->unmap(); m_uniform_buffer_ring_info.unmap();
const size_t fragment_constants_sz = m_prog_buffer.get_fragment_constants_buffer_size(fragment_program); const size_t fragment_constants_sz = m_prog_buffer.get_fragment_constants_buffer_size(fragment_program);
const size_t fragment_constants_offset = m_uniform_buffer_ring_info.alloc<256>(fragment_constants_sz); const size_t fragment_constants_offset = m_uniform_buffer_ring_info.alloc<256>(fragment_constants_sz);
buf = (u8*)m_uniform_buffer->map(fragment_constants_offset, fragment_constants_sz); buf = (u8*)m_uniform_buffer_ring_info.map(fragment_constants_offset, fragment_constants_sz);
m_prog_buffer.fill_fragment_constans_buffer({ reinterpret_cast<float*>(buf), gsl::narrow<int>(fragment_constants_sz) }, fragment_program); m_prog_buffer.fill_fragment_constans_buffer({ reinterpret_cast<float*>(buf), gsl::narrow<int>(fragment_constants_sz) }, fragment_program);
m_uniform_buffer->unmap(); m_uniform_buffer_ring_info.unmap();
m_program->bind_uniform({ m_uniform_buffer->value, scale_offset_offset, 256 }, SCALE_OFFSET_BIND_SLOT, descriptor_sets); m_program->bind_uniform({ m_uniform_buffer_ring_info.heap->value, scale_offset_offset, 256 }, SCALE_OFFSET_BIND_SLOT, descriptor_sets);
m_program->bind_uniform({ m_uniform_buffer->value, vertex_constants_offset, 512 * 4 * sizeof(float) }, VERTEX_CONSTANT_BUFFERS_BIND_SLOT, descriptor_sets); m_program->bind_uniform({ m_uniform_buffer_ring_info.heap->value, vertex_constants_offset, 512 * 4 * sizeof(float) }, VERTEX_CONSTANT_BUFFERS_BIND_SLOT, descriptor_sets);
m_program->bind_uniform({ m_uniform_buffer->value, fragment_constants_offset, fragment_constants_sz }, FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT, descriptor_sets); m_program->bind_uniform({ m_uniform_buffer_ring_info.heap->value, fragment_constants_offset, fragment_constants_sz }, FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT, descriptor_sets);
return true; return true;
} }

View File

@ -23,8 +23,7 @@ private:
rsx::surface_info m_surface; rsx::surface_info m_surface;
vk::data_heap m_attrib_ring_info; vk::vk_data_heap m_attrib_ring_info;
std::unique_ptr<vk::buffer> m_attrib_buffers;
vk::texture_cache m_texture_cache; vk::texture_cache m_texture_cache;
rsx::vk_render_targets m_rtts; rsx::vk_render_targets m_rtts;
@ -45,12 +44,9 @@ private:
vk::swap_chain* m_swap_chain; vk::swap_chain* m_swap_chain;
//buffer //buffer
vk::data_heap m_uniform_buffer_ring_info; vk::vk_data_heap m_uniform_buffer_ring_info;
std::unique_ptr<vk::buffer> m_uniform_buffer; vk::vk_data_heap m_index_buffer_ring_info;
vk::data_heap m_index_buffer_ring_info; vk::vk_data_heap m_texture_upload_buffer_ring_info;
std::unique_ptr<vk::buffer> m_index_buffer;
vk::data_heap m_texture_upload_buffer_ring_info;
std::unique_ptr<vk::buffer> m_texture_upload_buffer;
//Vulkan internals //Vulkan internals
u32 m_current_present_image = 0xFFFF; u32 m_current_present_image = 0xFFFF;

View File

@ -15,6 +15,7 @@
#include "VulkanAPI.h" #include "VulkanAPI.h"
#include "../GCM.h" #include "../GCM.h"
#include "../Common/TextureUtils.h" #include "../Common/TextureUtils.h"
#include "../Common/ring_buffer_helper.h"
namespace rsx namespace rsx
{ {
@ -1308,87 +1309,21 @@ namespace vk
}; };
} }
struct vk_data_heap : public data_heap
// TODO: factorize between backends
class data_heap
{ {
/** std::unique_ptr<vk::buffer> heap;
* Does alloc cross get position ?
*/ void* map(size_t offset, size_t size)
template<int Alignement>
bool can_alloc(size_t size) const
{ {
size_t alloc_size = align(size, Alignement); return heap->map(offset, size);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
// range before get
if (aligned_put_pos + alloc_size < m_get_pos)
return true;
// range after get
if (aligned_put_pos > m_get_pos)
return true;
return false;
}
else
{
// ..]....[..get..
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (alloc_size > m_get_pos)
return false;
return true;
}
} }
size_t m_size; void unmap()
size_t m_put_pos; // Start of free space
public:
data_heap() = default;
~data_heap() = default;
data_heap(const data_heap&) = delete;
data_heap(data_heap&&) = delete;
size_t m_get_pos; // End of free space
void init(size_t heap_size)
{ {
m_size = heap_size; heap->unmap();
m_put_pos = 0;
m_get_pos = heap_size - 1;
}
template<int Alignement>
size_t alloc(size_t size)
{
if (!can_alloc<Alignement>(size)) throw EXCEPTION("Working buffer not big enough");
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
m_put_pos = aligned_put_pos + alloc_size;
return aligned_put_pos;
}
else
{
m_put_pos = alloc_size;
return 0;
}
}
/**
* return current putpos - 1
*/
size_t get_current_put_pos_minus_one() const
{
return (m_put_pos - 1 > 0) ? m_put_pos - 1 : m_size - 1;
} }
}; };
/** /**
* Allocate enough space in upload_buffer and write all mipmap/layer data into the subbuffer. * Allocate enough space in upload_buffer and write all mipmap/layer data into the subbuffer.
* Then copy all layers into dst_image. * Then copy all layers into dst_image.
@ -1396,5 +1331,5 @@ namespace vk
*/ */
void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, VkImage dst_image, void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, VkImage dst_image,
const std::vector<rsx_subresource_layout> subresource_layout, int format, bool is_swizzled, u16 mipmap_count, const std::vector<rsx_subresource_layout> subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
vk::data_heap &upload_heap, vk::buffer* upload_buffer); vk::vk_data_heap &upload_heap, vk::buffer* upload_buffer);
} }

View File

@ -130,7 +130,7 @@ namespace vk
void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, VkImage dst_image, void copy_mipmaped_image_using_buffer(VkCommandBuffer cmd, VkImage dst_image,
const std::vector<rsx_subresource_layout> subresource_layout, int format, bool is_swizzled, u16 mipmap_count, const std::vector<rsx_subresource_layout> subresource_layout, int format, bool is_swizzled, u16 mipmap_count,
vk::data_heap &upload_heap, vk::buffer* upload_buffer) vk::vk_data_heap &upload_heap, vk::buffer* upload_buffer)
{ {
u32 mipmap_level = 0; u32 mipmap_level = 0;
u32 block_in_pixel = get_format_block_size_in_texel(format); u32 block_in_pixel = get_format_block_size_in_texel(format);

View File

@ -149,7 +149,7 @@ namespace vk
m_cache.resize(0); m_cache.resize(0);
} }
vk::image_view* upload_texture(command_buffer cmd, rsx::texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, data_heap& upload_heap, vk::buffer* upload_buffer) vk::image_view* upload_texture(command_buffer cmd, rsx::texture &tex, rsx::vk_render_targets &m_rtts, const vk::memory_type_mapping &memory_type_mapping, vk_data_heap& upload_heap, vk::buffer* upload_buffer)
{ {
const u32 texaddr = rsx::get_address(tex.offset(), tex.location()); const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
const u32 range = (u32)get_texture_size(tex); const u32 range = (u32)get_texture_size(tex);

View File

@ -218,18 +218,20 @@ namespace vk
namespace namespace
{ {
size_t alloc_and_copy(vk::buffer* buffer, vk::data_heap& data_heap_info, size_t size, std::function<void(gsl::span<gsl::byte> ptr)> copy_function) struct data_heap_alloc
{ {
size_t offset = data_heap_info.alloc<256>(size); static size_t alloc_and_copy(vk::vk_data_heap& data_heap_info, size_t size, std::function<void(gsl::span<gsl::byte> ptr)> copy_function)
void* buf = buffer->map(offset, size); {
gsl::span<gsl::byte> mapped_span = {reinterpret_cast<gsl::byte*>(buf), gsl::narrow<int>(size) }; size_t offset = data_heap_info.alloc<256>(size);
copy_function(mapped_span); void* buf = data_heap_info.map(offset, size);
buffer->unmap(); gsl::span<gsl::byte> mapped_span = { reinterpret_cast<gsl::byte*>(buf), gsl::narrow<int>(size) };
return offset; copy_function(mapped_span);
} data_heap_info.unmap();
return offset;
}
};
} }
std::tuple<VkPrimitiveTopology, bool, u32, VkDeviceSize, VkIndexType> std::tuple<VkPrimitiveTopology, bool, u32, VkDeviceSize, VkIndexType>
VKGSRender::upload_vertex_data() VKGSRender::upload_vertex_data()
{ {
@ -341,9 +343,9 @@ VKGSRender::upload_vertex_data()
throw EXCEPTION("Unknown base type %d", vertex_info.type); throw EXCEPTION("Unknown base type %d", vertex_info.type);
} }
size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [&vertex_arrays_data, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), vertex_arrays_data.data(), data_size); }); size_t offset_in_attrib_buffer = data_heap_alloc::alloc_and_copy(m_attrib_ring_info, data_size, [&vertex_arrays_data, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), vertex_arrays_data.data(), data_size); });
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size));
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets);
} }
} }
@ -428,8 +430,8 @@ VKGSRender::upload_vertex_data()
const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size);
const u32 data_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size) * num_stored_verts; const u32 data_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size) * num_stored_verts;
size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), data_ptr, data_size); }); size_t offset_in_attrib_buffer = data_heap_alloc::alloc_and_copy(m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), data_ptr, data_size); });
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size));
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets);
} }
else if (register_vertex_info[index].size > 0) else if (register_vertex_info[index].size > 0)
@ -465,8 +467,8 @@ VKGSRender::upload_vertex_data()
} }
size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), data_ptr, data_size); }); size_t offset_in_attrib_buffer = data_heap_alloc::alloc_and_copy(m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span<gsl::byte> ptr) { memcpy(ptr.data(), data_ptr, data_size); });
m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); m_buffer_view_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, format, offset_in_attrib_buffer, data_size));
m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets);
break; break;
} }
@ -500,9 +502,9 @@ VKGSRender::upload_vertex_data()
index_count = vk::expand_line_loop_array_to_strip(vertex_draw_count, indices); index_count = vk::expand_line_loop_array_to_strip(vertex_draw_count, indices);
size_t upload_size = index_count * sizeof(u16); size_t upload_size = index_count * sizeof(u16);
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer->map(offset_in_index_buffer, upload_size); void* buf = m_index_buffer_ring_info.heap->map(offset_in_index_buffer, upload_size);
memcpy(buf, indices.data(), upload_size); memcpy(buf, indices.data(), upload_size);
m_index_buffer->unmap(); m_index_buffer_ring_info.heap->unmap();
} }
else else
{ {
@ -515,18 +517,18 @@ VKGSRender::upload_vertex_data()
index_count = vk::expand_indexed_line_loop_to_strip(vertex_draw_count, (u32*)vertex_index_array.data(), indices32); index_count = vk::expand_indexed_line_loop_to_strip(vertex_draw_count, (u32*)vertex_index_array.data(), indices32);
size_t upload_size = index_count * sizeof(u32); size_t upload_size = index_count * sizeof(u32);
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer->map(offset_in_index_buffer, upload_size); void* buf = m_index_buffer_ring_info.heap->map(offset_in_index_buffer, upload_size);
memcpy(buf, indices32.data(), upload_size); memcpy(buf, indices32.data(), upload_size);
m_index_buffer->unmap(); m_index_buffer_ring_info.heap->unmap();
} }
else else
{ {
index_count = vk::expand_indexed_line_loop_to_strip(vertex_draw_count, (u16*)vertex_index_array.data(), indices); index_count = vk::expand_indexed_line_loop_to_strip(vertex_draw_count, (u16*)vertex_index_array.data(), indices);
size_t upload_size = index_count * sizeof(u16); size_t upload_size = index_count * sizeof(u16);
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer->map(offset_in_index_buffer, upload_size); void* buf = m_index_buffer_ring_info.heap->map(offset_in_index_buffer, upload_size);
memcpy(buf, indices.data(), upload_size); memcpy(buf, indices.data(), upload_size);
m_index_buffer->unmap(); m_index_buffer_ring_info.heap->unmap();
} }
} }
} }
@ -553,9 +555,9 @@ VKGSRender::upload_vertex_data()
size_t upload_size = index_count * sizeof(u16); size_t upload_size = index_count * sizeof(u16);
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer->map(offset_in_index_buffer, upload_size); void* buf = m_index_buffer_ring_info.heap->map(offset_in_index_buffer, upload_size);
memcpy(buf, indices.data(), upload_size); memcpy(buf, indices.data(), upload_size);
m_index_buffer->unmap(); m_index_buffer_ring_info.heap->unmap();
} }
is_indexed_draw = true; is_indexed_draw = true;
@ -582,9 +584,9 @@ VKGSRender::upload_vertex_data()
size_t upload_size = vertex_index_array.size(); size_t upload_size = vertex_index_array.size();
offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size); offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer->map(offset_in_index_buffer, upload_size); void* buf = m_index_buffer_ring_info.heap->map(offset_in_index_buffer, upload_size);
memcpy(buf, vertex_index_array.data(), upload_size); memcpy(buf, vertex_index_array.data(), upload_size);
m_index_buffer->unmap(); m_index_buffer_ring_info.heap->unmap();
} }
return std::make_tuple(prims, is_indexed_draw, index_count, offset_in_index_buffer, index_format); return std::make_tuple(prims, is_indexed_draw, index_count, offset_in_index_buffer, index_format);

View File

@ -550,6 +550,7 @@
<ClInclude Include="Emu\RSX\Common\BufferUtils.h" /> <ClInclude Include="Emu\RSX\Common\BufferUtils.h" />
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" /> <ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" /> <ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />
<ClInclude Include="Emu\RSX\Common\ring_buffer_helper.h" />
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" /> <ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
<ClInclude Include="Emu\RSX\Common\surface_store.h" /> <ClInclude Include="Emu\RSX\Common\surface_store.h" />
<ClInclude Include="Emu\RSX\Common\TextureUtils.h" /> <ClInclude Include="Emu\RSX\Common\TextureUtils.h" />

View File

@ -1776,10 +1776,13 @@
<ClInclude Include="Emu\RSX\rsx_methods.h"> <ClInclude Include="Emu\RSX\rsx_methods.h">
<Filter>Emu\GPU\RSX</Filter> <Filter>Emu\GPU\RSX</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\stblib\stb_image.h"> <ClInclude Include="Emu\RSX\Common\surface_store.h">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude>
<ClInclude Include="..\3rdparty\stblib\stb_image.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\RSX\Common\surface_store.h"> <ClInclude Include="Emu\RSX\Common\ring_buffer_helper.h">
<Filter>Emu\GPU\RSX\Common</Filter> <Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>