Merge pull request #1683 from LukeUsher/vertex-shader-register-tweaks
Vertex shader register tweaks
This commit is contained in:
commit
f62030a548
|
@ -4168,6 +4168,23 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexData4f)
|
||||||
|
|
||||||
HRESULT hRet = D3D_OK;
|
HRESULT hRet = D3D_OK;
|
||||||
|
|
||||||
|
// Get the vertex shader flags (if any is active) :
|
||||||
|
uint32_t ActiveVertexAttributeFlags = 0;
|
||||||
|
if (VshHandleIsVertexShader(g_CurrentXboxVertexShaderHandle)) {
|
||||||
|
LOG_TEST_CASE("D3DDevice_SetVertexData4f with active VertexShader");
|
||||||
|
X_D3DVertexShader* pXboxVertexShader = VshHandleToXboxVertexShader(g_CurrentXboxVertexShaderHandle);
|
||||||
|
if (!(pXboxVertexShader->Flags & 0x10/*=X_VERTEXSHADER_PROGRAM*/)) {
|
||||||
|
ActiveVertexAttributeFlags = pXboxVertexShader->Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have an active vertex shader, we also write the input to a vertex shader constant
|
||||||
|
// This allows us to implement Xbox functionality where SetVertexData4f can be used to specify attributes
|
||||||
|
// not present in the vertex declaration.
|
||||||
|
// We use range 193 and up to store these values, as Xbox shaders stop at c192!
|
||||||
|
FLOAT values[] = {a,b,c,d};
|
||||||
|
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + Register, values, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Grow g_InlineVertexBuffer_Table to contain at least current, and a potentially next vertex
|
// Grow g_InlineVertexBuffer_Table to contain at least current, and a potentially next vertex
|
||||||
if (g_InlineVertexBuffer_TableLength <= g_InlineVertexBuffer_TableOffset + 1) {
|
if (g_InlineVertexBuffer_TableLength <= g_InlineVertexBuffer_TableOffset + 1) {
|
||||||
if (g_InlineVertexBuffer_TableLength == 0) {
|
if (g_InlineVertexBuffer_TableLength == 0) {
|
||||||
|
@ -4185,16 +4202,6 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexData4f)
|
||||||
// Set first vertex to zero (preventing leaks from prior Begin/End calls)
|
// Set first vertex to zero (preventing leaks from prior Begin/End calls)
|
||||||
g_InlineVertexBuffer_Table[0] = {};
|
g_InlineVertexBuffer_Table[0] = {};
|
||||||
|
|
||||||
// Get the vertex shader flags (if any is active) :
|
|
||||||
uint32_t ActiveVertexAttributeFlags = 0;
|
|
||||||
if (VshHandleIsVertexShader(g_CurrentXboxVertexShaderHandle)) {
|
|
||||||
LOG_TEST_CASE("D3DDevice_SetVertexData4f with active VertexShader");
|
|
||||||
X_D3DVertexShader *pXboxVertexShader = VshHandleToXboxVertexShader(g_CurrentXboxVertexShaderHandle);
|
|
||||||
if (!(pXboxVertexShader->Flags & 0x10/*=X_VERTEXSHADER_PROGRAM*/)) {
|
|
||||||
ActiveVertexAttributeFlags = pXboxVertexShader->Flags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle persistent vertex attribute flags, by resetting non-persistent colors
|
// Handle persistent vertex attribute flags, by resetting non-persistent colors
|
||||||
// to their default value (and leaving the persistent colors alone - see the
|
// to their default value (and leaving the persistent colors alone - see the
|
||||||
// "Copy all attributes of the previous vertex" comment below) :
|
// "Copy all attributes of the previous vertex" comment below) :
|
||||||
|
@ -4313,6 +4320,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexData4f)
|
||||||
{
|
{
|
||||||
g_InlineVertexBuffer_Table[o].Diffuse = D3DCOLOR_COLORVALUE(a, b, c, d);
|
g_InlineVertexBuffer_Table[o].Diffuse = D3DCOLOR_COLORVALUE(a, b, c, d);
|
||||||
g_InlineVertexBuffer_FVF |= D3DFVF_DIFFUSE;
|
g_InlineVertexBuffer_FVF |= D3DFVF_DIFFUSE;
|
||||||
|
HLE_write_NV2A_vertex_attribute_slot(X_D3DVSDE_DIFFUSE, g_InlineVertexBuffer_Table[o].Diffuse);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4320,13 +4328,14 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexData4f)
|
||||||
{
|
{
|
||||||
g_InlineVertexBuffer_Table[o].Specular = D3DCOLOR_COLORVALUE(a, b, c, d);
|
g_InlineVertexBuffer_Table[o].Specular = D3DCOLOR_COLORVALUE(a, b, c, d);
|
||||||
g_InlineVertexBuffer_FVF |= D3DFVF_SPECULAR;
|
g_InlineVertexBuffer_FVF |= D3DFVF_SPECULAR;
|
||||||
|
HLE_write_NV2A_vertex_attribute_slot(X_D3DVSDE_SPECULAR, g_InlineVertexBuffer_Table[o].Specular);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case X_D3DVSDE_FOG: // Xbox extension
|
case X_D3DVSDE_FOG: // Xbox extension
|
||||||
{
|
{
|
||||||
g_InlineVertexBuffer_Table[o].Fog = a; // TODO : What about the other (b, c and d) arguments?
|
g_InlineVertexBuffer_Table[o].Fog = a; // TODO : What about the other (b, c and d) arguments?
|
||||||
EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF FOG");
|
//EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF FOG");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4335,14 +4344,16 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexData4f)
|
||||||
case X_D3DVSDE_BACKDIFFUSE: // Xbox extension
|
case X_D3DVSDE_BACKDIFFUSE: // Xbox extension
|
||||||
{
|
{
|
||||||
g_InlineVertexBuffer_Table[o].BackDiffuse = D3DCOLOR_COLORVALUE(a, b, c, d);
|
g_InlineVertexBuffer_Table[o].BackDiffuse = D3DCOLOR_COLORVALUE(a, b, c, d);
|
||||||
EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF BACKDIFFUSE");
|
//EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF BACKDIFFUSE");
|
||||||
|
HLE_write_NV2A_vertex_attribute_slot(X_D3DVSDE_BACKDIFFUSE, g_InlineVertexBuffer_Table[o].BackDiffuse);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case X_D3DVSDE_BACKSPECULAR: // Xbox extension
|
case X_D3DVSDE_BACKSPECULAR: // Xbox extension
|
||||||
{
|
{
|
||||||
g_InlineVertexBuffer_Table[o].BackSpecular = D3DCOLOR_COLORVALUE(a, b, c, d);
|
g_InlineVertexBuffer_Table[o].BackSpecular = D3DCOLOR_COLORVALUE(a, b, c, d);
|
||||||
EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF BACKSPECULAR");
|
//EmuLog(LOG_LEVEL::WARNING, "Host Direct3D8 doesn''t support FVF BACKSPECULAR");
|
||||||
|
HLE_write_NV2A_vertex_attribute_slot(X_D3DVSDE_BACKSPECULAR, g_InlineVertexBuffer_Table[o].BackSpecular);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6487,7 +6498,16 @@ VOID __fastcall XTL::EMUPATCH(D3DDevice_SetRenderState_Simple)
|
||||||
// Just log and return
|
// Just log and return
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "RenderState_Simple(0x%.08X (%s), 0x%.08X) was ignored!", Method, DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
|
EmuLog(LOG_LEVEL::DEBUG, "RenderState_Simple(0x%.08X (%s), 0x%.08X) was ignored!", Method, DxbxRenderStateInfo[XboxRenderStateIndex].S, Value);
|
||||||
return;
|
return;
|
||||||
case X_D3DRS_ALPHATESTENABLE: case X_D3DRS_ALPHABLENDENABLE:
|
case X_D3DRS_ALPHATESTENABLE:
|
||||||
|
if (g_LibVersion_D3D8 == 3925) {
|
||||||
|
// HACK: Many 3925 have missing polygons when this is true
|
||||||
|
// Until we find out the true underlying cause, and carry on
|
||||||
|
// Test Cases: Halo, Silent Hill 2.
|
||||||
|
LOG_TEST_CASE("Applying 3925 alpha test disable hack");
|
||||||
|
Value = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case X_D3DRS_ALPHABLENDENABLE:
|
||||||
case X_D3DRS_ALPHAREF: case X_D3DRS_ZWRITEENABLE:
|
case X_D3DRS_ALPHAREF: case X_D3DRS_ZWRITEENABLE:
|
||||||
case X_D3DRS_DITHERENABLE: case X_D3DRS_STENCILREF:
|
case X_D3DRS_DITHERENABLE: case X_D3DRS_STENCILREF:
|
||||||
case X_D3DRS_STENCILMASK: case X_D3DRS_STENCILWRITEMASK:
|
case X_D3DRS_STENCILMASK: case X_D3DRS_STENCILWRITEMASK:
|
||||||
|
@ -7119,6 +7139,15 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexShader)
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexDeclaration");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexDeclaration");
|
||||||
hRet = g_pD3DDevice->SetVertexShader((XTL::IDirect3DVertexShader9*)pVertexShader->Handle);
|
hRet = g_pD3DDevice->SetVertexShader((XTL::IDirect3DVertexShader9*)pVertexShader->Handle);
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader(VshHandleIsVertexShader)");
|
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(X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + X_D3DVSDE_DIFFUSE, ColorWhite, 1);
|
||||||
|
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + X_D3DVSDE_BACKDIFFUSE, ColorWhite, 1);
|
||||||
|
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + X_D3DVSDE_SPECULAR, ColorBlack, 1);
|
||||||
|
g_pD3DDevice->SetVertexShaderConstantF(X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + X_D3DVSDE_BACKSPECULAR, ColorBlack, 1);
|
||||||
} else {
|
} else {
|
||||||
hRet = g_pD3DDevice->SetVertexShader(nullptr);
|
hRet = g_pD3DDevice->SetVertexShader(nullptr);
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");
|
||||||
|
@ -7499,7 +7528,12 @@ void XTL::CxbxUpdateNativeD3DResources()
|
||||||
// Some titles set Vertex Shader constants directly via pushbuffers rather than through D3D
|
// Some titles set Vertex Shader constants directly via pushbuffers rather than through D3D
|
||||||
// We handle that case by updating any constants that have the dirty flag set on the nv2a.
|
// We handle that case by updating any constants that have the dirty flag set on the nv2a.
|
||||||
auto nv2a = g_NV2A->GetDeviceState();
|
auto nv2a = g_NV2A->GetDeviceState();
|
||||||
for(int i = 0; i < 192; i++) {
|
for(int i = 0; i < X_D3DVS_CONSTREG_COUNT; i++) {
|
||||||
|
// Skip vOffset and vScale constants, we don't want our values to be overwritten by accident
|
||||||
|
if (i == X_D3DSCM_RESERVED_CONSTANT1_CORRECTED || i == X_D3DSCM_RESERVED_CONSTANT2_CORRECTED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (nv2a->pgraph.vsh_constants_dirty[i]) {
|
if (nv2a->pgraph.vsh_constants_dirty[i]) {
|
||||||
g_pD3DDevice->SetVertexShaderConstantF(i, (float*)&nv2a->pgraph.vsh_constants[i][0], 1);
|
g_pD3DDevice->SetVertexShaderConstantF(i, (float*)&nv2a->pgraph.vsh_constants[i][0], 1);
|
||||||
nv2a->pgraph.vsh_constants_dirty[i] = false;
|
nv2a->pgraph.vsh_constants_dirty[i] = false;
|
||||||
|
|
|
@ -1081,6 +1081,10 @@ typedef DWORD X_VERTEXSHADERCONSTANTMODE;
|
||||||
#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
|
#define X_D3DVS_CONSTREG_COUNT 192
|
||||||
|
|
||||||
|
#define X_D3DSCM_RESERVED_CONSTANT1_CORRECTED (X_D3DSCM_RESERVED_CONSTANT1 + X_D3DSCM_CORRECTION)
|
||||||
|
#define X_D3DSCM_RESERVED_CONSTANT2_CORRECTED (X_D3DSCM_RESERVED_CONSTANT2 + X_D3DSCM_CORRECTION)
|
||||||
|
#define X_D3DVS_CONSTREG_VERTEXDATA4F_BASE (X_D3DVS_CONSTREG_COUNT + 1)
|
||||||
|
|
||||||
// Vertex shader types
|
// Vertex shader types
|
||||||
#define X_VST_NORMAL 1
|
#define X_VST_NORMAL 1
|
||||||
#define X_VST_READWRITE 2
|
#define X_VST_READWRITE 2
|
||||||
|
|
|
@ -103,7 +103,16 @@ void UpdateDeferredRenderStates()
|
||||||
Value = *(DWORD*)&fogValue;
|
Value = *(DWORD*)&fogValue;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case XTL::X_D3DRS_FOGENABLE:
|
case XTL::X_D3DRS_FOGENABLE:
|
||||||
|
if (g_LibVersion_D3D8 == 3925) {
|
||||||
|
// HACK: Many 3925 games only show a black screen if fog is enabled
|
||||||
|
// Initially, this was thought to be bad offsets, but it has been verified to be correct
|
||||||
|
// Until we find out the true underlying cause, disable fog and carry on
|
||||||
|
// Test Cases: Halo, Silent Hill 2.
|
||||||
|
LOG_TEST_CASE("Applying 3925 fog disable hack");
|
||||||
|
Value = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case XTL::X_D3DRS_FOGTABLEMODE:
|
case XTL::X_D3DRS_FOGTABLEMODE:
|
||||||
case XTL::X_D3DRS_FOGDENSITY:
|
case XTL::X_D3DRS_FOGDENSITY:
|
||||||
case XTL::X_D3DRS_RANGEFOGENABLE:
|
case XTL::X_D3DRS_RANGEFOGENABLE:
|
||||||
|
|
|
@ -486,8 +486,8 @@ static const char* OReg_Name[] =
|
||||||
"a0.x"
|
"a0.x"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<bool, 16> RegVUsage;
|
std::array<bool, 16> RegVIsPresentInDeclaration;
|
||||||
std::array<int, 16> RegVDeclUsage;
|
std::array<bool, 16> RegVIsUsedByShader;
|
||||||
|
|
||||||
/* TODO : map non-FVF Xbox vertex shader handle to CxbxVertexShader (a struct containing a host Xbox vertex shader handle and the original members)
|
/* 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;
|
std::unordered_map<DWORD, CxbxVertexShader> g_CxbxVertexShaders;
|
||||||
|
@ -790,28 +790,87 @@ static void VshWriteParameter(VSH_IMD_PARAMETER *pParameter,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// From D3D8to9
|
#define D3DDECLUSAGE_UNSUPPORTED ((D3DDECLUSAGE)-1)
|
||||||
static const BYTE DeclAddressUsages[][2] =
|
|
||||||
{
|
|
||||||
{ XTL::D3DDECLUSAGE_POSITION, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_BLENDWEIGHT, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_BLENDINDICES, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_NORMAL, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_PSIZE, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_COLOR, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_COLOR, 1 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 0 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 1 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 2 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 3 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 4 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 5 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 6 },
|
|
||||||
{ XTL::D3DDECLUSAGE_TEXCOORD, 7 },
|
|
||||||
{ XTL::D3DDECLUSAGE_POSITION, 1 },
|
|
||||||
{ XTL::D3DDECLUSAGE_NORMAL, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
XTL::D3DDECLUSAGE Xb2PCRegisterType
|
||||||
|
(
|
||||||
|
DWORD VertexRegister,
|
||||||
|
BYTE& PCUsageIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using namespace XTL;
|
||||||
|
|
||||||
|
D3DDECLUSAGE PCRegisterType;
|
||||||
|
PCUsageIndex = 0;
|
||||||
|
|
||||||
|
switch (VertexRegister)
|
||||||
|
{
|
||||||
|
case X_D3DVSDE_VERTEX: // -1
|
||||||
|
DbgVshPrintf("D3DVSDE_VERTEX /* xbox ext. */");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_POSITION: // 0
|
||||||
|
DbgVshPrintf("D3DVSDE_POSITION");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_POSITION;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_BLENDWEIGHT: // 1
|
||||||
|
DbgVshPrintf("D3DVSDE_BLENDWEIGHT");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_BLENDWEIGHT;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_NORMAL: // 2
|
||||||
|
DbgVshPrintf("D3DVSDE_NORMAL");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_NORMAL;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_DIFFUSE: // 3
|
||||||
|
DbgVshPrintf("D3DVSDE_DIFFUSE");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 0;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_SPECULAR: // 4
|
||||||
|
DbgVshPrintf("D3DVSDE_SPECULAR");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 1;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_FOG: // 5
|
||||||
|
DbgVshPrintf("D3DVSDE_FOG");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_FOG;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_POINTSIZE: // 6
|
||||||
|
DbgVshPrintf("D3DVDSE_POINTSIZE");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_PSIZE;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_BACKDIFFUSE: // 7
|
||||||
|
DbgVshPrintf("D3DVSDE_BACKDIFFUSE /* xbox ext. */");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 2;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_BACKSPECULAR: // 8
|
||||||
|
DbgVshPrintf("D3DVSDE_BACKSPECULAR /* xbox ext. */");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 3;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_TEXCOORD0: // 9
|
||||||
|
DbgVshPrintf("D3DVSDE_TEXCOORD0");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 0;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_TEXCOORD1: // 10
|
||||||
|
DbgVshPrintf("D3DVSDE_TEXCOORD1");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 1;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_TEXCOORD2: // 11
|
||||||
|
DbgVshPrintf("D3DVSDE_TEXCOORD2");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 2;
|
||||||
|
break;
|
||||||
|
case X_D3DVSDE_TEXCOORD3: // 12
|
||||||
|
DbgVshPrintf("D3DVSDE_TEXCOORD3");
|
||||||
|
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DbgVshPrintf("%d /* unknown register */", VertexRegister);
|
||||||
|
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PCRegisterType;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern XTL::D3DCAPS g_D3DCaps;
|
||||||
|
|
||||||
static void VshWriteShader(VSH_XBOX_SHADER *pShader,
|
static void VshWriteShader(VSH_XBOX_SHADER *pShader,
|
||||||
std::stringstream& pDisassembly,
|
std::stringstream& pDisassembly,
|
||||||
|
@ -841,55 +900,36 @@ static void VshWriteShader(VSH_XBOX_SHADER *pShader,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Truncate) {
|
if (Truncate) {
|
||||||
|
std::stringstream moveConstantsToTemporaries;
|
||||||
|
|
||||||
pDisassembly << "; Input usage declarations --\n";
|
pDisassembly << "; Input usage declarations --\n";
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
do {
|
do {
|
||||||
if (RegVUsage[i]) {
|
if (RegVIsUsedByShader[i]) {
|
||||||
DWORD PCUsageIndex = DeclAddressUsages[i][1];
|
if (!RegVIsPresentInDeclaration[i]) {
|
||||||
DWORD usage = DeclAddressUsages[i][0];
|
// Log test case and skip
|
||||||
|
// Any registers hitting this critera were already replaced with constant/temporary reads
|
||||||
// If an override exists, use it
|
// To correctly use the values given in SetVertexData4f.
|
||||||
if (RegVDeclUsage[i] >= 0) {
|
// We need to move these constant values to temporaries so they can be used as input alongside other constants!
|
||||||
usage = RegVDeclUsage[i];
|
// We count down from the highest available on the host because Xbox titles don't use values that high, and we read from c192 because Xbox uses 192 constants
|
||||||
|
static int temporaryRegisterBase = g_D3DCaps.VS20Caps.NumTemps - 13;
|
||||||
|
moveConstantsToTemporaries << "mov r" << (temporaryRegisterBase + i) << ", c" << (X_D3DVS_CONSTREG_VERTEXDATA4F_BASE + i) << "\n";
|
||||||
|
LOG_TEST_CASE("Shader uses undeclared Vertex Input Registers");
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream dclStream;
|
// dcl_texcoord can be useds for any user-defined data
|
||||||
switch (usage) {
|
// We need this because there is no reliable way to detect the real usage
|
||||||
case XTL::D3DDECLUSAGE_POSITION:
|
// Xbox has no concept of 'usage types', it only requires a list of attribute register numbers.
|
||||||
dclStream << "dcl_position" << (int)PCUsageIndex;
|
// So we treat them all as 'user-defined'
|
||||||
break;
|
pDisassembly << "dcl_texcoord" << i << " v" << i << "\n";
|
||||||
case XTL::D3DDECLUSAGE_BLENDWEIGHT:
|
|
||||||
dclStream << "dcl_blendweight";
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_BLENDINDICES:
|
|
||||||
dclStream << "dcl_blendindices";
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_NORMAL:
|
|
||||||
dclStream << "dcl_normal";
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_COLOR:
|
|
||||||
dclStream << "dcl_color" << (int)PCUsageIndex;
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_FOG:
|
|
||||||
dclStream << "dcl_fog";
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_TEXCOORD:
|
|
||||||
dclStream << "dcl_texcoord" << (int)PCUsageIndex;
|
|
||||||
break;
|
|
||||||
case XTL::D3DDECLUSAGE_PSIZE:
|
|
||||||
dclStream << "dcl_psize";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dclStream << "dcl_unknown ("<< (int)PCUsageIndex << ")";
|
|
||||||
LOG_TEST_CASE("Encountered unknown declaration");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDisassembly << dclStream.str() << " v" << i << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
} while (i < RegVUsage.size());
|
} while (i < RegVIsUsedByShader.size());
|
||||||
|
|
||||||
|
pDisassembly << moveConstantsToTemporaries.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < pShader->IntermediateCount && (i < VSH_MAX_INSTRUCTION_COUNT || !Truncate); i++)
|
for (int i = 0; i < pShader->IntermediateCount && (i < VSH_MAX_INSTRUCTION_COUNT || !Truncate); i++)
|
||||||
|
@ -1388,7 +1428,7 @@ static void VshRemoveScreenSpaceInstructions(VSH_XBOX_SHADER *pShader)
|
||||||
// If we couldn't find the generic screen space transformation we're
|
// If we couldn't find the generic screen space transformation we're
|
||||||
// assuming that the shader writes direct screen coordinates that must be
|
// assuming that the shader writes direct screen coordinates that must be
|
||||||
// normalized. This hack will fail if (a) the shader uses custom screen
|
// normalized. This hack will fail if (a) the shader uses custom screen
|
||||||
// space transformation, (b) reads r10 or r11 after we have written to
|
// space transformation, (b) reads r13 or r12 after we have written to
|
||||||
// them, or (c) doesn't reserve c-38 and c-37 for scale and offset.
|
// them, or (c) doesn't reserve c-38 and c-37 for scale and offset.
|
||||||
if(deleted != 3)
|
if(deleted != 3)
|
||||||
{
|
{
|
||||||
|
@ -1401,17 +1441,17 @@ static void VshRemoveScreenSpaceInstructions(VSH_XBOX_SHADER *pShader)
|
||||||
if( pIntermediate->Output.Type == IMD_OUTPUT_O &&
|
if( pIntermediate->Output.Type == IMD_OUTPUT_O &&
|
||||||
pIntermediate->Output.Address == OREG_OPOS)
|
pIntermediate->Output.Address == OREG_OPOS)
|
||||||
{
|
{
|
||||||
// Redirect output to r11.
|
// Redirect output to r12.
|
||||||
pIntermediate->Output.Type = IMD_OUTPUT_R;
|
pIntermediate->Output.Type = IMD_OUTPUT_R;
|
||||||
pIntermediate->Output.Address = 11;
|
pIntermediate->Output.Address = 12;
|
||||||
|
|
||||||
// Scale r11 to r10. (mul r10.[mask], r11, c58)
|
// Scale r12 to r13. (mul r13.[mask], r12, c58)
|
||||||
VSH_INTERMEDIATE_FORMAT MulIntermediate;
|
VSH_INTERMEDIATE_FORMAT MulIntermediate;
|
||||||
MulIntermediate.IsCombined = FALSE;
|
MulIntermediate.IsCombined = FALSE;
|
||||||
MulIntermediate.InstructionType = IMD_MAC;
|
MulIntermediate.InstructionType = IMD_MAC;
|
||||||
MulIntermediate.MAC = MAC_MUL;
|
MulIntermediate.MAC = MAC_MUL;
|
||||||
MulIntermediate.Output.Type = IMD_OUTPUT_R;
|
MulIntermediate.Output.Type = IMD_OUTPUT_R;
|
||||||
MulIntermediate.Output.Address = 10;
|
MulIntermediate.Output.Address = 13;
|
||||||
MulIntermediate.Output.Mask[0] = pIntermediate->Output.Mask[0];
|
MulIntermediate.Output.Mask[0] = pIntermediate->Output.Mask[0];
|
||||||
MulIntermediate.Output.Mask[1] = pIntermediate->Output.Mask[1];
|
MulIntermediate.Output.Mask[1] = pIntermediate->Output.Mask[1];
|
||||||
MulIntermediate.Output.Mask[2] = pIntermediate->Output.Mask[2];
|
MulIntermediate.Output.Mask[2] = pIntermediate->Output.Mask[2];
|
||||||
|
@ -1419,7 +1459,7 @@ static void VshRemoveScreenSpaceInstructions(VSH_XBOX_SHADER *pShader)
|
||||||
MulIntermediate.Parameters[0].Active = TRUE;
|
MulIntermediate.Parameters[0].Active = TRUE;
|
||||||
MulIntermediate.Parameters[0].IndexesWithA0_X = FALSE;
|
MulIntermediate.Parameters[0].IndexesWithA0_X = FALSE;
|
||||||
MulIntermediate.Parameters[0].Parameter.ParameterType = PARAM_R;
|
MulIntermediate.Parameters[0].Parameter.ParameterType = PARAM_R;
|
||||||
MulIntermediate.Parameters[0].Parameter.Address = 11;
|
MulIntermediate.Parameters[0].Parameter.Address = 12;
|
||||||
MulIntermediate.Parameters[0].Parameter.Neg = FALSE;
|
MulIntermediate.Parameters[0].Parameter.Neg = FALSE;
|
||||||
VshSetSwizzle(&MulIntermediate.Parameters[0], SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
|
VshSetSwizzle(&MulIntermediate.Parameters[0], SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
|
||||||
MulIntermediate.Parameters[1].Active = TRUE;
|
MulIntermediate.Parameters[1].Active = TRUE;
|
||||||
|
@ -1431,13 +1471,13 @@ static void VshRemoveScreenSpaceInstructions(VSH_XBOX_SHADER *pShader)
|
||||||
MulIntermediate.Parameters[2].Active = FALSE;
|
MulIntermediate.Parameters[2].Active = FALSE;
|
||||||
VshInsertIntermediate(pShader, &MulIntermediate, ++i);
|
VshInsertIntermediate(pShader, &MulIntermediate, ++i);
|
||||||
|
|
||||||
// Add offset with r10 to oPos (add oPos.[mask], r10, c59)
|
// Add offset with r13 to oPos (add oPos.[mask], r13, c59)
|
||||||
VSH_INTERMEDIATE_FORMAT AddIntermediate = MulIntermediate;
|
VSH_INTERMEDIATE_FORMAT AddIntermediate = MulIntermediate;
|
||||||
AddIntermediate.MAC = MAC_ADD;
|
AddIntermediate.MAC = MAC_ADD;
|
||||||
AddIntermediate.Output.Type = IMD_OUTPUT_O;
|
AddIntermediate.Output.Type = IMD_OUTPUT_O;
|
||||||
AddIntermediate.Output.Address = OREG_OPOS;
|
AddIntermediate.Output.Address = OREG_OPOS;
|
||||||
AddIntermediate.Parameters[0].Parameter.ParameterType = PARAM_R;
|
AddIntermediate.Parameters[0].Parameter.ParameterType = PARAM_R;
|
||||||
AddIntermediate.Parameters[0].Parameter.Address = 10;
|
AddIntermediate.Parameters[0].Parameter.Address = 13;
|
||||||
AddIntermediate.Parameters[1].Parameter.Address = ConvertCRegister(59);
|
AddIntermediate.Parameters[1].Parameter.Address = ConvertCRegister(59);
|
||||||
VshInsertIntermediate(pShader, &AddIntermediate, ++i);
|
VshInsertIntermediate(pShader, &AddIntermediate, ++i);
|
||||||
}
|
}
|
||||||
|
@ -1468,11 +1508,15 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
|
||||||
{
|
{
|
||||||
using namespace XTL;
|
using namespace XTL;
|
||||||
|
|
||||||
extern XTL::D3DCAPS g_D3DCaps;
|
|
||||||
|
|
||||||
const DWORD temporaryCount = g_D3DCaps.VS20Caps.NumTemps;
|
const DWORD temporaryCount = g_D3DCaps.VS20Caps.NumTemps;
|
||||||
|
|
||||||
boolean RUsage[VSH_MAX_TEMPORARY_REGISTERS] = { FALSE };
|
boolean RUsage[VSH_MAX_TEMPORARY_REGISTERS] = { FALSE };
|
||||||
|
// Set the last 13 register to used (they are used for SetVertexData4f Constants)
|
||||||
|
for (int i = 1; i <= 13; i++) {
|
||||||
|
RUsage[VSH_MAX_TEMPORARY_REGISTERS - i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: What about state shaders and such?
|
// TODO: What about state shaders and such?
|
||||||
pShader->ShaderHeader.Version = VERSION_VS;
|
pShader->ShaderHeader.Version = VERSION_VS;
|
||||||
|
|
||||||
|
@ -1569,7 +1613,16 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pIntermediate->Parameters[j].Parameter.ParameterType == PARAM_V) {
|
if (pIntermediate->Parameters[j].Parameter.ParameterType == PARAM_V) {
|
||||||
RegVUsage[pIntermediate->Parameters[j].Parameter.Address] = TRUE;
|
RegVIsUsedByShader[pIntermediate->Parameters[j].Parameter.Address] = TRUE;
|
||||||
|
|
||||||
|
if (!RegVIsPresentInDeclaration[pIntermediate->Parameters[j].Parameter.Address]) {
|
||||||
|
// This vertex register was not declared and therefore is not present within the Vertex Data object
|
||||||
|
// We read from temporary registers instead, that are set based on constants, in-turn, set by SetVertexData4f
|
||||||
|
// We count down from the highest available on the host because Xbox titles don't use values that high, and we read from c192 because Xbox uses 192 constants
|
||||||
|
static int temporaryRegisterBase = g_D3DCaps.VS20Caps.NumTemps - 13;
|
||||||
|
pIntermediate->Parameters[j].Parameter.ParameterType = PARAM_R;
|
||||||
|
pIntermediate->Parameters[j].Parameter.Address += temporaryRegisterBase;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1682,69 +1735,35 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int16_t R12Replacement = -1;
|
|
||||||
if(temporaryCount <= 12 && RUsage[12])
|
|
||||||
{
|
|
||||||
// Sigh, they absolutely had to use r12, didn't they?
|
|
||||||
for (int i = temporaryCount - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if(!RUsage[i])
|
|
||||||
{
|
|
||||||
R12Replacement = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(R12Replacement == -1)
|
|
||||||
{
|
|
||||||
EmuLog(LOG_LEVEL::WARNING, "Vertex shader uses all r registers, including r12; impossible to convert!");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < pShader->IntermediateCount; j++)
|
|
||||||
{
|
|
||||||
VSH_INTERMEDIATE_FORMAT* pIntermediate = &pShader->Intermediate[j];
|
|
||||||
if(pIntermediate->Output.Type == IMD_OUTPUT_O &&
|
|
||||||
pIntermediate->Output.Address == OREG_OPOS)
|
|
||||||
{
|
|
||||||
// Found instruction writing to oPos
|
|
||||||
pIntermediate->Output.Type = IMD_OUTPUT_R;
|
|
||||||
pIntermediate->Output.Address = R12Replacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int k = 0; k < 3; k++)
|
// Finally, iterate through the shader, replace all writes to oPos with writes to r12
|
||||||
{
|
// This fixes shaders that read from r12 expecting to see oPos
|
||||||
if(pIntermediate->Parameters[k].Active)
|
for (int i = 0; i < pShader->IntermediateCount; i++) {
|
||||||
{
|
VSH_INTERMEDIATE_FORMAT* pIntermediate = &pShader->Intermediate[i];
|
||||||
if(pIntermediate->Parameters[k].Parameter.ParameterType == PARAM_R &&
|
if (pIntermediate->Output.Type == IMD_OUTPUT_O && pIntermediate->Output.Address == OREG_OPOS) {
|
||||||
pIntermediate->Parameters[k].Parameter.Address == 12)
|
pIntermediate->Output.Type = IMD_OUTPUT_R;
|
||||||
{
|
pIntermediate->Output.Address = 12;
|
||||||
// Found a r12 used as a parameter; replace
|
|
||||||
pIntermediate->Parameters[k].Parameter.Address = R12Replacement;
|
|
||||||
}
|
|
||||||
else if(pIntermediate->Parameters[k].Parameter.ParameterType == PARAM_C &&
|
|
||||||
pIntermediate->Parameters[k].Parameter.Address == 58 &&
|
|
||||||
!pIntermediate->Parameters[k].IndexesWithA0_X)
|
|
||||||
{
|
|
||||||
// Found c-38, replace it with r12.w
|
|
||||||
pIntermediate->Parameters[k].Parameter.ParameterType = PARAM_R;
|
|
||||||
pIntermediate->Parameters[k].Parameter.Address = R12Replacement;
|
|
||||||
VshSetSwizzle(&pIntermediate->Parameters[k], SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Insert mov oPos, r## in the end
|
|
||||||
VSH_INTERMEDIATE_FORMAT *pOPosWriteBack = VshNewIntermediate(pShader);
|
|
||||||
pOPosWriteBack->InstructionType = IMD_ILU;
|
|
||||||
pOPosWriteBack->ILU = ILU_MOV;
|
|
||||||
pOPosWriteBack->MAC = MAC_NOP;
|
|
||||||
pOPosWriteBack->Output.Type = IMD_OUTPUT_O;
|
|
||||||
pOPosWriteBack->Output.Address = OREG_OPOS;
|
|
||||||
VshSetOutputMask(&pOPosWriteBack->Output, TRUE, TRUE, TRUE, TRUE);
|
|
||||||
pOPosWriteBack->Parameters[0].Active = TRUE;
|
|
||||||
pOPosWriteBack->Parameters[0].Parameter.ParameterType = PARAM_R;
|
|
||||||
pOPosWriteBack->Parameters[0].Parameter.Address = R12Replacement;
|
|
||||||
VshSetSwizzle(&pOPosWriteBack->Parameters[0], SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We append one additional instruction to mov oPos, r12
|
||||||
|
VSH_INTERMEDIATE_FORMAT MovIntermediate = {0};
|
||||||
|
MovIntermediate.MAC = MAC_MOV;
|
||||||
|
MovIntermediate.Output.Type = IMD_OUTPUT_O;
|
||||||
|
MovIntermediate.Output.Address = OREG_OPOS;
|
||||||
|
MovIntermediate.Output.Mask[0] = true;
|
||||||
|
MovIntermediate.Output.Mask[1] = true;
|
||||||
|
MovIntermediate.Output.Mask[2] = true;
|
||||||
|
MovIntermediate.Output.Mask[3] = true;
|
||||||
|
MovIntermediate.Parameters[0].Active = true;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.ParameterType = PARAM_R;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.Address = 12;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.Swizzle[0] = SWIZZLE_X;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.Swizzle[1] = SWIZZLE_Y;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.Swizzle[2] = SWIZZLE_Z;
|
||||||
|
MovIntermediate.Parameters[0].Parameter.Swizzle[3] = SWIZZLE_W;
|
||||||
|
VshInsertIntermediate(pShader, &MovIntermediate, pShader->IntermediateCount);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1773,93 +1792,6 @@ static DWORD VshGetDeclarationCount(DWORD *pDeclaration)
|
||||||
return Pos + 1;
|
return Pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define D3DDECLUSAGE_UNSUPPORTED ((D3DDECLUSAGE)-1)
|
|
||||||
|
|
||||||
XTL::D3DDECLUSAGE Xb2PCRegisterType
|
|
||||||
(
|
|
||||||
DWORD VertexRegister,
|
|
||||||
boolean IsFixedFunction,
|
|
||||||
BYTE& PCUsageIndex
|
|
||||||
)
|
|
||||||
{
|
|
||||||
using namespace XTL;
|
|
||||||
|
|
||||||
D3DDECLUSAGE PCRegisterType;
|
|
||||||
PCUsageIndex = 0;
|
|
||||||
|
|
||||||
if (!IsFixedFunction) {
|
|
||||||
DbgVshPrintf("%d", VertexRegister);
|
|
||||||
PCUsageIndex = DeclAddressUsages[VertexRegister][1];
|
|
||||||
return (D3DDECLUSAGE)DeclAddressUsages[VertexRegister][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (VertexRegister)
|
|
||||||
{
|
|
||||||
case X_D3DVSDE_VERTEX: // -1
|
|
||||||
DbgVshPrintf("D3DVSDE_VERTEX /* xbox ext. */");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_POSITION: // 0
|
|
||||||
DbgVshPrintf("D3DVSDE_POSITION");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_POSITION;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_BLENDWEIGHT: // 1
|
|
||||||
DbgVshPrintf("D3DVSDE_BLENDWEIGHT");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_BLENDWEIGHT;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_NORMAL: // 2
|
|
||||||
DbgVshPrintf("D3DVSDE_NORMAL");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_NORMAL;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_DIFFUSE: // 3
|
|
||||||
DbgVshPrintf("D3DVSDE_DIFFUSE");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 0;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_SPECULAR: // 4
|
|
||||||
DbgVshPrintf("D3DVSDE_SPECULAR");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 1;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_FOG: // 5
|
|
||||||
DbgVshPrintf("D3DVSDE_FOG");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_FOG;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_POINTSIZE: // 6
|
|
||||||
DbgVshPrintf("D3DVDSE_POINTSIZE");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_PSIZE;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_BACKDIFFUSE: // 7
|
|
||||||
DbgVshPrintf("D3DVSDE_BACKDIFFUSE /* xbox ext. */");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 2;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_BACKSPECULAR: // 8
|
|
||||||
DbgVshPrintf("D3DVSDE_BACKSPECULAR /* xbox ext. */");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 3;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_TEXCOORD0: // 9
|
|
||||||
DbgVshPrintf("D3DVSDE_TEXCOORD0");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 0;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_TEXCOORD1: // 10
|
|
||||||
DbgVshPrintf("D3DVSDE_TEXCOORD1");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 1;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_TEXCOORD2: // 11
|
|
||||||
DbgVshPrintf("D3DVSDE_TEXCOORD2");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 2;
|
|
||||||
break;
|
|
||||||
case X_D3DVSDE_TEXCOORD3: // 12
|
|
||||||
DbgVshPrintf("D3DVSDE_TEXCOORD3");
|
|
||||||
PCRegisterType = D3DDECLUSAGE_TEXCOORD; PCUsageIndex = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DbgVshPrintf("%d /* unknown register */", VertexRegister);
|
|
||||||
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PCRegisterType;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline DWORD VshGetTokenType(DWORD Token)
|
static inline DWORD VshGetTokenType(DWORD Token)
|
||||||
{
|
{
|
||||||
return (Token & X_D3DVSD_TOKENTYPEMASK) >> X_D3DVSD_TOKENTYPESHIFT;
|
return (Token & X_D3DVSD_TOKENTYPEMASK) >> X_D3DVSD_TOKENTYPESHIFT;
|
||||||
|
@ -1921,19 +1853,18 @@ static void VshConvertToken_TESSELATOR(
|
||||||
using namespace XTL;
|
using namespace XTL;
|
||||||
BYTE Index;
|
BYTE Index;
|
||||||
|
|
||||||
// TODO: Investigate why Xb2PCRegisterType is only used for fixed function vertex shaders
|
|
||||||
if(*pToken & X_D3DVSD_MASK_TESSUV)
|
if(*pToken & X_D3DVSD_MASK_TESSUV)
|
||||||
{
|
{
|
||||||
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
|
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
|
||||||
XTL::DWORD NewVertexRegister = VertexRegister;
|
XTL::DWORD NewVertexRegister = VertexRegister;
|
||||||
|
|
||||||
DbgVshPrintf("\tD3DVSD_TESSUV(");
|
DbgVshPrintf("\tD3DVSD_TESSUV(");
|
||||||
NewVertexRegister = Xb2PCRegisterType(VertexRegister, IsFixedFunction, Index);
|
NewVertexRegister = Xb2PCRegisterType(VertexRegister, Index);
|
||||||
DbgVshPrintf("),\n");
|
DbgVshPrintf("),\n");
|
||||||
|
|
||||||
// TODO : Expand on the setting of this TESSUV register element :
|
// TODO : Expand on the setting of this TESSUV register element :
|
||||||
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegister);
|
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegister);
|
||||||
pRecompiled->UsageIndex = Xb2PCRegisterType(NewVertexRegister, IsFixedFunction, Index); // TODO : Get Index from Xb2PCRegisterType
|
pRecompiled->UsageIndex =Index;
|
||||||
}
|
}
|
||||||
// D3DVSD_TESSNORMAL
|
// D3DVSD_TESSNORMAL
|
||||||
else
|
else
|
||||||
|
@ -1945,18 +1876,18 @@ static void VshConvertToken_TESSELATOR(
|
||||||
XTL::DWORD NewVertexRegisterOut = VertexRegisterOut;
|
XTL::DWORD NewVertexRegisterOut = VertexRegisterOut;
|
||||||
|
|
||||||
DbgVshPrintf("\tD3DVSD_TESSNORMAL(");
|
DbgVshPrintf("\tD3DVSD_TESSNORMAL(");
|
||||||
NewVertexRegisterIn = Xb2PCRegisterType(VertexRegisterIn, IsFixedFunction, Index);
|
NewVertexRegisterIn = Xb2PCRegisterType(VertexRegisterIn, Index);
|
||||||
DbgVshPrintf(", ");
|
DbgVshPrintf(", ");
|
||||||
// TODO : Expand on the setting of this TESSNORMAL input register element :
|
// TODO : Expand on the setting of this TESSNORMAL input register element :
|
||||||
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterIn);
|
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterIn);
|
||||||
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
|
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
|
||||||
NewVertexRegisterOut = Xb2PCRegisterType(VertexRegisterOut, IsFixedFunction, Index);
|
NewVertexRegisterOut = Xb2PCRegisterType(VertexRegisterOut, Index);
|
||||||
DbgVshPrintf("),\n");
|
DbgVshPrintf("),\n");
|
||||||
|
|
||||||
// TODO : Expand on the setting of this TESSNORMAL output register element :
|
// TODO : Expand on the setting of this TESSNORMAL output register element :
|
||||||
pRecompiled++;
|
pRecompiled++;
|
||||||
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterOut);
|
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterOut);
|
||||||
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
|
pRecompiled->UsageIndex = Index; // TODO : Get Index from Xb2PCRegisterType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2045,18 +1976,30 @@ static void VshConvertToken_STREAMDATA_REG(
|
||||||
{
|
{
|
||||||
using namespace XTL;
|
using namespace XTL;
|
||||||
|
|
||||||
extern XTL::D3DCAPS g_D3DCaps;
|
|
||||||
|
|
||||||
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
|
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
|
||||||
XTL::BYTE HostVertexRegister;
|
|
||||||
XTL::BOOL NeedPatching = FALSE;
|
XTL::BOOL NeedPatching = FALSE;
|
||||||
XTL::BYTE Index;
|
XTL::BYTE Index;
|
||||||
|
|
||||||
|
BYTE HostVertexRegisterType;
|
||||||
|
// If this is a fixed-function shader, use Xb2PCRegisterType
|
||||||
DbgVshPrintf("\t\tD3DVSD_REG(");
|
DbgVshPrintf("\t\tD3DVSD_REG(");
|
||||||
BYTE XboxVertexRegister = Xb2PCRegisterType(VertexRegister, IsFixedFunction, Index);
|
if (IsFixedFunction) {
|
||||||
HostVertexRegister = XboxVertexRegister;
|
HostVertexRegisterType = Xb2PCRegisterType(VertexRegister, Index);
|
||||||
|
} else {
|
||||||
|
// D3DDECLUSAGE_TEXCOORD can be useds for any user-defined data
|
||||||
|
// We need this because there is no reliable way to detect the real usage
|
||||||
|
// Xbox has no concept of 'usage types', it only requires a list of attribute register numbers.
|
||||||
|
// So we treat them all as 'user-defined' with an Index of the Vertex Register Index
|
||||||
|
// this prevents information loss in shaders due to non-matching dcl types!
|
||||||
|
HostVertexRegisterType = D3DDECLUSAGE_TEXCOORD;
|
||||||
|
Index = VertexRegister;
|
||||||
|
DbgVshPrintf("%d", Index);
|
||||||
|
}
|
||||||
DbgVshPrintf(", ");
|
DbgVshPrintf(", ");
|
||||||
|
|
||||||
|
// Add this register to the list of declared registers
|
||||||
|
RegVIsPresentInDeclaration[VertexRegister] = true;
|
||||||
|
|
||||||
XTL::DWORD XboxVertexElementDataType = (*pToken & X_D3DVSD_DATATYPEMASK) >> X_D3DVSD_DATATYPESHIFT;
|
XTL::DWORD XboxVertexElementDataType = (*pToken & X_D3DVSD_DATATYPEMASK) >> X_D3DVSD_DATATYPESHIFT;
|
||||||
XTL::BYTE HostVertexElementDataType = 0;
|
XTL::BYTE HostVertexElementDataType = 0;
|
||||||
XTL::WORD HostVertexElementByteSize = 0;
|
XTL::WORD HostVertexElementByteSize = 0;
|
||||||
|
@ -2072,32 +2015,21 @@ static void VshConvertToken_STREAMDATA_REG(
|
||||||
DbgVshPrintf("D3DVSDT_FLOAT2");
|
DbgVshPrintf("D3DVSDT_FLOAT2");
|
||||||
HostVertexElementDataType = D3DDECLTYPE_FLOAT2;
|
HostVertexElementDataType = D3DDECLTYPE_FLOAT2;
|
||||||
HostVertexElementByteSize = 2 * sizeof(FLOAT);
|
HostVertexElementByteSize = 2 * sizeof(FLOAT);
|
||||||
//HostVertexRegister = D3DDECLUSAGE_TEXCOORD;
|
|
||||||
break;
|
break;
|
||||||
case X_D3DVSDT_FLOAT3: // 0x32:
|
case X_D3DVSDT_FLOAT3: // 0x32:
|
||||||
DbgVshPrintf("D3DVSDT_FLOAT3");
|
DbgVshPrintf("D3DVSDT_FLOAT3");
|
||||||
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
|
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
|
||||||
HostVertexElementByteSize = 3 * sizeof(FLOAT);
|
HostVertexElementByteSize = 3 * sizeof(FLOAT);
|
||||||
|
|
||||||
/*
|
|
||||||
if (pPatchData->pCurrentVertexShaderStreamInfo->DeclPosition) {
|
|
||||||
pPatchData->pCurrentVertexShaderStreamInfo->DeclPosition = true;
|
|
||||||
HostVertexRegister = D3DDECLUSAGE_POSITION;
|
|
||||||
} else {
|
|
||||||
HostVertexRegister = D3DDECLUSAGE_NORMAL;
|
|
||||||
} */
|
|
||||||
break;
|
break;
|
||||||
case X_D3DVSDT_FLOAT4: // 0x42:
|
case X_D3DVSDT_FLOAT4: // 0x42:
|
||||||
DbgVshPrintf("D3DVSDT_FLOAT4");
|
DbgVshPrintf("D3DVSDT_FLOAT4");
|
||||||
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
|
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
|
||||||
HostVertexElementByteSize = 4 * sizeof(FLOAT);
|
HostVertexElementByteSize = 4 * sizeof(FLOAT);
|
||||||
//HostVertexRegister = D3DDECLUSAGE_COLOR;
|
|
||||||
break;
|
break;
|
||||||
case X_D3DVSDT_D3DCOLOR: // 0x40:
|
case X_D3DVSDT_D3DCOLOR: // 0x40:
|
||||||
DbgVshPrintf("D3DVSDT_D3DCOLOR");
|
DbgVshPrintf("D3DVSDT_D3DCOLOR");
|
||||||
HostVertexElementDataType = D3DDECLTYPE_D3DCOLOR;
|
HostVertexElementDataType = D3DDECLTYPE_D3DCOLOR;
|
||||||
HostVertexElementByteSize = 1 * sizeof(D3DCOLOR);
|
HostVertexElementByteSize = 1 * sizeof(D3DCOLOR);
|
||||||
//HostVertexRegister = D3DDECLUSAGE_COLOR;
|
|
||||||
break;
|
break;
|
||||||
case X_D3DVSDT_SHORT2: // 0x25:
|
case X_D3DVSDT_SHORT2: // 0x25:
|
||||||
DbgVshPrintf("D3DVSDT_SHORT2");
|
DbgVshPrintf("D3DVSDT_SHORT2");
|
||||||
|
@ -2272,14 +2204,9 @@ static void VshConvertToken_STREAMDATA_REG(
|
||||||
pRecompiled->Offset = pPatchData->pCurrentVertexShaderStreamInfo->HostVertexStride;
|
pRecompiled->Offset = pPatchData->pCurrentVertexShaderStreamInfo->HostVertexStride;
|
||||||
pRecompiled->Type = HostVertexElementDataType;
|
pRecompiled->Type = HostVertexElementDataType;
|
||||||
pRecompiled->Method = D3DDECLMETHOD_DEFAULT;
|
pRecompiled->Method = D3DDECLMETHOD_DEFAULT;
|
||||||
pRecompiled->Usage = HostVertexRegister;
|
pRecompiled->Usage = HostVertexRegisterType;
|
||||||
pRecompiled->UsageIndex = Index;
|
pRecompiled->UsageIndex = Index;
|
||||||
|
|
||||||
// If the xbox and host register number and usage differ, store an override!
|
|
||||||
if (XboxVertexRegister != HostVertexRegister) {
|
|
||||||
RegVDeclUsage[XboxVertexRegister] = HostVertexRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
pRecompiled++;
|
pRecompiled++;
|
||||||
|
|
||||||
pPatchData->pCurrentVertexShaderStreamInfo->HostVertexStride += HostVertexElementByteSize;
|
pPatchData->pCurrentVertexShaderStreamInfo->HostVertexStride += HostVertexElementByteSize;
|
||||||
|
@ -2363,7 +2290,7 @@ DWORD XTL::EmuRecompileVshDeclaration
|
||||||
CxbxVertexShaderInfo *pVertexShaderInfo
|
CxbxVertexShaderInfo *pVertexShaderInfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegVDeclUsage.fill(-1);
|
RegVIsPresentInDeclaration.fill(false);
|
||||||
|
|
||||||
// First of all some info:
|
// First of all some info:
|
||||||
// We have to figure out which flags are set and then
|
// We have to figure out which flags are set and then
|
||||||
|
@ -2413,8 +2340,6 @@ DWORD XTL::EmuRecompileVshDeclaration
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern XTL::D3DCAPS g_D3DCaps;
|
|
||||||
|
|
||||||
// recompile xbox vertex shader function
|
// recompile xbox vertex shader function
|
||||||
extern HRESULT XTL::EmuRecompileVshFunction
|
extern HRESULT XTL::EmuRecompileVshFunction
|
||||||
(
|
(
|
||||||
|
@ -2444,9 +2369,9 @@ extern HRESULT XTL::EmuRecompileVshFunction
|
||||||
DWORD* pDeclEnd = (DWORD*)((BYTE*)pDeclToken + DeclarationSize);
|
DWORD* pDeclEnd = (DWORD*)((BYTE*)pDeclToken + DeclarationSize);
|
||||||
do {
|
do {
|
||||||
DWORD regNum = *pDeclToken & X_D3DVSD_VERTEXREGMASK;
|
DWORD regNum = *pDeclToken & X_D3DVSD_VERTEXREGMASK;
|
||||||
if (regNum >= temporaryCount /*12*/) {
|
if (regNum >= temporaryCount /*12 for D3D8, D3D9 value depends on host GPU */) {
|
||||||
// Lego Star Wars hits this
|
// Lego Star Wars hits this
|
||||||
LOG_TEST_CASE("RegNum > 12");
|
LOG_TEST_CASE("RegNum > NumTemps");
|
||||||
pDeclToken++;
|
pDeclToken++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2489,7 +2414,7 @@ extern HRESULT XTL::EmuRecompileVshFunction
|
||||||
|
|
||||||
if(SUCCEEDED(hRet))
|
if(SUCCEEDED(hRet))
|
||||||
{
|
{
|
||||||
RegVUsage.fill(false);
|
RegVIsUsedByShader.fill(false);
|
||||||
|
|
||||||
for (pToken = (DWORD*)((uint8_t*)pFunction + sizeof(VSH_SHADER_HEADER)); !EOI; pToken += VSH_INSTRUCTION_SIZE)
|
for (pToken = (DWORD*)((uint8_t*)pFunction + sizeof(VSH_SHADER_HEADER)); !EOI; pToken += VSH_INSTRUCTION_SIZE)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue