rsx/common/d3d12/gl: Use span in vertex upload function.

This commit is contained in:
Vincent Lejeune 2016-02-20 00:50:20 +01:00
parent 79dc835378
commit 5a14644cd4
5 changed files with 90 additions and 66 deletions

View File

@ -5,6 +5,16 @@
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
namespace
{
// FIXME: GSL as_span break build if template parameter is non const with current revision.
// Replace with true as_span when fixed.
template <typename T>
gsl::span<T> as_span_workaround(gsl::span<gsl::byte> unformated_span)
{
return{ (T*)unformated_span.data(), gsl::narrow<int>(unformated_span.size_bytes() / sizeof(T)) };
}
}
namespace
{
@ -24,73 +34,64 @@ namespace
X = X << 5;
return{ X, Y, Z, 1 };
}
template<typename U, typename T>
void copy_whole_attribute_array(gsl::span<T> dst, const gsl::byte* src_ptr, u8 attribute_size, u8 dst_stride, u32 src_stride, u32 first, u32 vertex_count)
{
for (u32 vertex = 0; vertex < vertex_count; ++vertex)
{
const U* src = reinterpret_cast<const U*>(src_ptr + src_stride * (first + vertex));
for (u32 i = 0; i < attribute_size; ++i)
{
dst[vertex * dst_stride / sizeof(T) + i] = src[i];
}
}
}
}
// FIXME: these functions shouldn't access rsx::method_registers (global)
void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_t index, const rsx::data_array_format_info &vertex_array_desc)
void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, const gsl::byte *src_ptr, u32 first, u32 count, rsx::vertex_base_type type, u32 vector_element_count, u32 attribute_src_stride)
{
Expects(vertex_array_desc.size > 0);
Expects(vector_element_count > 0);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
u32 element_size = rsx::get_vertex_type_size_on_host(type, vector_element_count);
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_array_desc.type, vertex_array_desc.size);
u32 base_index = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
for (u32 i = 0; i < count; ++i)
switch (type)
{
auto src = vm::ps3::_ptr<const u8>(address + vertex_array_desc.stride * (first + i + base_index));
u8* dst = (u8*)buffer + i * element_size;
switch (vertex_array_desc.type)
case rsx::vertex_base_type::ub:
{
gsl::span<u8> dst_span = as_span_workaround<u8>(raw_dst_span);
copy_whole_attribute_array<u8>(dst_span, src_ptr, vector_element_count, element_size, attribute_src_stride, first, count);
return;
}
case rsx::vertex_base_type::s1:
case rsx::vertex_base_type::sf:
{
gsl::span<u16> dst_span = as_span_workaround<u16>(raw_dst_span);
copy_whole_attribute_array<be_t<u16>>(dst_span, src_ptr, vector_element_count, element_size, attribute_src_stride, first, count);
return;
}
case rsx::vertex_base_type::f:
case rsx::vertex_base_type::s32k:
case rsx::vertex_base_type::ub256:
{
gsl::span<u32> dst_span = as_span_workaround<u32>(raw_dst_span);
copy_whole_attribute_array<be_t<u32>>(dst_span, src_ptr, vector_element_count, element_size, attribute_src_stride, first, count);
return;
}
case rsx::vertex_base_type::cmp:
{
gsl::span<u16> dst_span = as_span_workaround<u16>(raw_dst_span);
for (u32 i = 0; i < count; ++i)
{
case rsx::vertex_base_type::ub:
memcpy(dst, src, vertex_array_desc.size);
break;
case rsx::vertex_base_type::s1:
case rsx::vertex_base_type::sf:
{
auto* c_src = (const be_t<u16>*)src;
u16* c_dst = (u16*)dst;
for (u32 j = 0; j < vertex_array_desc.size; ++j)
{
*c_dst++ = *c_src++;
}
if (vertex_array_desc.size * sizeof(u16) < element_size)
*c_dst++ = 0x3c00;
break;
}
case rsx::vertex_base_type::f:
case rsx::vertex_base_type::s32k:
case rsx::vertex_base_type::ub256:
{
auto* c_src = (const be_t<u32>*)src;
u32* c_dst = (u32*)dst;
for (u32 j = 0; j < vertex_array_desc.size; ++j)
{
*c_dst++ = *c_src++;
}
break;
}
case rsx::vertex_base_type::cmp:
{
auto* c_src = (const be_t<u32>*)src;
auto* c_src = (const be_t<u32>*)(src_ptr + attribute_src_stride * (first + i));
const auto& decoded_vector = decode_cmp_vector(*c_src);
u16* c_dst = (u16*)dst;
c_dst[0] = decoded_vector[0];
c_dst[1] = decoded_vector[1];
c_dst[2] = decoded_vector[2];
c_dst[3] = decoded_vector[3];
break;
}
dst_span[i * element_size / sizeof(u16)] = decoded_vector[0];
dst_span[i * element_size / sizeof(u16) + 1] = decoded_vector[1];
dst_span[i * element_size / sizeof(u16) + 2] = decoded_vector[2];
dst_span[i * element_size / sizeof(u16) + 3] = decoded_vector[3];
}
return;
}
}
}
@ -333,7 +334,7 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
}
// TODO: Unify indexed and non indexed primitive expansion ?
// FIXME: these functions shouldn't access rsx::method_registers (global)
template<typename T>
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{

View File

@ -4,9 +4,10 @@
#include "../RSXThread.h"
/**
* Write count vertex attributes from index array buffer starting at first, using vertex_array_desc
* Write count vertex attributes from src_ptr starting at first.
* src_ptr array layout is deduced from the type, vector element count and src_stride arguments.
*/
void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_t index, const rsx::data_array_format_info &vertex_array_desc);
void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, const gsl::byte *src_ptr, u32 first, u32 count, rsx::vertex_base_type type, u32 vector_element_count, u32 attribute_src_stride);
/*
* If primitive mode is not supported and need to be emulated (using an index buffer) returns false.

View File

@ -78,6 +78,7 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
u32 vertex_count = get_vertex_count(vertex_ranges);
size_t offset_in_vertex_buffers_buffer = 0;
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
@ -94,10 +95,16 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
UINT buffer_size = element_size * vertex_count;
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
for (const auto &range : vertex_ranges)
{
write_vertex_array_data_to_buffer(mapped_buffer, range.first, range.second, index, info);
gsl::span<gsl::byte> mapped_buffer_span = { (gsl::byte*)mapped_buffer, gsl::narrow_cast<int>(buffer_size) };
write_vertex_array_data_to_buffer(mapped_buffer_span, src_ptr, range.first, range.second, info.type, info.size, info.stride);
mapped_buffer = (char*)mapped_buffer + range.second * element_size;
}
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));

View File

@ -564,24 +564,33 @@ void GLGSRender::end()
{
auto &vertex_info = vertex_arrays_info[index];
// Active vertex array
std::vector<u8> vertex_array;
std::vector<gsl::byte> vertex_array;
// Fill vertex_array
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
vertex_array.resize(vertex_draw_count * element_size);
// Get source pointer
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
const gsl::byte *src_ptr = gsl::narrow_cast<const gsl::byte*>(vm::base(address));
if (draw_command == rsx::draw_command::array)
{
size_t offset = 0;
gsl::span<gsl::byte> dest_span(vertex_array);
for (const auto &first_count : first_count_commands)
{
write_vertex_array_data_to_buffer(vertex_array.data() + offset, first_count.first, first_count.second, index, vertex_info);
write_vertex_array_data_to_buffer(dest_span.subspan(offset), src_ptr, first_count.first, first_count.second, vertex_info.type, vertex_info.size, vertex_info.stride);
offset += first_count.second * element_size;
}
}
if (draw_command == rsx::draw_command::indexed)
{
vertex_array.resize((max_index + 1) * element_size);
write_vertex_array_data_to_buffer(vertex_array.data(), 0, max_index + 1, index, vertex_info);
gsl::span<gsl::byte> dest_span(vertex_array);
write_vertex_array_data_to_buffer(dest_span, src_ptr, 0, max_index + 1, vertex_info.type, vertex_info.size, vertex_info.stride);
}
size_t size = vertex_array.size();

View File

@ -83,7 +83,13 @@
<ClCompile Include="Emu\IdManager.cpp" />
<ClCompile Include="Emu\RSX\CgBinaryFragmentProgram.cpp" />
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp" />
<ClCompile Include="Emu\RSX\Common\BufferUtils.cpp" />
<ClCompile Include="Emu\RSX\Common\BufferUtils.cpp">
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</TreatWarningAsError>
<TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">true</TreatWarningAsError>
</ClCompile>
<ClCompile Include="Emu\RSX\Common\FragmentProgramDecompiler.cpp" />
<ClCompile Include="Emu\RSX\Common\ProgramStateCache.cpp" />
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />