Use an HLSL accessor function for reading constant registers, allowing Xbox-native negative indices and out-of-bounds handling. This makes the generated HLSL look closed to the original Xbox vertex shader assembly.

This commit is contained in:
PatrickvL 2019-12-13 18:20:57 +01:00 committed by patrickvl
parent d74e5947ee
commit ff1412b3d9
3 changed files with 37 additions and 17 deletions

View File

@ -21,16 +21,19 @@ struct VS_OUTPUT
float4 oT2 : TEXCOORD2; // Texture coordinate set 2
float4 oT3 : TEXCOORD3; // Texture coordinate set 3
};
// Xbox constant registers
extern uniform float4 c[192] : register(c0);
#define X_D3DSCM_CORRECTION 96 // Add 96 to arrive at the range 0..191 (instead of -96..95)
#define X_D3DVS_CONSTREG_COUNT 192
// Xbox constant registers
uniform float4 C[X_D3DVS_CONSTREG_COUNT] : register(c0);
// Vertex input overrides for SetVertexData4f support
extern float4 vOverrideValue[16] : register(c192);
extern float4 vOverridePacked[4] : register(c208);
uniform float4 vOverrideValue[16] : register(c192);
uniform float4 vOverridePacked[4] : register(c208);
extern float4 xboxViewportScale : register(c212);
extern float4 xboxViewportOffset : register(c213);
uniform float4 xboxViewportScale : register(c212);
uniform float4 xboxViewportOffset : register(c213);
// Overloaded casts, assuring all inputs are treated as float4
float4 _tof4(float src) { return float4(src, src, src, src); }
@ -40,6 +43,20 @@ float4 _tof4(float4 src) { return src; }
float4 _ssss(float s) { return float4(s, s, s, s); } // a scalar output replicated across a 4-component vector
#define _scalar(src) _tof4(src).x /* a scalar input */
float4 c(int register_number)
{
// Map Xbox [-96, 95] to Host [0, 191]
// Account for Xbox's negative constant indexes
register_number += X_D3DSCM_CORRECTION;
if (register_number < 0)
return 0;
if (register_number >= X_D3DVS_CONSTREG_COUNT) // X_D3DVS_CONSTREG_COUNT
return 0;
return C[register_number];
}
// http://xboxdevwiki.net/NV2A/Vertex_Shader
// https://www.khronos.org/registry/OpenGL/extensions/NV/NV_vertex_program.txt
// https://www.khronos.org/registry/OpenGL/extensions/NV/NV_vertex_program1_1.txt

View File

@ -986,7 +986,7 @@ typedef DWORD X_VERTEXSHADERCONSTANTMODE;
#define X_D3DSCM_RESERVED_CONSTANT_SCALE -38 // Becomes 58 after correction, contains Scale v
#define X_D3DSCM_RESERVED_CONSTANT_OFFSET -37 // Becomes 59 after correction, contains Offset
#define X_D3DSCM_CORRECTION 96 // Add 96 to arrive at the range 0..191 (instead of 96..95)
#define X_D3DSCM_CORRECTION 96 // Add 96 to arrive at the range 0..191 (instead of -96..95)
#define X_D3DVS_CONSTREG_COUNT 192
// Special Registers, used to pass additional information to the shaders

View File

@ -1601,7 +1601,9 @@ static void OutputHlsl(std::stringstream& hlsl, VSH_IMD_OUTPUT& dest)
switch (dest.Type) {
case IMD_OUTPUT_C:
hlsl << "c[" << dest.Address << "]";
// Access the HLSL capital C[] constants array, with the index bias applied :
// TODO : Avoid out-of-bound writes (perhaps writing to a reserverd index?)
hlsl << "C[" << dest.Address + X_D3DSCM_CORRECTION << "]";
LOG_TEST_CASE("Vertex shader writes to constant table");
break;
case IMD_OUTPUT_R:
@ -1647,18 +1649,19 @@ static void ParameterHlsl(std::stringstream& hlsl, VSH_IMD_PARAMETER& paramMeta)
int register_number = param.Address;
if (param.ParameterType == PARAM_C) {
// Map Xbox [-96, 95] to Host [0, 191]
// Account for Xbox's negative constant indexes
register_number += 96;
// Access constant registers through our HLSL c() function,
// which allows dumping negative indices (like Xbox shaders),
// and which returns zero when out-of-bounds indices are passed in:
if (paramMeta.IndexesWithA0_X) {
// Only display the offset if it's not 0.
if (register_number != 0) {
hlsl << "c[a0.x+" << register_number << "]";
if (register_number == 0) {
hlsl << "c(a0.x)"; // Hide the offset if it's 0
} else if (register_number < 0) {
hlsl << "c(a0.x" << register_number << ")"; // minus is part of the offset
} else {
hlsl << "c[a0.x]";
hlsl << "c(a0.x+" << register_number << ")"; // show addition character
}
} else {
hlsl << "c[" << register_number << "]";
hlsl << "c(" << register_number << ")";
}
} else {
hlsl << RegisterName[param.ParameterType] << register_number;