mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
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:
commit
b055747d4f
16 changed files with 253 additions and 98 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue