rsx: Use register_decoder for vertex attributes.

This commit is contained in:
Vincent Lejeune 2016-07-13 18:18:10 +02:00
parent cc30e1aa47
commit e9bee80f4b
8 changed files with 234 additions and 166 deletions

View File

@ -59,6 +59,19 @@ namespace
return vertex_buffer_view;
}
D3D12_SHADER_RESOURCE_VIEW_DESC get_vertex_attribute_srv(const rsx::vertex_base_type type, u8 size, UINT64 offset_in_vertex_buffers_buffer, UINT buffer_size)
{
u32 element_size = rsx::get_vertex_type_size_on_host(type, size);
D3D12_SHADER_RESOURCE_VIEW_DESC vertex_buffer_view = {
get_vertex_attribute_format(type, size),
D3D12_SRV_DIMENSION_BUFFER,
get_component_mapping_from_vector_size(size)
};
vertex_buffer_view.Buffer.FirstElement = offset_in_vertex_buffers_buffer / element_size;
vertex_buffer_view.Buffer.NumElements = buffer_size / element_size;
return vertex_buffer_view;
}
template<int N>
UINT64 get_next_multiple_of(UINT64 val)
{
@ -120,20 +133,19 @@ std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attrib
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
// In register vertex attribute
const rsx::data_array_format_info &info = rsx::method_registers.register_vertex_info[index];
const std::vector<u8> &data = rsx::method_registers.register_vertex_data[index];
const rsx::register_vertex_data_info &info = rsx::method_registers.register_vertex_info[index];
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = gsl::narrow<UINT>(data.size());
UINT buffer_size = element_size;
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
memcpy(mapped_buffer, data.data(), data.size());
memcpy(mapped_buffer, info.data.data(), buffer_size);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
command_list->CopyBufferRegion(m_vertex_buffer_data.Get(), offset_in_vertex_buffers_buffer, m_buffer_data.get_heap(), heap_offset, buffer_size);
vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info, offset_in_vertex_buffers_buffer, buffer_size));
vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info.type, info.size, offset_in_vertex_buffers_buffer, buffer_size));
offset_in_vertex_buffers_buffer = get_next_multiple_of<48>(offset_in_vertex_buffers_buffer + buffer_size); // 48 is multiple of 2, 4, 6, 8, 12, 16
}
}

View File

@ -388,7 +388,6 @@ u32 GLGSRender::set_vertex_buffer()
}
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
auto &vertex_info = rsx::method_registers.register_vertex_info[index];
switch (vertex_info.type)
@ -397,14 +396,14 @@ u32 GLGSRender::set_vertex_buffer()
{
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
const size_t data_size = vertex_data.size();
const size_t data_size = element_size;
auto &texture = m_gl_attrib_buffers[index];
auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment);
u8 *dst = static_cast<u8*>(mapping.first);
memcpy(dst, vertex_data.data(), data_size);
memcpy(dst, vertex_info.data.data(), element_size);
texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size);
//Link texture to uniform

View File

@ -354,7 +354,6 @@ namespace rsx
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
rsx::method_registers.register_vertex_info[index].size = 0;
rsx::method_registers.register_vertex_data[index].clear();
}
if (capture_current_frame)

View File

@ -508,18 +508,17 @@ VKGSRender::upload_vertex_data()
else if (rsx::method_registers.register_vertex_info[index].size > 0)
{
//Untested!
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
auto &vertex_info = rsx::method_registers.register_vertex_info[index];
switch (vertex_info.type)
{
case rsx::vertex_base_type::f:
{
size_t data_size = vertex_data.size();
size_t data_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size);
u32 offset_in_attrib_buffer = 0;
void *data_ptr = vertex_data.data();
void *data_ptr = vertex_info.data.data();
if (vk::requires_component_expansion(vertex_info.type, vertex_info.size))
{
@ -530,14 +529,14 @@ VKGSRender::upload_vertex_data()
offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size);
void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size);
vk::expand_array_components<float, 3, 4, 1>(reinterpret_cast<float*>(vertex_data.data()), dst, num_stored_verts);
vk::expand_array_components<float, 3, 4, 1>(reinterpret_cast<float*>(vertex_info.data.data()), dst, num_stored_verts);
m_attrib_ring_info.unmap();
}
else
{
offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size);
void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size);
memcpy(dst, vertex_data.data(), data_size);
memcpy(dst, vertex_info.data.data(), data_size);
m_attrib_ring_info.unmap();
}

View File

@ -85,6 +85,21 @@ namespace
subreg == 2 ? "z" :
"w";
}
std::string print_vertex_attribute_format(rsx::vertex_base_type type)
{
switch (type)
{
case rsx::vertex_base_type::s1: return "Signed short normalized";
case rsx::vertex_base_type::f: return "Float";
case rsx::vertex_base_type::sf: return "Half float";
case rsx::vertex_base_type::ub: return "Unsigned byte normalized";
case rsx::vertex_base_type::s32k: return "Signed short unormalized";
case rsx::vertex_base_type::cmp: return "CMP";
case rsx::vertex_base_type::ub256: return "Unsigned byte unormalized";
}
throw;
}
}
namespace rsx
@ -2318,6 +2333,172 @@ struct registers_decoder<NV4097_SET_TRANSFORM_PROGRAM_LOAD>
#define DECLARE_TRANSFORM_PROGRAM(index) NV4097_SET_TRANSFORM_PROGRAM + index,
EXPAND_RANGE_512(0, TRANSFORM_PROGRAM)
template<u32 index>
struct vertex_array_helper
{
static auto decode(u32 value)
{
u16 frequency = value >> 16;
u8 stride = (value >> 8) & 0xff;
u8 size = (value >> 4) & 0xf;
rsx::vertex_base_type type = rsx::to_vertex_base_type(value & 0xf);
return std::make_tuple(frequency, stride, size, type);
}
static void commit_rsx_state(rsx::rsx_state &state, std::tuple<u16, u8, u8, rsx::vertex_base_type> &&decoded_values)
{
state.vertex_arrays_info[index].frequency = std::get<0>(decoded_values);
state.vertex_arrays_info[index].stride = std::get<1>(decoded_values);
state.vertex_arrays_info[index].size = std::get<2>(decoded_values);
state.vertex_arrays_info[index].type = std::get<3>(decoded_values);
}
static std::string dump(std::tuple<u16, u8, u8, rsx::vertex_base_type> &&decoded_values)
{
if (std::get<2>(decoded_values) == 0)
return "(disabled)";
return "Vertex array " + std::to_string(index) + ": Type = " + print_vertex_attribute_format(std::get<3>(decoded_values)) +
" size = " + std::to_string(std::get<2>(decoded_values)) +
" stride = " + std::to_string(std::get<1>(decoded_values)) +
" frequency = " + std::to_string(std::get<0>(decoded_values));
}
};
#define VERTEX_DATA_ARRAY_FORMAT(index) template<> struct registers_decoder<NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + index> : public vertex_array_helper<index> {};
#define DECLARE_VERTEX_DATA_ARRAY_FORMAT(index) NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + index,
EXPAND_RANGE_16(0, VERTEX_DATA_ARRAY_FORMAT)
template<u32 index>
struct vertex_array_offset_helper
{
static auto decode(u32 value)
{
return value;
}
static void commit_rsx_state(rsx::rsx_state &state, u32 &&decoded_values)
{
state.vertex_arrays_info[index].m_offset = decoded_values;
}
static std::string dump(u32 &&decoded_values)
{
return "Vertex array " + std::to_string(index) + ": Offset = " + std::to_string(decoded_values);
}
};
#define VERTEX_DATA_ARRAY_OFFSET(index) template<> struct registers_decoder<NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index> : public vertex_array_offset_helper<index> {};
#define DECLARE_VERTEX_DATA_ARRAY_OFFSET(index) NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index,
EXPAND_RANGE_16(0, VERTEX_DATA_ARRAY_OFFSET)
template<typename Type> struct vertex_data_type_from_element_type;
template<> struct vertex_data_type_from_element_type<float> { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::f; };
template<> struct vertex_data_type_from_element_type<f16> { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::sf; };
template<> struct vertex_data_type_from_element_type<u8> { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::ub; };
template<> struct vertex_data_type_from_element_type<u16> { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::s1; };
template<typename type, int count>
struct vertex_type_namer;
template<int count>
struct vertex_type_namer<f32, count>
{
static std::string get()
{
return "float" + std::to_string(count);
}
};
template<int count>
struct vertex_type_namer<u16, count>
{
static std::string get()
{
return "short" + std::to_string(count);
}
};
template<>
struct vertex_type_namer<u8, 4>
{
static std::string get()
{
return "uchar4";
}
};
template<u32 index, typename type, int count>
struct register_vertex_helper
{
static auto decode(u32 value)
{
return value;
}
static const size_t increment_per_array_index = (count * sizeof(type)) / sizeof(u32);
static const size_t attribute_index = index / increment_per_array_index;
static const size_t vertex_subreg = index % increment_per_array_index;
static void commit_rsx_state(rsx::rsx_state &state, u32 &&decoded_values)
{
auto& info = state.register_vertex_info[attribute_index];
info.type = vertex_data_type_from_element_type<type>::type;
info.size = count;
info.frequency = 0;
info.stride = 0;
state.register_vertex_info[attribute_index].data[vertex_subreg] = decoded_values;
}
static std::string dump(u32&& decoded_values)
{
return "register vertex " + std::to_string(attribute_index) + " as " + vertex_type_namer<type, count>::get() + ": " +
std::to_string(decoded_values);
}
};
#define VERTEX_DATA4UB(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA4UB_M + index> : public register_vertex_helper<index, u8, 4> {};
#define VERTEX_DATA1F(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA1F_M + index> : public register_vertex_helper<index, f32, 1> {};
#define VERTEX_DATA2F(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA2F_M + index> : public register_vertex_helper<index, f32, 2> {};
#define VERTEX_DATA3F(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA3F_M + index> : public register_vertex_helper<index, f32, 3> {};
#define VERTEX_DATA4F(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA4F_M + index> : public register_vertex_helper<index, f32, 4> {};
#define VERTEX_DATA2S(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA2S_M + index> : public register_vertex_helper<index, u16, 2> {};
#define VERTEX_DATA4S(index) \
template<> struct registers_decoder<NV4097_SET_VERTEX_DATA4S_M + index> : public register_vertex_helper<index, u16, 4> {};
#define DECLARE_VERTEX_DATA4UB(index) \
NV4097_SET_VERTEX_DATA4UB_M + index,
#define DECLARE_VERTEX_DATA1F(index) \
NV4097_SET_VERTEX_DATA1F_M + index,
#define DECLARE_VERTEX_DATA2F(index) \
NV4097_SET_VERTEX_DATA2F_M + index,
#define DECLARE_VERTEX_DATA3F(index) \
NV4097_SET_VERTEX_DATA3F_M + index,
#define DECLARE_VERTEX_DATA4F(index) \
NV4097_SET_VERTEX_DATA4F_M + index,
#define DECLARE_VERTEX_DATA2S(index) \
NV4097_SET_VERTEX_DATA2S_M + index,
#define DECLARE_VERTEX_DATA4S(index) \
NV4097_SET_VERTEX_DATA4S_M + index,
EXPAND_RANGE_16(0, VERTEX_DATA4UB)
EXPAND_RANGE_16(0, VERTEX_DATA1F)
EXPAND_RANGE_16(0, VERTEX_DATA2F)
EXPAND_RANGE_16(0, VERTEX_DATA3F)
EXPAND_RANGE_16(0, VERTEX_DATA4F)
EXPAND_RANGE_16(0, VERTEX_DATA2S)
EXPAND_RANGE_16(0, VERTEX_DATA4S)
constexpr std::integer_sequence<u32,
NV4097_SET_VIEWPORT_HORIZONTAL,
NV4097_SET_VIEWPORT_VERTICAL,
@ -2463,10 +2644,18 @@ constexpr std::integer_sequence<u32,
NV4097_SET_ANTI_ALIASING_CONTROL,
NV4097_SET_FRONT_POLYGON_MODE,
NV4097_SET_BACK_POLYGON_MODE,
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_FORMAT)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA_ARRAY_OFFSET)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA4UB)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA1F)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA2F)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA3F)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA4F)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA2S)
EXPAND_RANGE_16(0, DECLARE_VERTEX_DATA4S)
EXPAND_RANGE_32(0, DECLARE_TRANSFORM_CONSTANT)
NV4097_SET_TRANSFORM_CONSTANT_LOAD,
EXPAND_RANGE_512(0, DECLARE_TRANSFORM_PROGRAM)
NV4097_SET_TRANSFORM_PROGRAM_LOAD
> opcode_list{};
} // end namespace rsx

