Merge pull request #1414 from vlj/rsx

Rsx: Fix for vertex buffer filling and for some non IEEE compliant fragment instructions.
This commit is contained in:
B1ackDaemon 2016-01-10 02:44:29 +02:00
commit b055747d4f
16 changed files with 253 additions and 98 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

@ -341,7 +341,9 @@ bool FragmentProgramDecompiler::handle_sct(u32 opcode)
{
case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); return true;
case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1).xxxx)"); return true;
// Note: DIVSQ is not IEEE compliant. divsq(0, 0) is 0 (Super Puzzle Fighter II Turbo HD Remix).
// sqrt(x, 0) might be equal to some big value (in absolute) whose sign is sign(x) but it has to be proven.
case RSX_FP_OPCODE_DIVSQ: SetDst("divsq_legacy($0, $1)"); return true;
case RSX_FP_OPCODE_DP2: SetDst(getFunction(FUNCTION::FUNCTION_DP2)); return true;
case RSX_FP_OPCODE_DP3: SetDst(getFunction(FUNCTION::FUNCTION_DP3)); return true;
case RSX_FP_OPCODE_DP4: SetDst(getFunction(FUNCTION::FUNCTION_DP4)); return true;
@ -351,8 +353,11 @@ bool FragmentProgramDecompiler::handle_sct(u32 opcode)
case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); return true;
case RSX_FP_OPCODE_MOV: SetDst("$0"); return true;
case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); return true;
case RSX_FP_OPCODE_RCP: SetDst("1.0 / $0"); return true;
case RSX_FP_OPCODE_RSQ: SetDst("1.f / sqrt($0)"); return true;
// Note: It's higly likely that RCP is not IEEE compliant but a game that uses rcp(0) has to be found
case RSX_FP_OPCODE_RCP: SetDst("rcp_legacy($0)"); return true;
// Note: RSQ is not IEEE compliant. rsq(0) is some big number (Silent Hill 3 HD)
// It is not know what happens if 0 is negative.
case RSX_FP_OPCODE_RSQ: SetDst("rsq_legacy($0)"); return true;
case RSX_FP_OPCODE_SEQ: SetDst(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SEQ, "$0", "$1") + ")"); return true;
case RSX_FP_OPCODE_SFL: SetDst(getFunction(FUNCTION::FUNCTION_SFL)); return true;
case RSX_FP_OPCODE_SGE: SetDst(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SGE, "$0", "$1") + ")"); return true;
@ -372,7 +377,9 @@ bool FragmentProgramDecompiler::handle_scb(u32 opcode)
case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); return true;
case RSX_FP_OPCODE_COS: SetDst("cos($0.xxxx)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); return true;
case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1).xxxx)"); return true;
// Note: DIVSQ is not IEEE compliant. sqrt(0, 0) is 0 (Super Puzzle Fighter II Turbo HD Remix).
// sqrt(x, 0) might be equal to some big value (in absolute) whose sign is sign(x) but it has to be proven.
case RSX_FP_OPCODE_DIVSQ: SetDst("divsq_legacy($0, sqrt($1).xxxx)"); return true;
case RSX_FP_OPCODE_DP2: SetDst(getFunction(FUNCTION::FUNCTION_DP2)); return true;
case RSX_FP_OPCODE_DP3: SetDst(getFunction(FUNCTION::FUNCTION_DP3)); return true;
case RSX_FP_OPCODE_DP4: SetDst(getFunction(FUNCTION::FUNCTION_DP4)); return true;
@ -453,7 +460,22 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); return true;
case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); return true;
case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXL: SetDst("textureLod($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXL:
if (dst.tex_num >= m_texture_dimensions.size())
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{
case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
return true;
case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD));
return true;
}
return false;
case RSX_FP_OPCODE_UP2: SetDst("unpackSnorm2x16($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478))
case RSX_FP_OPCODE_UP4: SetDst("unpackSnorm4x8($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478))
case RSX_FP_OPCODE_UP16: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP16"); return true;

View file

@ -15,8 +15,10 @@ enum class FUNCTION {
FUNCTION_DFDY,
FUNCTION_TEXTURE_SAMPLE,
FUNCTION_TEXTURE_SAMPLE_PROJ,
FUNCTION_TEXTURE_SAMPLE_LOD,
FUNCTION_TEXTURE_CUBE_SAMPLE,
FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ,
FUNCTION_TEXTURE_CUBE_SAMPLE_LOD,
};
enum class COMPARE {

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

@ -46,10 +46,14 @@ std::string getFunctionImp(FUNCTION f)
return "$t.Sample($tsampler, $0.xy * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
return "$t.Sample($tsampler, ($0.xy / $0.z) * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xy / $0.z) * $t_scale, $1)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
return "$t.Sample($tsampler, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
return "$t.Sample($tsampler, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xyz / $0.w), $1)";
case FUNCTION::FUNCTION_DFDX:
return "ddx($0)";
case FUNCTION::FUNCTION_DFDY:

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

@ -141,6 +141,24 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
{
// "lib" function
// 0.00001 is used as "some non zero very little number"
OS << "float4 divsq_legacy(float4 num, float4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n";
OS << "}\n";
OS << "float4 rcp_legacy(float4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "float4 rsq_legacy(float4 denum)\n";
OS << "{\n";
OS << " return 1. / sqrt(max(denum, 0.00001));\n";
OS << "}\n";
const std::set<std::string> output_value =
{
"r0", "r1", "r2", "r3", "r4",

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

@ -44,10 +44,14 @@ std::string getFunctionImpl(FUNCTION f)
return "texture($t, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
return "textureProj($t, $0.xyz, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD:
return "textureLod($t, $0.xy, $1)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD:
return "textureLod($t, $0.xyz, $1)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY:

View file

@ -84,6 +84,23 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
// "lib" function
// 0.00001 is used as "some non zero very little number"
OS << "vec4 divsq_legacy(vec4 num, vec4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n";
OS << "}\n";
OS << "vec4 rcp_legacy(vec4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "vec4 rsq_legacy(vec4 denum)\n";
OS << "{\n";
OS << " return 1. / sqrt(max(denum, 0.00001));\n";
OS << "}\n";
OS << "void main ()" << std::endl;
OS << "{" << std::endl;

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);
@ -319,7 +347,7 @@ namespace rsx
color_index_to_record = { 0, 1, 2, 3 };
break;
}
/* for (size_t i : color_index_to_record)
for (size_t i : color_index_to_record)
{
draw_state.color_buffer[i].width = clip_w;
draw_state.color_buffer[i].height = clip_h;
@ -336,7 +364,7 @@ namespace rsx
draw_state.stencil.height = clip_h;
draw_state.stencil.data.resize(clip_w * clip_h * 4);
copy_stencil_buffer_to_memory(draw_state.stencil.data.data());
}*/
}
draw_state.programs = get_programs();
draw_state.name = name;
frame_debug.draw_calls.push_back(draw_state);
@ -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;