rsx/common/d3d12/gl: Support for CMP/non pow of 2 size vertex formats.

Also use class enum for base_vertex_type everywhere.
Fix Bomberman Ultra color and Cubixx HD geometry.
This commit is contained in:
Vincent Lejeune 2016-01-07 23:35:59 +01:00
parent 3afc62e525
commit d153575e59
10 changed files with 179 additions and 91 deletions

View File

@ -5,6 +5,27 @@
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
namespace
{
/**
* Convert CMP vector to RGBA16.
* A vector in CMP (compressed) format is stored as X11Y11Z10 and has a W component of 1.
* X11 and Y11 channels are int between -1024 and 1023 interpreted as -1.f, 1.f
* Z10 is int between -512 and 511 interpreted as -1.f, 1.f
*/
std::array<u16, 4> decode_cmp_vector(u32 encoded_vector)
{
u16 Z = encoded_vector >> 22;
Z = Z << 6;
u16 Y = (encoded_vector >> 11) & 0x7FF;
Y = Y << 5;
u16 X = encoded_vector & 0x7FF;
X = X << 5;
return{ X, Y, Z, 1 };
}
}
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.size > 0);
@ -15,8 +36,7 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = rsx::get_address(offset & 0x7fffffff, offset >> 31);
u32 type_size = rsx::get_vertex_type_size(vertex_array_desc.type);
u32 element_size = type_size * vertex_array_desc.size;
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_array_desc.type, vertex_array_desc.size);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 base_index = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
@ -26,13 +46,14 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
auto src = vm::ps3::_ptr<const u8>(address + base_offset + vertex_array_desc.stride * (first + i + base_index));
u8* dst = (u8*)buffer + i * element_size;
switch (type_size)
switch (vertex_array_desc.type)
{
case 1:
case Vertex_base_type::ub:
memcpy(dst, src, vertex_array_desc.size);
break;
case 2:
case Vertex_base_type::s1:
case Vertex_base_type::sf:
{
auto* c_src = (const be_t<u16>*)src;
u16* c_dst = (u16*)dst;
@ -41,10 +62,14 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
{
*c_dst++ = *c_src++;
}
if (vertex_array_desc.size * sizeof(u16) < element_size)
*c_dst++ = 0x3800;
break;
}
case 4:
case Vertex_base_type::f:
case Vertex_base_type::s32k:
case Vertex_base_type::ub256:
{
auto* c_src = (const be_t<u32>*)src;
u32* c_dst = (u32*)dst;
@ -55,6 +80,17 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
}
break;
}
case Vertex_base_type::cmp:
{
auto* c_src = (const be_t<u32>*)src;
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;
}
}
}
}

View File