View File

@ -26,12 +26,6 @@ namespace rsx
rsx_state method_registers;
rsx_method_t methods[0x10000 >> 2]{};
template<typename Type> struct vertex_data_type_from_element_type;
template<> struct vertex_data_type_from_element_type<float> { static const vertex_base_type type = vertex_base_type::f; };
template<> struct vertex_data_type_from_element_type<f16> { static const vertex_base_type type = vertex_base_type::sf; };
template<> struct vertex_data_type_from_element_type<u8> { static const vertex_base_type type = vertex_base_type::ub; };
template<> struct vertex_data_type_from_element_type<u16> { static const vertex_base_type type = vertex_base_type::s1; };
namespace nv406e
{
force_inline void set_reference(thread* rsx, u32 arg)
@ -73,104 +67,6 @@ namespace rsx
(arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff));
}
//fire only when all data passed to rsx cmd buffer
template<u32 id, u32 index, int count, typename type>
force_inline void set_vertex_data_impl(thread* rsx, u32 arg)
{
static const size_t element_size = (count * sizeof(type));
static const size_t element_size_in_words = element_size / sizeof(u32);
auto& info = rsx::method_registers.register_vertex_info[index];
info.type = vertex_data_type_from_element_type<type>::type;
info.size = count;
info.frequency = 0;
info.stride = 0;
auto& entry = rsx::method_registers.register_vertex_data[index];
//find begin of data
size_t begin = id + index * element_size_in_words;
size_t position = entry.size();
entry.resize(position + element_size);
memcpy(entry.data() + position, &method_registers[begin], element_size);
}
template<u32 index>
struct set_vertex_data4ub_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4UB_M, index, 4, u8>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data1f_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 1, f32>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data2f_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2F_M, index, 2, f32>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data3f_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA3F_M, index, 3, f32>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data4f_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4F_M, index, 4, f32>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data2s_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2S_M, index, 2, u16>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data4s_m
{
force_inline static void impl(thread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4S_M, index, 4, u16>(rsx, arg);
}
};
template<u32 index>
struct set_vertex_data_array_format
{
force_inline static void impl(thread* rsx, u32 arg)
{
auto& info = rsx::method_registers.vertex_arrays_info[index];
info.unpack_array(arg);
}
};
force_inline void draw_arrays(thread* rsx, u32 arg)
{
rsx->draw_command = rsx::draw_command::array;
@ -221,10 +117,8 @@ namespace rsx
if (vertex_info.size > 0)
{
auto &vertex_data = rsx::method_registers.register_vertex_data[index];
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
u32 element_count = vertex_data.size() / element_size;
u32 element_count = vertex_info.size;
vertex_info.frequency = element_count;
@ -763,9 +657,7 @@ namespace rsx
rsx_state::rsx_state() :
fragment_textures(fill_array<texture>(registers, std::make_index_sequence<16>())),
vertex_textures(fill_array<vertex_texture>(registers, std::make_index_sequence<4>())),
register_vertex_info(fill_array<data_array_format_info>(registers, std::make_index_sequence<16>())),
vertex_arrays_info(fill_array<data_array_format_info>(registers, std::make_index_sequence<16>()))
vertex_textures(fill_array<vertex_texture>(registers, std::make_index_sequence<4>()))
{
}
@ -1033,14 +925,6 @@ namespace
bind<NV4097_DRAW_ARRAYS, nv4097::draw_arrays>();
bind<NV4097_DRAW_INDEX_ARRAY, nv4097::draw_index_array>();
bind<NV4097_INLINE_ARRAY, nv4097::draw_inline_array>();
bind_range<NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 1, 16, nv4097::set_vertex_data_array_format>();
bind_range<NV4097_SET_VERTEX_DATA4UB_M, 1, 16, nv4097::set_vertex_data4ub_m>();
bind_range<NV4097_SET_VERTEX_DATA1F_M, 1, 16, nv4097::set_vertex_data1f_m>();
bind_range<NV4097_SET_VERTEX_DATA2F_M + 1, 2, 16, nv4097::set_vertex_data2f_m>();
bind_range<NV4097_SET_VERTEX_DATA3F_M + 2, 3, 16, nv4097::set_vertex_data3f_m>();
bind_range<NV4097_SET_VERTEX_DATA4F_M + 3, 4, 16, nv4097::set_vertex_data4f_m>();
bind_range<NV4097_SET_VERTEX_DATA2S_M, 1, 16, nv4097::set_vertex_data2s_m>();
bind_range<NV4097_SET_VERTEX_DATA4S_M + 1, 2, 16, nv4097::set_vertex_data4s_m>();
bind_range<NV4097_SET_TRANSFORM_CONSTANT, 1, 32, nv4097::set_transform_constant>();
bind_cpu_only<NV4097_GET_REPORT, nv4097::get_report>();
bind_cpu_only<NV4097_CLEAR_REPORT_VALUE, nv4097::clear_report_value>();

View File

@ -101,23 +101,12 @@ namespace rsx
* Note that behavior when both vertex array and immediate value system are disabled but vertex attrib mask
* request inputs is unknown.
*/
std::array<data_array_format_info, 16> register_vertex_info;
std::array<std::vector<u8>, 16> register_vertex_data;
std::array<register_vertex_data_info, 16> register_vertex_info;
std::array<data_array_format_info, 16> vertex_arrays_info;
rsx_state();
~rsx_state();
u32& operator[](size_t idx)
{
return registers[idx];
}
const u32& operator[](size_t idx) const
{
return registers[idx];
}
void decode(u32 reg, u32 value);
void reset();

View File

@ -8,33 +8,30 @@ namespace rsx
struct data_array_format_info
{
private:
u8 index;
std::array<u32, 0x10000 / 4> &registers;
public:
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
vertex_base_type type = vertex_base_type::f;
u32 m_offset;
data_array_format_info() {}
u32 offset() const
{
return m_offset;
}
};
struct register_vertex_data_info
{
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
vertex_base_type type = vertex_base_type::f;
register_vertex_data_info() {}
std::array<u32, 4> data;
data_array_format_info(u8 idx, std::array<u32, 0x10000 / 4> &r) : index(idx), registers(r)
{}
data_array_format_info() = delete;
void unpack_array(u32 data_array_format)
{
frequency = data_array_format >> 16;
stride = (data_array_format >> 8) & 0xff;
size = (data_array_format >> 4) & 0xf;
type = to_vertex_base_type(data_array_format & 0xf);
}
u32 offset() const
{
return registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
}
};
}