SetVertexData4f support

This commit is contained in:
Anthony Miles 2019-12-12 21:54:31 +13:00 committed by patrickvl
parent ba5d25e2ed
commit 136083d72a
5 changed files with 67 additions and 48 deletions

View File

@ -489,6 +489,17 @@ const char *CxbxGetErrorDescription(HRESULT hResult)
return nullptr;
}
// TODO move to shader file. Needs to be called whenever a shader or declaration is set
void SetOverrideFlags(CxbxVertexShader* pCxbxVertexShader) {
if (pCxbxVertexShader != nullptr && pCxbxVertexShader->pHostVertexShader != nullptr) {
float overrideFlags[16];
for (int i = 0; i < 16; i++) {
overrideFlags[i] = !pCxbxVertexShader->VertexShaderInfo.vRegisterInDeclaration[i];
}
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_CONSTREG_VERTEXDATA4F_FLAG_BASE, overrideFlags, 4);
}
}
const char *D3DErrorString(HRESULT hResult)
{
static char buffer[1024];
@ -3452,6 +3463,8 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SelectVertexShader)
pHostVertexDeclaration = pCxbxVertexShader->pHostVertexDeclaration;
pHostVertexShader = pCxbxVertexShader->pHostVertexShader;
HostFVF = pCxbxVertexShader->HostFVF;
SetOverrideFlags(pCxbxVertexShader);
}
hRet = g_pD3DDevice->SetVertexDeclaration(pHostVertexDeclaration);
@ -3808,15 +3821,10 @@ void UpdateViewPortOffsetAndScaleConstants()
{
float vOffset[4], vScale[4];
GetViewPortOffsetAndScale(vOffset, vScale);
float vScaleReversed[4] = { 1.0f / (double)vScale[0], 1.0f / (double)vScale[1], 1.0f / (double)vScale[2], 0 };
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_VIEWPORT_SCALE_MIRROR_INVERTED, vScaleReversed, 1);
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_VIEWPORT_SCALE_MIRROR, vScale, 1);
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_VIEWPORT_OFFSET_MIRROR, vOffset, 1);
// Set 0 and 1 constant, used to compare and transform W when required
float ZeroOne[] = { 0, 1, 0, 0 };
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_VIEWPORT_SCALE_ZERO_ONE, ZeroOne, 1);
// Store viewport offset and scale in constant registers 58 (c-38) and
// 59 (c-37) used for screen space transformation.
// We only do this if X_D3DSCM_NORESERVEDCONSTANTS is not set, since enabling this flag frees up these registers for shader used
@ -6674,18 +6682,12 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexShader)
}
else
{
SetOverrideFlags(pCxbxVertexShader);
hRet = g_pD3DDevice->SetVertexShader(pCxbxVertexShader->pHostVertexShader);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader(VshHandleIsVertexShader)");
}
// Set default constant values for specular, diffuse, etc
static const float ColorBlack[4] = { 0,0,0,0 };
static const float ColorWhite[4] = { 1,1,1,1 };
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VERTEXDATA4F_BASE + XTL::X_D3DVSDE_DIFFUSE, ColorWhite, 1);
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VERTEXDATA4F_BASE + XTL::X_D3DVSDE_BACKDIFFUSE, ColorWhite, 1);
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VERTEXDATA4F_BASE + XTL::X_D3DVSDE_SPECULAR, ColorBlack, 1);
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VERTEXDATA4F_BASE + XTL::X_D3DVSDE_BACKSPECULAR, ColorBlack, 1);
} else {
hRet = g_pD3DDevice->SetVertexShader(nullptr);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");

View File

@ -25,6 +25,13 @@ struct VS_OUTPUT
// Xbox constant registers
extern uniform float4 c[192] : register(c0);
// Vertex input overrides for SetVertexData4f support
extern float4 vOverrideValue[16] : register(c192);
extern float4 vOverridePacked[4] : register(c208);
extern float4 xboxViewportScale : register(c212);
extern float4 xboxViewportOffset : register(c213);
// Overloaded casts, assuring all inputs are treated as float4
float4 _tof4(float src) { return float4(src, src, src, src); }
float4 _tof4(float2 src) { return src.xyyy; }
@ -176,16 +183,16 @@ float _rcc(float input)
float4 reverseScreenspaceTransform(float4 oPos)
{
// On Xbox, oPos should contain the vertex position in screenspace
// We need to reverse this transformation
// Conventionally, each Xbox Vertex Shader includes instructions like this
// mul oPos.xyz, r12, c-38
// +rcc r1.x, r12.w
// mad oPos.xyz, r12, r1.x, c-37
// where c-37 and c-38 are reserved transform values
// Lets hope c-37 and c-38 contain the conventional values
oPos.xyz -= (float3)c[-37 + 96]; // reverse offset
oPos.xyz -= xboxViewportOffset.xyz; // reverse offset
oPos.xyz *= oPos.w; // reverse perspective divide
oPos.xyz /= (float3)c[-38 + 96]; // reverse scale
oPos.xyz /= xboxViewportScale.xyz; // reverse scale
return oPos;
}
@ -208,25 +215,33 @@ VS_OUTPUT main(const VS_INPUT xIn)
r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = float4(0, 0, 0, 0);
#define r12 oPos // oPos and r12 are two ways of accessing the same register on Xbox
// Input registers
float4 v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15;
// Initialize input variables
v0 = xIn.v[0];
v1 = xIn.v[1];
v2 = xIn.v[2];
v3 = xIn.v[3];
v4 = xIn.v[4];
v5 = xIn.v[5];
v6 = xIn.v[6];
v7 = xIn.v[7];
v8 = xIn.v[8];
v9 = xIn.v[9];
v10 = xIn.v[10];
v11 = xIn.v[11];
v12 = xIn.v[12];
v13 = xIn.v[13];
v14 = xIn.v[14];
v15 = xIn.v[15];
// Input registerss
float4 v[16];
# define v0 v[0]
# define v1 v[1]
# define v2 v[2]
# define v3 v[3]
# define v4 v[4]
# define v5 v[5]
# define v6 v[6]
# define v7 v[7]
# define v8 v[8]
# define v9 v[9]
# define v10 v[10]
# define v11 v[11]
# define v12 v[12]
# define v13 v[13]
# define v14 v[14]
# define v15 v[15]
// View 4 packed overrides as an array of 16 floats
float vOverride[16] = (float[16])vOverridePacked;
// Initialize input registers from the vertex buffer
// Or use an override value set with SetVertexData4f
for(uint i = 0; i < 16; i++){
v[i] = vOverride[i] ? vOverrideValue[i] : xIn.v[i];
}
// Xbox shader program
// <Xbox Shader>

View File

@ -988,17 +988,13 @@ typedef DWORD X_VERTEXSHADERCONSTANTMODE;
#define X_D3DSCM_CORRECTION 96 // Add 96 to arrive at the range 0..191 (instead of 96..95)
#define X_D3DVS_CONSTREG_COUNT 192
#define X_D3DVS_RESERVED_CONSTANT1 -38 // Becomes 58 after correction, contains Scale v
#define X_D3DVS_RESERVED_CONSTANT2 -37 // Becomes 59 after correction, contains Offset
#define X_D3DVS_RESERVED_CONSTANT1_CORRECTED (X_D3DVS_RESERVED_CONSTANT1 + X_D3DVS_CONSTREG_BIAS)
#define X_D3DVS_RESERVED_CONSTANT2_CORRECTED (X_D3DVS_RESERVED_CONSTANT2 + X_D3DVS_CONSTREG_BIAS)
// Special Registers, used to pass additional information to the shaders
#define X_D3DVS_CONSTREG_VERTEXDATA4F_BASE (X_D3DVS_CONSTREG_COUNT + 1)
#define X_D3DVS_CONSTREG_VERTEXDATA4F_END (X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + 14)
#define X_D3DVS_VIEWPORT_SCALE_MIRROR_INVERTED (X_D3DVS_CONSTREG_VERTEXDATA4F_END + 1)
#define X_D3DVS_VIEWPORT_OFFSET_MIRROR (X_D3DVS_VIEWPORT_SCALE_MIRROR_INVERTED + 1)
#define X_D3DVS_VIEWPORT_SCALE_ZERO_ONE (X_D3DVS_VIEWPORT_OFFSET_MIRROR + 1)
// TODO co-locate shader workaround constants with shader code
#define X_D3DVS_CONSTREG_VERTEXDATA4F_BASE (X_D3DVS_CONSTREG_COUNT)
#define X_D3DVS_CONSTREG_VERTEXDATA4F_FLAG_BASE (X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + 16)
#define X_D3DVS_VIEWPORT_SCALE_MIRROR (X_D3DVS_CONSTREG_VERTEXDATA4F_FLAG_BASE + 4)
#define X_D3DVS_VIEWPORT_OFFSET_MIRROR (X_D3DVS_VIEWPORT_SCALE_MIRROR + 1)
#define X_D3DSCM_RESERVED_CONSTANT_SCALE_CORRECTED (X_D3DSCM_RESERVED_CONSTANT_SCALE + X_D3DSCM_CORRECTION)
#define X_D3DSCM_RESERVED_CONSTANT_OFFSET_CORRECTED (X_D3DSCM_RESERVED_CONSTANT_OFFSET + X_D3DSCM_CORRECTION)

View File

@ -302,7 +302,7 @@ typedef struct _VSH_XBOX_SHADER
}
VSH_XBOX_SHADER;
// TODO : Reinstate and use : std::array<bool, 16> RegVIsPresentInDeclaration;
std::array<bool, 16> RegVIsPresentInDeclaration;
/* TODO : map non-FVF Xbox vertex shader handle to CxbxVertexShader (a struct containing a host Xbox vertex shader handle and the original members)
std::unordered_map<DWORD, CxbxVertexShader> g_CxbxVertexShaders;
@ -1290,7 +1290,7 @@ private:
}
// Add this register to the list of declared registers
// TODO : Reinstate and use : RegVIsPresentInDeclaration[VertexRegister] = true;
RegVIsPresentInDeclaration[VertexRegister] = true;
DWORD XboxVertexElementDataType = (*pXboxToken & X_D3DVSD_DATATYPEMASK) >> X_D3DVSD_DATATYPESHIFT;
WORD XboxVertexElementByteSize = 0;
@ -1617,7 +1617,7 @@ public:
IsFixedFunction = bIsFixedFunction;
// TODO : Reinstate and use : RegVIsPresentInDeclaration.fill(false);
RegVIsPresentInDeclaration.fill(false);
// First of all some info:
// We have to figure out which flags are set and then
@ -1661,6 +1661,11 @@ public:
// Free the preprocessed declaration copy
free(pXboxVertexDeclarationCopy);
for (int i = 0; i < RegVIsPresentInDeclaration.size(); i++) {
pCxbxVertexShaderInfo->vRegisterInDeclaration[i] = RegVIsPresentInDeclaration[i];
EmuLog(LOG_LEVEL::DEBUG, "Vertex regs used: v%d %d", i, pCxbxVertexShaderInfo->vRegisterInDeclaration[i]);
}
return Result;
}
};

View File

@ -71,6 +71,7 @@ typedef struct _CxbxVertexShaderInfo
{
UINT NumberOfVertexStreams; // The number of streams the vertex shader uses
CxbxVertexShaderStreamInfo VertexStreams[X_VSH_MAX_STREAMS];
bool vRegisterInDeclaration[16];
}
CxbxVertexShaderInfo;