@ -60,8 +60,7 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(co
// 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 element_size = type_size * info.size;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
size_t buffer_size = element_size * vertex_count;
assert(m_vertex_index_data.can_alloc(buffer_size));
@ -104,8 +103,7 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(co
const std::vector<u8> &data = register_vertex_data[index];
u32 type_size = rsx::get_vertex_type_size(info.type);
u32 element_size = type_size * info.size;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
size_t buffer_size = data.size();
assert(m_vertex_index_data.can_alloc(buffer_size));
@ -253,7 +251,7 @@ std::tuple<D3D12_VERTEX_BUFFER_VIEW, size_t> D3D12GSRender::upload_inlined_verte
IAElement.InstanceDataStepRate = 0;
m_IASet.push_back(IAElement);
offset += rsx::get_vertex_type_size(info.type) * info.size;
offset += rsx::get_vertex_type_size_on_host(info.type, info.size);
}
// Copy inline buffer

View File

@ -372,11 +372,11 @@ DXGI_FORMAT get_index_type(u8 index_type)
throw EXCEPTION("Invalid index_type (0x%x)", index_type);
}
DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
{
switch (type)
{
case CELL_GCM_VERTEX_S1:
case Vertex_base_type::s1:
{
switch (size)
{
@ -387,7 +387,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_F:
case Vertex_base_type::f:
{
switch (size)
{
@ -398,7 +398,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_SF:
case Vertex_base_type::sf:
{
switch (size)
{
@ -409,7 +409,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_UB:
case Vertex_base_type::ub:
{
switch (size)
{
@ -420,7 +420,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_S32K:
case Vertex_base_type::s32k:
{
switch (size)
{
@ -431,18 +431,18 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_CMP:
case Vertex_base_type::cmp:
{
switch (size)
{
case 1: return DXGI_FORMAT_R32_FLOAT;
case 2: return DXGI_FORMAT_R32G32_FLOAT;
case 3: return DXGI_FORMAT_R32G32B32_FLOAT;
case 4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case 1: return DXGI_FORMAT_R16G16B16A16_SNORM;
case 2:
case 3:
case 4: throw EXCEPTION("Unsupported CMP vertex format with size > 1");
}
break;
}
case CELL_GCM_VERTEX_UB256:
case Vertex_base_type::ub256:
{
switch (size)
{

View File

@ -101,7 +101,7 @@ DXGI_FORMAT get_index_type(u8 index_type);
/**
* Convert vertex attribute format and size to DXGI_FORMAT
*/
DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size);
DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size);
/**
* Convert scissor register value to D3D12_RECT

View File

@ -719,6 +719,21 @@ namespace
};
}
Vertex_base_type to_vertex_base_type(u8 in)
{
switch (in)
{
case 1: return Vertex_base_type::s1;
case 2: return Vertex_base_type::f;
case 3: return Vertex_base_type::sf;
case 4: return Vertex_base_type::ub;
case 5: return Vertex_base_type::s32k;
case 6: return Vertex_base_type::cmp;
case 7: return Vertex_base_type::ub256;
}
throw new EXCEPTION("Unknow vertex base type %d", in);
}
std::string rsx::get_method_name(const u32 id)
{
auto found = methods.find(id);
@ -926,17 +941,16 @@ namespace
std::string get_vertex_attribute_format(u8 type)
{
switch (type)
switch (to_vertex_base_type(type))
{
case CELL_GCM_VERTEX_S1: return "Short";
case CELL_GCM_VERTEX_F: return "Float";
case CELL_GCM_VERTEX_SF: return "Half float";
case CELL_GCM_VERTEX_UB: return "Unsigned byte";
case CELL_GCM_VERTEX_S32K: return "Signed int";
case CELL_GCM_VERTEX_CMP: return "CMP";
case CELL_GCM_VERTEX_UB256: return "UB256";
case Vertex_base_type::s1: return "Short";
case Vertex_base_type::f: return "Float";
case Vertex_base_type::sf: return "Half float";
case Vertex_base_type::ub: return "Unsigned byte";
case Vertex_base_type::s32k: return "Signed int";
case Vertex_base_type::cmp: return "CMP";
case Vertex_base_type::ub256: return "UB256";
}
return "Error";
}
std::string unpack_vertex_format(u32 arg)

View File

@ -23,17 +23,19 @@ enum
CELL_GCM_DISPLAY_FREQUENCY_DISABLE = 3,
};
enum
enum class Vertex_base_type
{
CELL_GCM_VERTEX_S1 = 1,
CELL_GCM_VERTEX_F = 2,
CELL_GCM_VERTEX_SF = 3,
CELL_GCM_VERTEX_UB = 4,
CELL_GCM_VERTEX_S32K = 5,
CELL_GCM_VERTEX_CMP = 6,
CELL_GCM_VERTEX_UB256 = 7,
s1, ///< signed byte
f, ///< float
sf, ///< half float
ub, ///< unsigned byte
s32k, ///< signed 32bits int
cmp, ///< compressed aka X11G11Z10 and always 1. W.
ub256,
};
Vertex_base_type to_vertex_base_type(u8 in);
enum
{
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0,

View File

@ -292,6 +292,39 @@ void apply_attrib_array(gl::glsl::program& program, int location, const std::vec
}
}
namespace
{
gl::buffer_pointer::type gl_types(Vertex_base_type type)
{
switch (type)
{
case Vertex_base_type::s1: return gl::buffer_pointer::type::s16;
case Vertex_base_type::f: return gl::buffer_pointer::type::f32;
case Vertex_base_type::sf: return gl::buffer_pointer::type::f16;
case Vertex_base_type::ub: return gl::buffer_pointer::type::u8;
case Vertex_base_type::s32k: return gl::buffer_pointer::type::s32;
case Vertex_base_type::cmp: return gl::buffer_pointer::type::s16; // Needs conversion
case Vertex_base_type::ub256: gl::buffer_pointer::type::u8;
}
}
bool gl_normalized(Vertex_base_type type)
{
switch (type)
{
case Vertex_base_type::s1:
case Vertex_base_type::ub:
case Vertex_base_type::cmp:
return true;
case Vertex_base_type::f:
case Vertex_base_type::sf:
case Vertex_base_type::ub256:
case Vertex_base_type::s32k:
return false;
}
}
}
void GLGSRender::end()
{
if (!draw_fbo || !vertex_draw_count)
@ -322,31 +355,9 @@ void GLGSRender::end()
}
//initialize vertex attributes
static const gl::buffer_pointer::type gl_types[] =
{
gl::buffer_pointer::type::f32,
gl::buffer_pointer::type::s16,
gl::buffer_pointer::type::f32,
gl::buffer_pointer::type::f16,
gl::buffer_pointer::type::u8,
gl::buffer_pointer::type::s16,
gl::buffer_pointer::type::f32, // Needs conversion
gl::buffer_pointer::type::u8
};
static const bool gl_normalized[] =
{
false,
true,
false,
false,
true,
false,
true,
false
};
//merge all vertex arrays
std::vector<u8> vertex_arrays_data;
@ -382,8 +393,8 @@ void GLGSRender::end()
__glcheck m_program->attribs[location] =
(m_vao + offset)
.config(gl_types[vertex_info.type], vertex_info.size, gl_normalized[vertex_info.type]);
offset += rsx::get_vertex_type_size(vertex_info.type) * vertex_info.size;
.config(gl_types(vertex_info.type), vertex_info.size, gl_normalized(vertex_info.type));
offset += rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
}
}
else
@ -416,7 +427,7 @@ void GLGSRender::end()
__glcheck m_program->attribs[location] =
(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 if (register_vertex_info[index].size > 0)
{
@ -425,7 +436,7 @@ void GLGSRender::end()
switch (vertex_info.type)
{
case CELL_GCM_VERTEX_F:
case Vertex_base_type::f:
switch (register_vertex_info[index].size)
{
case 1: apply_attrib_array<f32, 1>(*m_program, location, vertex_data); break;

View File

@ -120,22 +120,51 @@ namespace rsx
return res;
}
u32 get_vertex_type_size(u32 type)
u32 get_vertex_type_size_on_host(Vertex_base_type type, u32 size)
{
switch (type)
{
case CELL_GCM_VERTEX_S1: return sizeof(u16);
case CELL_GCM_VERTEX_F: return sizeof(f32);
case CELL_GCM_VERTEX_SF: return sizeof(f16);
case CELL_GCM_VERTEX_UB: return sizeof(u8);
case CELL_GCM_VERTEX_S32K: return sizeof(u32);
case CELL_GCM_VERTEX_CMP: return sizeof(u32);
case CELL_GCM_VERTEX_UB256: return sizeof(u8) * 4;
case Vertex_base_type::s1:
switch (size)
{
case 1:
case 2:
case 4:
return sizeof(u16) * size;
case 3:
return sizeof(u16) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::f: return sizeof(f32) * size;
case Vertex_base_type::sf:
switch (size)
{
case 1:
case 2:
case 4:
return sizeof(f16) * size;
case 3:
return sizeof(f16) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::ub:
switch (size)
{
case 1:
case 2:
case 4:
return sizeof(u8) * size;
case 3:
return sizeof(u8) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::s32k: return sizeof(u32) * size;
case Vertex_base_type::cmp: return sizeof(u16) * 4;
case Vertex_base_type::ub256: return sizeof(u8) * 4;
default:
LOG_ERROR(RSX, "RSXVertexData::GetTypeSize: Bad vertex data type (%d)!", type);
assert(0);
return 1;
throw new EXCEPTION("RSXVertexData::GetTypeSize: Bad vertex data type (%d)!", type);
return 0;
}
}
@ -254,8 +283,7 @@ namespace rsx
auto &data = vertex_arrays[index];
u32 type_size = get_vertex_type_size(info.type);
u32 element_size = type_size * info.size;
u32 element_size = get_vertex_type_size_on_host(info.type, info.size);
u32 dst_position = (u32)data.size();
data.resize(dst_position + count * element_size);
@ -537,10 +565,9 @@ namespace rsx
if (!info.size) // disabled
continue;
u32 type_size = rsx::get_vertex_type_size(info.type);
u32 element_size = type_size * info.size;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
if (type_size == 1 && info.size == 4)
if (info.type == Vertex_base_type::ub && info.size == 4)
{
dst[0] = src[3];
dst[1] = src[2];

View File

@ -148,7 +148,7 @@ namespace rsx
static std::string path_to_root();
};
u32 get_vertex_type_size(u32 type);
u32 get_vertex_type_size_on_host(Vertex_base_type type, u32 size);
u32 get_address(u32 offset, u32 location);
@ -195,14 +195,14 @@ namespace rsx
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
u8 type = CELL_GCM_VERTEX_F;
Vertex_base_type type = Vertex_base_type::f;
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 = data_array_format & 0xf;
type = to_vertex_base_type(data_array_format & 0xf);
}
};

View File

@ -14,10 +14,10 @@ namespace rsx
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> { enum { type = CELL_GCM_VERTEX_F }; };
template<> struct vertex_data_type_from_element_type<f16> { enum { type = CELL_GCM_VERTEX_SF }; };
template<> struct vertex_data_type_from_element_type<u8> { enum { type = CELL_GCM_VERTEX_UB }; };
template<> struct vertex_data_type_from_element_type<u16> { enum { type = CELL_GCM_VERTEX_S1 }; };
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
{
@ -248,7 +248,7 @@ namespace rsx
continue;
u32 count = u32(rsx->register_vertex_data[i].size()) /
rsx::get_vertex_type_size(rsx->register_vertex_info[i].type) * rsx->register_vertex_info[i].size;
rsx::get_vertex_type_size_on_host(rsx->register_vertex_info[i].type, rsx->register_vertex_info[i].size);
if (count < min_count)
min_count = count;