mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
rsx/common/d3d12/vulkan: Factorise data_heap between vulkan and d3d12.
This commit is contained in:
parent
cbe119b457
commit
2e17ea1490
86
rpcs3/Emu/RSX/Common/ring_buffer_helper.h
Normal file
86
rpcs3/Emu/RSX/Common/ring_buffer_helper.h
Normal 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;
|
||||
}
|
||||
};
|
@ -146,7 +146,7 @@ namespace
|
||||
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 gsl::byte> inlined_array_raw_data,
|
||||
data_heap& ring_buffer_data,
|
||||
d3d12_data_heap& ring_buffer_data,
|
||||
ID3D12Resource* vertex_buffer_placement,
|
||||
ID3D12GraphicsCommandList* command_list
|
||||
)
|
||||
|
@ -106,8 +106,8 @@ private:
|
||||
resource_storage &get_non_current_resource_storage();
|
||||
|
||||
// Textures, constants, index and vertex buffers storage
|
||||
data_heap m_buffer_data;
|
||||
data_heap m_readback_resources;
|
||||
d3d12_data_heap m_buffer_data;
|
||||
d3d12_data_heap m_readback_resources;
|
||||
ComPtr<ID3D12Resource> m_vertex_buffer_data;
|
||||
|
||||
rsx::render_targets m_rtts;
|
||||
|
@ -1,58 +1,16 @@
|
||||
#pragma once
|
||||
#include "D3D12Utils.h"
|
||||
#include "d3dx12.h"
|
||||
#include "../Common/ring_buffer_helper.h"
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
struct d3d12_data_heap : public 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;
|
||||
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
|
||||
d3d12_data_heap() = default;
|
||||
~d3d12_data_heap() = default;
|
||||
d3d12_data_heap(const d3d12_data_heap&) = delete;
|
||||
d3d12_data_heap(d3d12_data_heap&&) = delete;
|
||||
|
||||
template <typename... arg_type>
|
||||
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>
|
||||
T* map(const D3D12_RANGE &range)
|
||||
{
|
||||
@ -122,14 +62,6 @@ public:
|
||||
{
|
||||
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
|
||||
|
@ -240,7 +240,7 @@ namespace
|
||||
size_t download_to_readback_buffer(
|
||||
ID3D12Device *device,
|
||||
ID3D12GraphicsCommandList * command_list,
|
||||
data_heap &readback_heap,
|
||||
d3d12_data_heap &readback_heap,
|
||||
ID3D12Resource * color_surface,
|
||||
rsx::surface_color_format color_surface_format
|
||||
)
|
||||
@ -262,7 +262,7 @@ namespace
|
||||
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
|
||||
void *mapped_buffer = readback_heap.map<void>(offset_in_heap);
|
||||
|
@ -130,7 +130,7 @@ struct render_target_traits
|
||||
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_download_command(
|
||||
gsl::not_null<ID3D12Resource*> rtt,
|
||||
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();
|
||||
@ -163,7 +163,7 @@ struct render_target_traits
|
||||
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_depth_download_command(
|
||||
gsl::not_null<ID3D12Resource*> ds,
|
||||
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();
|
||||
@ -196,7 +196,7 @@ struct render_target_traits
|
||||
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_stencil_download_command(
|
||||
gsl::not_null<ID3D12Resource*> stencil,
|
||||
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();
|
||||
@ -226,7 +226,7 @@ struct render_target_traits
|
||||
|
||||
static
|
||||
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 buffer_size;
|
||||
@ -243,7 +243,7 @@ struct render_target_traits
|
||||
|
||||
static
|
||||
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();
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace {
|
||||
void update_existing_texture(
|
||||
const rsx::texture &texture,
|
||||
ID3D12GraphicsCommandList *command_list,
|
||||
data_heap &texture_buffer_heap,
|
||||
d3d12_data_heap &texture_buffer_heap,
|
||||
ID3D12Resource *existing_texture)
|
||||
{
|
||||
size_t w = texture.width(), h = texture.height();
|
||||
@ -123,7 +123,7 @@ ComPtr<ID3D12Resource> upload_single_texture(
|
||||
const rsx::texture &texture,
|
||||
ID3D12Device *device,
|
||||
ID3D12GraphicsCommandList *command_list,
|
||||
data_heap &texture_buffer_heap)
|
||||
d3d12_data_heap &texture_buffer_heap)
|
||||
{
|
||||
ComPtr<ID3D12Resource> result;
|
||||
CHECK_HRESULT(device->CreateCommittedResource(
|
||||
|
@ -403,11 +403,11 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
|
||||
|
||||
#define RING_BUFFER_SIZE 16 * 1024 * 1024
|
||||
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.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.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);
|
||||
|
||||
@ -451,10 +451,10 @@ VKGSRender::~VKGSRender()
|
||||
//TODO: Properly destroy shader modules instead of calling clear...
|
||||
m_prog_buffer.clear();
|
||||
|
||||
m_index_buffer.release();
|
||||
m_uniform_buffer.release();
|
||||
m_attrib_buffers.release();
|
||||
m_texture_upload_buffer.release();
|
||||
m_index_buffer_ring_info.heap.release();
|
||||
m_uniform_buffer_ring_info.heap.release();
|
||||
m_attrib_ring_info.heap.release();
|
||||
m_texture_upload_buffer_ring_info.heap.release();
|
||||
null_buffer.release();
|
||||
null_buffer_view.release();
|
||||
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);
|
||||
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;
|
||||
VkSamplerMipmapMode mip_mode;
|
||||
@ -603,7 +603,7 @@ void VKGSRender::end()
|
||||
VkDeviceSize offset;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ void VKGSRender::on_init_thread()
|
||||
{
|
||||
GSRender::on_init_thread();
|
||||
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()
|
||||
@ -893,7 +893,7 @@ bool VKGSRender::load_program()
|
||||
//3. Update fragment constants
|
||||
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
|
||||
/**
|
||||
@ -926,22 +926,22 @@ bool VKGSRender::load_program()
|
||||
memset((char*)buf+64, 0, 8);
|
||||
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));
|
||||
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));
|
||||
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);
|
||||
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_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_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->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, scale_offset_offset, 256 }, SCALE_OFFSET_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_ring_info.heap->value, fragment_constants_offset, fragment_constants_sz }, FRAGMENT_CONSTANT_BUFFERS_BIND_SLOT, descriptor_sets);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ private:
|
||||
|
||||
rsx::surface_info m_surface;
|
||||
|
||||
vk::data_heap m_attrib_ring_info;
|
||||
std::unique_ptr<vk::buffer> m_attrib_buffers;
|
||||
vk::vk_data_heap m_attrib_ring_info;
|
||||
|
||||
vk::texture_cache m_texture_cache;
|
||||
rsx::vk_render_targets m_rtts;
|
||||
@ -45,12 +44,9 @@ private:
|
||||
vk::swap_chain* m_swap_chain;
|
||||
//buffer
|
||||
|
||||
vk::data_heap m_uniform_buffer_ring_info;
|
||||
std::unique_ptr<vk::buffer> m_uniform_buffer;
|
||||
vk::data_heap m_index_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;
|
||||
vk::vk_data_heap m_uniform_buffer_ring_info;
|
||||
vk::vk_data_heap m_index_buffer_ring_info;
|
||||
vk::vk_data_heap m_texture_upload_buffer_ring_info;
|
||||
|
||||
//Vulkan internals
|
||||
u32 m_current_present_image = 0xFFFF;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "VulkanAPI.h"
|
||||
#include "../GCM.h"
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "../Common/ring_buffer_helper.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
@ -1308,87 +1309,21 @@ namespace vk
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: factorize between backends
|
||||
class data_heap
|
||||
struct vk_data_heap : public data_heap
|
||||
{
|
||||
/**
|
||||
* Does alloc cross get position ?
|
||||
*/
|
||||
template<int Alignement>
|
||||
bool can_alloc(size_t size) const
|
||||
std::unique_ptr<vk::buffer> heap;
|
||||
|
||||
void* map(size_t offset, size_t size)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return heap->map(offset, size);
|
||||
}
|
||||
|
||||
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)
|
||||
void unmap()
|
||||
{
|
||||
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;
|
||||
heap->unmap();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allocate enough space in upload_buffer and write all mipmap/layer data into the subbuffer.
|
||||
* Then copy all layers into dst_image.
|
||||
@ -1396,5 +1331,5 @@ namespace vk
|
||||
*/
|
||||
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,
|
||||
vk::data_heap &upload_heap, vk::buffer* upload_buffer);
|
||||
vk::vk_data_heap &upload_heap, vk::buffer* upload_buffer);
|
||||
}
|
@ -130,7 +130,7 @@ namespace vk
|
||||
|
||||
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,
|
||||
vk::data_heap &upload_heap, vk::buffer* upload_buffer)
|
||||
vk::vk_data_heap &upload_heap, vk::buffer* upload_buffer)
|
||||
{
|
||||
u32 mipmap_level = 0;
|
||||
u32 block_in_pixel = get_format_block_size_in_texel(format);
|
||||
|
@ -149,7 +149,7 @@ namespace vk
|
||||
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 range = (u32)get_texture_size(tex);
|
||||
|
@ -218,18 +218,20 @@ namespace vk
|
||||
|
||||
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);
|
||||
void* buf = buffer->map(offset, size);
|
||||
gsl::span<gsl::byte> mapped_span = {reinterpret_cast<gsl::byte*>(buf), gsl::narrow<int>(size) };
|
||||
copy_function(mapped_span);
|
||||
buffer->unmap();
|
||||
return offset;
|
||||
}
|
||||
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)
|
||||
{
|
||||
size_t offset = data_heap_info.alloc<256>(size);
|
||||
void* buf = data_heap_info.map(offset, size);
|
||||
gsl::span<gsl::byte> mapped_span = { reinterpret_cast<gsl::byte*>(buf), gsl::narrow<int>(size) };
|
||||
copy_function(mapped_span);
|
||||
data_heap_info.unmap();
|
||||
return offset;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
std::tuple<VkPrimitiveTopology, bool, u32, VkDeviceSize, VkIndexType>
|
||||
VKGSRender::upload_vertex_data()
|
||||
{
|
||||
@ -341,9 +343,9 @@ VKGSRender::upload_vertex_data()
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -428,8 +430,8 @@ VKGSRender::upload_vertex_data()
|
||||
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;
|
||||
|
||||
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); });
|
||||
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));
|
||||
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_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);
|
||||
}
|
||||
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); });
|
||||
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));
|
||||
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_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);
|
||||
break;
|
||||
}
|
||||
@ -500,9 +502,9 @@ VKGSRender::upload_vertex_data()
|
||||
index_count = vk::expand_line_loop_array_to_strip(vertex_draw_count, indices);
|
||||
size_t upload_size = index_count * sizeof(u16);
|
||||
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);
|
||||
m_index_buffer->unmap();
|
||||
m_index_buffer_ring_info.heap->unmap();
|
||||
}
|
||||
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);
|
||||
size_t upload_size = index_count * sizeof(u32);
|
||||
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);
|
||||
m_index_buffer->unmap();
|
||||
m_index_buffer_ring_info.heap->unmap();
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
m_index_buffer->unmap();
|
||||
m_index_buffer_ring_info.heap->unmap();
|
||||
}
|
||||
|
||||
is_indexed_draw = true;
|
||||
@ -582,9 +584,9 @@ VKGSRender::upload_vertex_data()
|
||||
|
||||
size_t upload_size = vertex_index_array.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);
|
||||
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);
|
||||
|
@ -550,6 +550,7 @@
|
||||
<ClInclude Include="Emu\RSX\Common\BufferUtils.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.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\surface_store.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\TextureUtils.h" />
|
||||
|
@ -1776,10 +1776,13 @@
|
||||
<ClInclude Include="Emu\RSX\rsx_methods.h">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</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>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Common\surface_store.h">
|
||||
<ClInclude Include="Emu\RSX\Common\ring_buffer_helper.h">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user