mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-12 17:58:37 +12:00
Merge pull request #1383 from vlj/rsx
rsx/common/d3d12/gl: Use separate vertex array/vertex register states.
This commit is contained in:
commit
6811195345
5 changed files with 140 additions and 193 deletions
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
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(void *buffer, u32 first, u32 count, size_t index, const rsx::data_array_format_info &vertex_array_desc)
|
||||||
{
|
{
|
||||||
assert(vertex_array_desc.array);
|
assert(vertex_array_desc.size > 0);
|
||||||
|
|
||||||
if (vertex_array_desc.frequency > 1)
|
if (vertex_array_desc.frequency > 1)
|
||||||
LOG_ERROR(RSX, "%s: frequency is not null (%d, index=%d)", __FUNCTION__, vertex_array_desc.frequency, index);
|
LOG_ERROR(RSX, "%s: frequency is not null (%d, index=%d)", __FUNCTION__, vertex_array_desc.frequency, index);
|
||||||
|
|
|
@ -45,14 +45,19 @@ void D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u3
|
||||||
for (const auto &pair : vertex_ranges)
|
for (const auto &pair : vertex_ranges)
|
||||||
vertex_count += pair.second;
|
vertex_count += pair.second;
|
||||||
|
|
||||||
// First array attribute
|
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
|
||||||
|
|
||||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||||
{
|
{
|
||||||
const auto &info = vertex_arrays_info[index];
|
bool enabled = !!(input_mask & (1 << index));
|
||||||
|
if (!enabled)
|
||||||
if (!info.array) // disabled or not a vertex array
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (vertex_arrays_info[index].size > 0)
|
||||||
|
{
|
||||||
|
// Active vertex array
|
||||||
|
const rsx::data_array_format_info &info = vertex_arrays_info[index];
|
||||||
|
|
||||||
u32 type_size = rsx::get_vertex_type_size(info.type);
|
u32 type_size = rsx::get_vertex_type_size(info.type);
|
||||||
u32 element_size = type_size * info.size;
|
u32 element_size = type_size * info.size;
|
||||||
|
|
||||||
|
@ -90,18 +95,12 @@ void D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u3
|
||||||
IAElement.InstanceDataStepRate = 0;
|
IAElement.InstanceDataStepRate = 0;
|
||||||
m_IASet.push_back(IAElement);
|
m_IASet.push_back(IAElement);
|
||||||
}
|
}
|
||||||
|
else if (register_vertex_info[index].size > 0)
|
||||||
// Now immediate vertex buffer
|
|
||||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
|
||||||
{
|
{
|
||||||
const auto &info = vertex_arrays_info[index];
|
// In register vertex attribute
|
||||||
|
const rsx::data_array_format_info &info = register_vertex_info[index];
|
||||||
|
|
||||||
if (info.array)
|
const std::vector<u8> &data = register_vertex_data[index];
|
||||||
continue;
|
|
||||||
if (!info.size) // disabled
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto &data = vertex_arrays[index];
|
|
||||||
|
|
||||||
u32 type_size = rsx::get_vertex_type_size(info.type);
|
u32 type_size = rsx::get_vertex_type_size(info.type);
|
||||||
u32 element_size = type_size * info.size;
|
u32 element_size = type_size * info.size;
|
||||||
|
@ -134,6 +133,7 @@ void D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u3
|
||||||
m_IASet.push_back(IAElement);
|
m_IASet.push_back(IAElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void D3D12GSRender::load_vertex_index_data(u32 first, u32 count)
|
void D3D12GSRender::load_vertex_index_data(u32 first, u32 count)
|
||||||
{
|
{
|
||||||
|
|
|
@ -366,13 +366,34 @@ void GLGSRender::end()
|
||||||
std::vector<u8> vertex_arrays_data;
|
std::vector<u8> vertex_arrays_data;
|
||||||
size_t vertex_arrays_offsets[rsx::limits::vertex_count];
|
size_t vertex_arrays_offsets[rsx::limits::vertex_count];
|
||||||
|
|
||||||
#if DUMP_VERTEX_DATA
|
const std::string reg_table[] =
|
||||||
fs::file dump(fs::get_config_dir() + "VertexDataArray.dump", fom::rewrite);
|
{
|
||||||
Emu.Pause();
|
"in_pos", "in_weight", "in_normal",
|
||||||
#endif
|
"in_diff_color", "in_spec_color",
|
||||||
|
"in_fog",
|
||||||
|
"in_point_size", "in_7",
|
||||||
|
"in_tc0", "in_tc1", "in_tc2", "in_tc3",
|
||||||
|
"in_tc4", "in_tc5", "in_tc6", "in_tc7"
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
|
||||||
|
m_vao.bind();
|
||||||
|
|
||||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||||
{
|
{
|
||||||
|
bool enabled = !!(input_mask & (1 << index));
|
||||||
|
if (!enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int location;
|
||||||
|
if (!m_program->attribs.has_location(reg_table[index], &location))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (vertex_arrays_info[index].size > 0)
|
||||||
|
{
|
||||||
|
auto &vertex_info = vertex_arrays_info[index];
|
||||||
|
// Active vertex array
|
||||||
|
|
||||||
size_t position = vertex_arrays_data.size();
|
size_t position = vertex_arrays_data.size();
|
||||||
vertex_arrays_offsets[index] = position;
|
vertex_arrays_offsets[index] = position;
|
||||||
|
|
||||||
|
@ -384,115 +405,19 @@ void GLGSRender::end()
|
||||||
|
|
||||||
memcpy(vertex_arrays_data.data() + position, vertex_arrays[index].data(), size);
|
memcpy(vertex_arrays_data.data() + position, vertex_arrays[index].data(), size);
|
||||||
|
|
||||||
#if DUMP_VERTEX_DATA
|
|
||||||
auto &vertex_info = vertex_arrays_info[index];
|
|
||||||
dump.write(fmt::format("VertexData[%d]:\n", index));
|
|
||||||
switch (vertex_info.type)
|
|
||||||
{
|
|
||||||
case CELL_GCM_VERTEX_S1:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); j += 2)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%d\n", *(u16*)&vertex_arrays[index][j]));
|
|
||||||
if (!(((j + 2) / 2) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CELL_GCM_VERTEX_F:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); j += 4)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%.01f\n", *(float*)&vertex_arrays[index][j]));
|
|
||||||
if (!(((j + 4) / 4) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CELL_GCM_VERTEX_SF:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); j += 2)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%.01f\n", *(float*)&vertex_arrays[index][j]));
|
|
||||||
if (!(((j + 2) / 2) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CELL_GCM_VERTEX_UB:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); ++j)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%d\n", vertex_arrays[index][j]));
|
|
||||||
if (!((j + 1) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CELL_GCM_VERTEX_S32K:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); j += 2)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%d\n", *(u16*)&vertex_arrays[index][j]));
|
|
||||||
if (!(((j + 2) / 2) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// case CELL_GCM_VERTEX_CMP:
|
|
||||||
|
|
||||||
case CELL_GCM_VERTEX_UB256:
|
|
||||||
for (u32 j = 0; j < vertex_arrays[index].size(); ++j)
|
|
||||||
{
|
|
||||||
dump.write(fmt::format("%d\n", vertex_arrays[index][j]));
|
|
||||||
if (!((j + 1) % vertex_info.size)) dump.write("\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dump.write("\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vbo.data(vertex_arrays_data.size(), vertex_arrays_data.data());
|
|
||||||
m_vao.bind();
|
|
||||||
|
|
||||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
|
||||||
{
|
|
||||||
auto &vertex_info = vertex_arrays_info[index];
|
|
||||||
|
|
||||||
if (!vertex_info.size)
|
|
||||||
{
|
|
||||||
//disabled
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertex_info.type < 1 || vertex_info.type > 7)
|
|
||||||
{
|
|
||||||
LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", vertex_info.type);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string reg_table[] =
|
|
||||||
{
|
|
||||||
"in_pos", "in_weight", "in_normal",
|
|
||||||
"in_diff_color", "in_spec_color",
|
|
||||||
"in_fog",
|
|
||||||
"in_point_size", "in_7",
|
|
||||||
"in_tc0", "in_tc1", "in_tc2", "in_tc3",
|
|
||||||
"in_tc4", "in_tc5", "in_tc6", "in_tc7"
|
|
||||||
};
|
|
||||||
|
|
||||||
int location;
|
|
||||||
|
|
||||||
//TODO: use attrib input mask register
|
|
||||||
if (!m_program->attribs.has_location(reg_table[index], &location))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (vertex_info.array)
|
|
||||||
{
|
|
||||||
__glcheck m_program->attribs[location] =
|
__glcheck m_program->attribs[location] =
|
||||||
(m_vao + vertex_arrays_offsets[index])
|
(m_vao + vertex_arrays_offsets[index])
|
||||||
.config(gl_types[vertex_info.type], vertex_info.size, gl_normalized[vertex_info.type]);
|
.config(gl_types[vertex_info.type], vertex_info.size, gl_normalized[vertex_info.type]);
|
||||||
}
|
}
|
||||||
else
|
else if (register_vertex_info[index].size > 0)
|
||||||
{
|
{
|
||||||
auto &vertex_data = vertex_arrays[index];
|
auto &vertex_data = register_vertex_data[index];
|
||||||
|
auto &vertex_info = register_vertex_info[index];
|
||||||
|
|
||||||
switch (vertex_info.type)
|
switch (vertex_info.type)
|
||||||
{
|
{
|
||||||
case CELL_GCM_VERTEX_F:
|
case CELL_GCM_VERTEX_F:
|
||||||
switch (vertex_info.size)
|
switch (register_vertex_info[index].size)
|
||||||
{
|
{
|
||||||
case 1: apply_attrib_array<f32, 1>(*m_program, location, vertex_data); break;
|
case 1: apply_attrib_array<f32, 1>(*m_program, location, vertex_data); break;
|
||||||
case 2: apply_attrib_array<f32, 2>(*m_program, location, vertex_data); break;
|
case 2: apply_attrib_array<f32, 2>(*m_program, location, vertex_data); break;
|
||||||
|
@ -507,6 +432,8 @@ void GLGSRender::end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_vbo.data(vertex_arrays_data.size(), vertex_arrays_data.data());
|
||||||
|
|
||||||
|
|
||||||
if (vertex_index_array.empty())
|
if (vertex_index_array.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,20 +82,19 @@ namespace rsx
|
||||||
static const size_t element_size = (count * sizeof(type));
|
static const size_t element_size = (count * sizeof(type));
|
||||||
static const size_t element_size_in_words = element_size / sizeof(u32);
|
static const size_t element_size_in_words = element_size / sizeof(u32);
|
||||||
|
|
||||||
auto& info = rsx->vertex_arrays_info[index];
|
auto& info = rsx->register_vertex_info[index];
|
||||||
|
|
||||||
info.type = vertex_data_type_from_element_type<type>::type;
|
info.type = vertex_data_type_from_element_type<type>::type;
|
||||||
info.size = count;
|
info.size = count;
|
||||||
info.frequency = 0;
|
info.frequency = 0;
|
||||||
info.stride = 0;
|
info.stride = 0;
|
||||||
info.array = false;
|
|
||||||
|
|
||||||
auto& entry = rsx->vertex_arrays[index];
|
auto& entry = rsx->register_vertex_data[index];
|
||||||
|
|
||||||
//find begin of data
|
//find begin of data
|
||||||
size_t begin = id + index * element_size_in_words;
|
size_t begin = id + index * element_size_in_words;
|
||||||
|
|
||||||
size_t position = entry.size();
|
size_t position = 0;//entry.size();
|
||||||
entry.resize(position + element_size);
|
entry.resize(position + element_size);
|
||||||
|
|
||||||
memcpy(entry.data() + position, method_registers + begin, element_size);
|
memcpy(entry.data() + position, method_registers + begin, element_size);
|
||||||
|
@ -170,8 +169,7 @@ namespace rsx
|
||||||
force_inline static void impl(thread* rsx, u32 arg)
|
force_inline static void impl(thread* rsx, u32 arg)
|
||||||
{
|
{
|
||||||
auto& info = rsx->vertex_arrays_info[index];
|
auto& info = rsx->vertex_arrays_info[index];
|
||||||
info.unpack(arg);
|
info.unpack_array(arg);
|
||||||
info.array = info.size > 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -237,7 +235,7 @@ namespace rsx
|
||||||
|
|
||||||
for (int i = 0; i < rsx::limits::vertex_count; ++i)
|
for (int i = 0; i < rsx::limits::vertex_count; ++i)
|
||||||
{
|
{
|
||||||
if (rsx->vertex_arrays_info[i].array)
|
if (rsx->vertex_arrays_info[i].size > 0)
|
||||||
{
|
{
|
||||||
has_array = true;
|
has_array = true;
|
||||||
break;
|
break;
|
||||||
|
@ -250,11 +248,11 @@ namespace rsx
|
||||||
|
|
||||||
for (int i = 0; i < rsx::limits::vertex_count; ++i)
|
for (int i = 0; i < rsx::limits::vertex_count; ++i)
|
||||||
{
|
{
|
||||||
if (!rsx->vertex_arrays_info[i].size)
|
if (!rsx->register_vertex_info[i].size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 count = u32(rsx->vertex_arrays[i].size()) /
|
u32 count = u32(rsx->register_vertex_data[i].size()) /
|
||||||
rsx::get_vertex_type_size(rsx->vertex_arrays_info[i].type) * rsx->vertex_arrays_info[i].size;
|
rsx::get_vertex_type_size(rsx->register_vertex_info[i].type) * rsx->register_vertex_info[i].size;
|
||||||
|
|
||||||
if (count < min_count)
|
if (count < min_count)
|
||||||
min_count = count;
|
min_count = count;
|
||||||
|
@ -933,7 +931,7 @@ namespace rsx
|
||||||
{
|
{
|
||||||
const auto &info = vertex_arrays_info[index];
|
const auto &info = vertex_arrays_info[index];
|
||||||
|
|
||||||
if (!info.array) // disabled or not a vertex array
|
if (info.size == 0) // disabled
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto &data = vertex_arrays[index];
|
auto &data = vertex_arrays[index];
|
||||||
|
@ -1270,6 +1268,10 @@ namespace rsx
|
||||||
|
|
||||||
method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff;
|
method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff;
|
||||||
|
|
||||||
|
// Reset vertex attrib array
|
||||||
|
for (int i = 0; i < limits::vertex_count; i++)
|
||||||
|
vertex_arrays_info[i].size = 0;
|
||||||
|
|
||||||
// Construct Textures
|
// Construct Textures
|
||||||
for (int i = 0; i < limits::textures_count; i++)
|
for (int i = 0; i < limits::textures_count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -334,9 +334,8 @@ namespace rsx
|
||||||
u8 stride = 0;
|
u8 stride = 0;
|
||||||
u8 size = 0;
|
u8 size = 0;
|
||||||
u8 type = CELL_GCM_VERTEX_F;
|
u8 type = CELL_GCM_VERTEX_F;
|
||||||
bool array = false;
|
|
||||||
|
|
||||||
void unpack(u32 data_array_format)
|
void unpack_array(u32 data_array_format)
|
||||||
{
|
{
|
||||||
frequency = data_array_format >> 16;
|
frequency = data_array_format >> 16;
|
||||||
stride = (data_array_format >> 8) & 0xff;
|
stride = (data_array_format >> 8) & 0xff;
|
||||||
|
@ -363,6 +362,25 @@ namespace rsx
|
||||||
rsx::texture textures[limits::textures_count];
|
rsx::texture textures[limits::textures_count];
|
||||||
rsx::vertex_texture vertex_textures[limits::vertex_textures_count];
|
rsx::vertex_texture vertex_textures[limits::vertex_textures_count];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSX can sources vertex attributes from 2 places:
|
||||||
|
* - Immediate values passed by NV4097_SET_VERTEX_DATA*_M + ARRAY_ID write.
|
||||||
|
* For a given ARRAY_ID the last command of this type defines the actual type of the immediate value.
|
||||||
|
* Since there can be only a single value per ARRAY_ID passed this way, all vertex in the draw call
|
||||||
|
* shares it.
|
||||||
|
* - Vertex array values passed by offset/stride/size/format description.
|
||||||
|
*
|
||||||
|
* A given ARRAY_ID can have both an immediate value and a vertex array enabled at the same time
|
||||||
|
* (See After Burner Climax intro cutscene). In such case the vertex array has precedence over the
|
||||||
|
* immediate value. As soon as the vertex array is disabled (size set to 0) the immediate value
|
||||||
|
* must be used if the vertex attrib mask request it.
|
||||||
|
*
|
||||||
|
* Note that behavior when both vertex array and immediate value system are disabled but vertex attrib mask
|
||||||
|
* request inputs is unknow.
|
||||||
|
*/
|
||||||
|
data_array_format_info register_vertex_info[limits::vertex_count];
|
||||||
|
std::vector<u8> register_vertex_data[limits::vertex_count];
|
||||||
data_array_format_info vertex_arrays_info[limits::vertex_count];
|
data_array_format_info vertex_arrays_info[limits::vertex_count];
|
||||||
std::vector<u8> vertex_arrays[limits::vertex_count];
|
std::vector<u8> vertex_arrays[limits::vertex_count];
|
||||||
std::vector<u8> vertex_index_array;
|
std::vector<u8> vertex_index_array;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue