Merge pull request #1200 from PatrickvL/d3d9_vertex_shader

More porting work towards Direct3D 9
This commit is contained in:
Luke Usher 2018-05-29 13:33:22 +01:00 committed by GitHub
commit 86a3f88cf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 647 additions and 274 deletions

View File

@ -124,7 +124,7 @@ struct {
// D3D based variables
static GUID g_ddguid; // DirectDraw driver GUID
static XTL::IDirect3D *g_pDirect3D = nullptr;
static XTL::D3DCAPS g_D3DCaps; // Direct3D Caps
static XTL::D3DCAPS g_D3DCaps = {}; // Direct3D Caps
// wireframe toggle
static int g_iWireframe = 0;
@ -7579,6 +7579,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawVertices)
// test-case : BLiNX: the time sweeper
// test-case : Halo - Combat Evolved
// test-case : Worms 3D Special Edition
// test-case : XDK sample Lensflare
DrawContext.dwStartVertex = StartVertex; // Breakpoint location for testing.
}
@ -8111,7 +8112,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderTarget)
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderTarget");
if (FAILED(hRet)) {
// If Direct3D 9 SetRenderTarget failed, skip setting depth stencil
return hRet;
return;
}
}
@ -9521,10 +9522,14 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetPixelShaderConstant_4)
if(g_BuildVersion <= 4361)
Register += 96;
#ifdef CXBX_USE_D3D9
HRESULT hRet = g_pD3DDevice->SetPixelShaderConstantF
#else
HRESULT hRet = g_pD3DDevice->SetPixelShaderConstant
#endif
(
Register,
pConstantData,
(PixelShaderConstantType*)pConstantData,
ConstantCount
);
//DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetPixelShaderConstant");

View File

@ -4107,10 +4107,9 @@ PSH_RECOMPILED_SHADER XTL_EmuRecompilePshDef(XTL::X_D3DPIXELSHADERDEF *pPSDef)
uint32 PSVersion = D3DPS_VERSION(1, 3); // Use pixel shader model 1.3 by default
#if 0 // Once PS.1.4 can be generated, enable this :
XTL::D3DCAPS g_D3DCaps = {};
if (g_pD3DDevice->GetDeviceCaps(&g_D3DCaps) == D3D_OK) {
PSVersion = g_D3DCaps.PixelShaderVersion;
}
extern XTL::D3DCAPS g_D3DCaps;
PSVersion = g_D3DCaps.PixelShaderVersion;
#endif
// TODO : Make the pixel shader version configurable
@ -4338,10 +4337,15 @@ VOID XTL::DxbxUpdateActivePixelShader() // NOPATCH
// TODO : Avoid the following setter if it's no different from the previous update (this might speed things up)
// Set the value locally in this register :
#ifdef CXBX_USE_D3D9
g_pD3DDevice->SetPixelShaderConstantF(Register_, (float*)(&fColor), 1);
g_pD3DDevice->SetPixelShaderConstantF
#else
g_pD3DDevice->SetPixelShaderConstant(Register_, &fColor, 1);
g_pD3DDevice->SetPixelShaderConstant
#endif
(
Register_,
(PixelShaderConstantType*)(&fColor),
1
);
}
}
}

View File

@ -268,12 +268,36 @@ UINT XTL::CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pDrawContext
return 0;
}
inline FLOAT PackedIntToFloat(const int value, const FLOAT PosFactor, const FLOAT NegFactor)
{
if (value >= 0) {
return ((FLOAT)value) / PosFactor;
}
else {
return ((FLOAT)value) / NegFactor;
}
}
inline FLOAT NormShortToFloat(const SHORT value)
{
return PackedIntToFloat((int)value, 32767.0f, 32768.0f);
}
inline FLOAT ByteToFloat(const BYTE value)
{
return ((FLOAT)value) / 255.0f;
}
void XTL::CxbxVertexBufferConverter::ConvertStream
(
CxbxDrawContext *pDrawContext,
UINT uiStream
)
{
#if CXBX_USE_D3D9
extern XTL::D3DCAPS g_D3DCaps;
#endif
bool bVshHandleIsFVF = VshHandleIsFVF(pDrawContext->hVertexShader);
DWORD XboxFVF = bVshHandleIsFVF ? pDrawContext->hVertexShader : 0;
// Texture normalization can only be set for FVF shaders
@ -391,128 +415,250 @@ void XTL::CxbxVertexBufferConverter::ConvertStream
if (bNeedVertexPatching) {
// assert(bNeedStreamCopy || "bNeedVertexPatching implies bNeedStreamCopy (but copies via conversions");
for (uint32 uiVertex = 0; uiVertex < uiVertexCount; uiVertex++) {
uint08 *pXboxVertex = &pXboxVertexData[uiVertex * uiXboxVertexStride];
FLOAT *pHostVertexAsFloat = (FLOAT*)(&pHostVertexData[uiVertex * uiHostVertexStride]);
uint08 *pXboxVertexAsByte = &pXboxVertexData[uiVertex * uiXboxVertexStride];
uint08 *pHostVertexAsByte = &pHostVertexData[uiVertex * uiHostVertexStride];
for (UINT uiElement = 0; uiElement < pVertexShaderStreamInfo->NumberOfVertexElements; uiElement++) {
FLOAT *pXboxVertexAsFloat = (FLOAT*)pXboxVertexAsByte;
SHORT *pXboxVertexAsShort = (SHORT*)pXboxVertexAsByte;
int XboxElementByteSize = pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize;
FLOAT *pHostVertexAsFloat = (FLOAT*)pHostVertexAsByte;
SHORT *pHostVertexAsShort = (SHORT*)pHostVertexAsByte;
// Dxbx note : The following code handles only the D3DVSDT enums that need conversion;
// All other cases are catched by the memcpy in the default-block.
switch (pVertexShaderStreamInfo->VertexElements[uiElement].XboxType) {
case X_D3DVSDT_NORMPACKED3: { // 0x16: // Make it FLOAT3
// Hit by Dashboard
int32 iPacked = ((int32 *)pXboxVertex)[0];
// Cxbx note : to make each component signed, two need to be shifted towards the sign-bit first :
pHostVertexAsFloat[0] = ((FLOAT)((iPacked << 21) >> 21)) / 1023.0f;
pHostVertexAsFloat[1] = ((FLOAT)((iPacked << 10) >> 21)) / 1023.0f;
pHostVertexAsFloat[2] = ((FLOAT)((iPacked ) >> 22)) / 511.0f;
pXboxVertex += 1 * sizeof(int32);
break;
}
case X_D3DVSDT_SHORT1: { // 0x15: // Make it SHORT2 and set the second short to 0
//memcpy(pHostVertexAsFloat, pXboxVertex, pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize);
((SHORT *)pHostVertexAsFloat)[0] = ((SHORT*)pXboxVertex)[0];
((SHORT *)pHostVertexAsFloat)[1] = 0x00;
pXboxVertex += 1 * sizeof(SHORT);
break;
}
case X_D3DVSDT_SHORT3: { // 0x35: // Make it a SHORT4 and set the fourth short to 1
// Hit by Turok
//memcpy(pHostVertexAsFloat, pXboxVertex, pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize);
((SHORT *)pHostVertexAsFloat)[0] = ((SHORT*)pXboxVertex)[0];
((SHORT *)pHostVertexAsFloat)[1] = ((SHORT*)pXboxVertex)[1];
((SHORT *)pHostVertexAsFloat)[2] = ((SHORT*)pXboxVertex)[2];
((SHORT *)pHostVertexAsFloat)[3] = 0x01; // Turok verified (character disappears when this is 32767)
pXboxVertex += 3 * sizeof(SHORT);
break;
}
case X_D3DVSDT_PBYTE1: { // 0x14: // Make it FLOAT1
pHostVertexAsFloat[0] = ((FLOAT)((BYTE*)pXboxVertex)[0]) / 255.0f;
pXboxVertex += 1 * sizeof(BYTE);
break;
}
case X_D3DVSDT_PBYTE2: { // 0x24: // Make it FLOAT2
pHostVertexAsFloat[0] = ((FLOAT)((BYTE*)pXboxVertex)[0]) / 255.0f;
pHostVertexAsFloat[1] = ((FLOAT)((BYTE*)pXboxVertex)[1]) / 255.0f;
pXboxVertex += 2 * sizeof(BYTE);
break;
}
case X_D3DVSDT_PBYTE3: { // 0x34: // Make it FLOAT3
// Hit by Turok
pHostVertexAsFloat[0] = ((FLOAT)((BYTE*)pXboxVertex)[0]) / 255.0f;
pHostVertexAsFloat[1] = ((FLOAT)((BYTE*)pXboxVertex)[1]) / 255.0f;
pHostVertexAsFloat[2] = ((FLOAT)((BYTE*)pXboxVertex)[2]) / 255.0f;
pXboxVertex += 3 * sizeof(BYTE);
break;
}
case X_D3DVSDT_PBYTE4: { // 0x44: // Make it FLOAT4
// Hit by Jet Set Radio Future
pHostVertexAsFloat[0] = ((FLOAT)((BYTE*)pXboxVertex)[0]) / 255.0f;
pHostVertexAsFloat[1] = ((FLOAT)((BYTE*)pXboxVertex)[1]) / 255.0f;
pHostVertexAsFloat[2] = ((FLOAT)((BYTE*)pXboxVertex)[2]) / 255.0f;
pHostVertexAsFloat[3] = ((FLOAT)((BYTE*)pXboxVertex)[3]) / 255.0f;
pXboxVertex += 4 * sizeof(BYTE);
break;
}
case X_D3DVSDT_NORMSHORT1: { // 0x11: // Make it FLOAT1
case X_D3DVSDT_NORMSHORT1: { // 0x11:
// Test-cases : Halo - Combat Evolved
pHostVertexAsFloat[0] = ((FLOAT)((SHORT*)pXboxVertex)[0]) / 32767.0f;
//pHostVertexAsFloat[1] = 0.0f; // Would be needed for FLOAT2
pXboxVertex += 1 * sizeof(SHORT);
XboxElementByteSize = 1 * sizeof(SHORT);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT2N) {
// Make it SHORT2N
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = 0;
}
else
#endif
{
// Make it FLOAT1
pHostVertexAsFloat[0] = NormShortToFloat(pXboxVertexAsShort[0]);
//pHostVertexAsFloat[1] = 0.0f; // Would be needed for FLOAT2
}
break;
}
#if !DXBX_USE_D3D9 // No need for patching in D3D9
case X_D3DVSDT_NORMSHORT2: { // 0x21: // Make it FLOAT2
case X_D3DVSDT_NORMSHORT2: { // 0x21:
// Test-cases : Baldur's Gate: Dark Alliance 2, F1 2002, Gun, Halo - Combat Evolved, Scrapland
pHostVertexAsFloat[0] = ((FLOAT)((SHORT*)pXboxVertex)[0]) / 32767.0f;
pHostVertexAsFloat[1] = ((FLOAT)((SHORT*)pXboxVertex)[1]) / 32767.0f;
pXboxVertex += 2 * sizeof(SHORT);
XboxElementByteSize = 2 * sizeof(SHORT);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT2N) {
// No need for patching when D3D9 supports D3DDECLTYPE_SHORT2N
// TODO : goto default; // ??
//assert(XboxElementByteSize == 2 * sizeof(SHORT));
//memcpy(pHostVertexAsByte, pXboxVertexAsByte, XboxElementByteSize);
// Make it SHORT2N
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = pXboxVertexAsShort[1];
}
else
#endif
{
// Make it FLOAT2
pHostVertexAsFloat[0] = NormShortToFloat(pXboxVertexAsShort[0]);
pHostVertexAsFloat[1] = NormShortToFloat(pXboxVertexAsShort[1]);
}
break;
}
#endif
case X_D3DVSDT_NORMSHORT3: { // 0x31: // Make it FLOAT3
case X_D3DVSDT_NORMSHORT3: { // 0x31:
// Test-cases : Cel Damage, Constantine, Destroy All Humans!
pHostVertexAsFloat[0] = ((FLOAT)((SHORT*)pXboxVertex)[0]) / 32767.0f;
pHostVertexAsFloat[1] = ((FLOAT)((SHORT*)pXboxVertex)[1]) / 32767.0f;
pHostVertexAsFloat[2] = ((FLOAT)((SHORT*)pXboxVertex)[2]) / 32767.0f;
pXboxVertex += 3 * sizeof(SHORT);
break;
}
#if !DXBX_USE_D3D9 // No need for patching in D3D9
case X_D3DVSDT_NORMSHORT4: { // 0x41: // Make it FLOAT4
LOG_TEST_CASE("X_D3DVSDT_NORMSHORT4"); // UNTESTED - Need test-case!
pHostVertexAsFloat[0] = ((FLOAT)((SHORT*)pXboxVertex)[0]) / 32767.0f;
pHostVertexAsFloat[1] = ((FLOAT)((SHORT*)pXboxVertex)[1]) / 32767.0f;
pHostVertexAsFloat[2] = ((FLOAT)((SHORT*)pXboxVertex)[2]) / 32767.0f;
pHostVertexAsFloat[3] = ((FLOAT)((SHORT*)pXboxVertex)[3]) / 32767.0f;
pXboxVertex += 4 * sizeof(SHORT);
break;
}
XboxElementByteSize = 3 * sizeof(SHORT);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT4N) {
// Make it SHORT4N
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = pXboxVertexAsShort[1];
pHostVertexAsShort[2] = pXboxVertexAsShort[2];
pHostVertexAsShort[3] = 32767; // TODO : verify
}
else
#endif
case X_D3DVSDT_FLOAT2H: { // 0x72: // Make it FLOAT4 and set the third float to 0.0
pHostVertexAsFloat[0] = ((FLOAT*)pXboxVertex)[0];
pHostVertexAsFloat[1] = ((FLOAT*)pXboxVertex)[1];
{
// Make it FLOAT3
pHostVertexAsFloat[0] = NormShortToFloat(pXboxVertexAsShort[0]);
pHostVertexAsFloat[1] = NormShortToFloat(pXboxVertexAsShort[1]);
pHostVertexAsFloat[2] = NormShortToFloat(pXboxVertexAsShort[2]);
}
break;
}
case X_D3DVSDT_NORMSHORT4: { // 0x41:
// Test-cases : Judge Dredd: Dredd vs Death, NHL Hitz 2002, Silent Hill 2, Sneakers, Tony Hawk Pro Skater 4
XboxElementByteSize = 4 * sizeof(SHORT);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT4N) {
// No need for patching when D3D9 supports D3DDECLTYPE_SHORT4N
// TODO : goto default; // ??
//assert(XboxElementByteSize == 4 * sizeof(SHORT));
//memcpy(pHostVertexAsByte, pXboxVertexAsByte, XboxElementByteSize);
// Make it SHORT4N
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = pXboxVertexAsShort[1];
pHostVertexAsShort[2] = pXboxVertexAsShort[2];
pHostVertexAsShort[3] = pXboxVertexAsShort[3];
}
else
#endif
{
// Make it FLOAT4
pHostVertexAsFloat[0] = NormShortToFloat(pXboxVertexAsShort[0]);
pHostVertexAsFloat[1] = NormShortToFloat(pXboxVertexAsShort[1]);
pHostVertexAsFloat[2] = NormShortToFloat(pXboxVertexAsShort[2]);
pHostVertexAsFloat[3] = NormShortToFloat(pXboxVertexAsShort[3]);
}
break;
}
case X_D3DVSDT_NORMPACKED3: { // 0x16:
// Test-cases : Dashboard
XboxElementByteSize = 1 * sizeof(int32);
// Make it FLOAT3
union {
int32 value;
struct {
int x : 11;
int y : 11;
int z : 10;
};
} NormPacked3;
NormPacked3.value = ((int32 *)pXboxVertexAsByte)[0];
pHostVertexAsFloat[0] = PackedIntToFloat(NormPacked3.x, 1023.0f, 1024.f);
pHostVertexAsFloat[1] = PackedIntToFloat(NormPacked3.y, 1023.0f, 1024.f);
pHostVertexAsFloat[2] = PackedIntToFloat(NormPacked3.z, 511.0f, 512.f);
break;
}
case X_D3DVSDT_SHORT1: { // 0x15:
XboxElementByteSize = 1 * sizeof(SHORT);
// Make it SHORT2 and set the second short to 0
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = 0;
break;
}
case X_D3DVSDT_SHORT3: { // 0x35:
// Test-cases : Turok
XboxElementByteSize = 3 * sizeof(SHORT);
// Make it a SHORT4 and set the fourth short to 1
pHostVertexAsShort[0] = pXboxVertexAsShort[0];
pHostVertexAsShort[1] = pXboxVertexAsShort[1];
pHostVertexAsShort[2] = pXboxVertexAsShort[2];
pHostVertexAsShort[3] = 1; // Turok verified (character disappears when this is 32767)
break;
}
case X_D3DVSDT_PBYTE1: { // 0x14:
XboxElementByteSize = 1 * sizeof(BYTE);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
// Make it UBYTE4N
pHostVertexAsByte[0] = pXboxVertexAsByte[0];
pHostVertexAsByte[1] = 0;
pHostVertexAsByte[2] = 0;
pHostVertexAsByte[3] = 255; // TODO : Verify
}
else
#endif
{
// Make it FLOAT1
pHostVertexAsFloat[0] = ByteToFloat(pXboxVertexAsByte[0]);
}
break;
}
case X_D3DVSDT_PBYTE2: { // 0x24:
XboxElementByteSize = 2 * sizeof(BYTE);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
// Make it UBYTE4N
pHostVertexAsByte[0] = pXboxVertexAsByte[0];
pHostVertexAsByte[1] = pXboxVertexAsByte[1];
pHostVertexAsByte[2] = 0;
pHostVertexAsByte[3] = 255; // TODO : Verify
}
else
#endif
{
// Make it FLOAT2
pHostVertexAsFloat[0] = ByteToFloat(pXboxVertexAsByte[0]);
pHostVertexAsFloat[1] = ByteToFloat(pXboxVertexAsByte[1]);
}
break;
}
case X_D3DVSDT_PBYTE3: { // 0x34:
// Test-cases : Turok
XboxElementByteSize = 3 * sizeof(BYTE);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
// Make it UBYTE4N
pHostVertexAsByte[0] = pXboxVertexAsByte[0];
pHostVertexAsByte[1] = pXboxVertexAsByte[1];
pHostVertexAsByte[2] = pXboxVertexAsByte[2];
pHostVertexAsByte[3] = 255; // TODO : Verify
}
else
#endif
{
// Make it FLOAT3
pHostVertexAsFloat[0] = ByteToFloat(pXboxVertexAsByte[0]);
pHostVertexAsFloat[1] = ByteToFloat(pXboxVertexAsByte[1]);
pHostVertexAsFloat[2] = ByteToFloat(pXboxVertexAsByte[2]);
}
break;
}
case X_D3DVSDT_PBYTE4: { // 0x44:
// Test-case : Jet Set Radio Future
XboxElementByteSize = 4 * sizeof(BYTE);
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
// No need for patching when D3D9 supports D3DDECLTYPE_UBYTE4N
// TODO : goto default; // ??
//assert(XboxElementByteSize == 4 * sizeof(BYTE));
//memcpy(pHostVertexAsByte, pXboxVertexAsByte, XboxElementByteSize);
// Make it UBYTE4N
pHostVertexAsByte[0] = pXboxVertexAsByte[0];
pHostVertexAsByte[1] = pXboxVertexAsByte[1];
pHostVertexAsByte[2] = pXboxVertexAsByte[2];
pHostVertexAsByte[3] = pXboxVertexAsByte[3];
}
else
#endif
{
// Make it FLOAT4
pHostVertexAsFloat[0] = ByteToFloat(pXboxVertexAsByte[0]);
pHostVertexAsFloat[1] = ByteToFloat(pXboxVertexAsByte[1]);
pHostVertexAsFloat[2] = ByteToFloat(pXboxVertexAsByte[2]);
pHostVertexAsFloat[3] = ByteToFloat(pXboxVertexAsByte[3]);
}
break;
}
case X_D3DVSDT_FLOAT2H: { // 0x72:
XboxElementByteSize = 3 * sizeof(FLOAT);
// Make it FLOAT4 and set the third float to 0.0
pHostVertexAsFloat[0] = pXboxVertexAsFloat[0];
pHostVertexAsFloat[1] = pXboxVertexAsFloat[1];
pHostVertexAsFloat[2] = 0.0f;
pHostVertexAsFloat[3] = ((FLOAT*)pXboxVertex)[2];
pXboxVertex += 3 * sizeof(FLOAT);
pHostVertexAsFloat[3] = pXboxVertexAsFloat[2];
break;
}
/*TODO
case X_D3DVSDT_NONE: { // 0x02:
printf("D3DVSDT_NONE / xbox ext. nsp /");
dwNewDataType = 0xFF;
case X_D3DVSDT_NONE: { // 0x02: // Skip it
// Test-case : WWE RAW2
LOG_TEST_CASE("X_D3DVSDT_NONE");
break;
}
*/
default: {
// Generic 'conversion' - just make a copy :
memcpy(pHostVertexAsFloat, pXboxVertex, pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize);
pXboxVertex += pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize;
memcpy(pHostVertexAsByte, pXboxVertexAsByte, XboxElementByteSize);
break;
}
} // switch
// Increment the new pointer :
pHostVertexAsFloat = (FLOAT*)((uintptr_t)pHostVertexAsFloat + pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize);
// Increment the Xbox pointer :
pXboxVertexAsByte += XboxElementByteSize;
// Increment the host pointer :
pHostVertexAsByte += pVertexShaderStreamInfo->VertexElements[uiElement].HostByteSize;
} // for NumberOfVertexElements
} // for uiVertexCount
}

View File

@ -44,6 +44,10 @@
#include <unordered_map>
#ifdef CXBX_USE_VS30
//#define CXBX_USE_VS30 // Separate the port to Vertex Shader model 3.0 from the port to Direct3D9
#endif
// ****************************************************************************
// * Vertex shader function recompiler
// ****************************************************************************
@ -56,6 +60,11 @@
#define VSH_XBOX_MAX_INSTRUCTION_COUNT 136 // The maximum Xbox shader instruction count
#define VSH_MAX_INTERMEDIATE_COUNT 1024 // The maximum number of intermediate format slots
#define X_D3DVSD_MASK_TESSUV 0x10000000
#define X_D3DVSD_MASK_SKIP 0x10000000 // Skips (normally) dwords
#define X_D3DVSD_MASK_SKIPBYTES 0x08000000 // Skips bytes (no, really?!)
#define X_D3DVSD_STREAMTESSMASK (1 << 28)
typedef enum _VSH_SWIZZLE
{
SWIZZLE_X = 0,
@ -785,7 +794,11 @@ static void VshWriteShader(VSH_XBOX_SHADER *pShader,
switch(pShader->ShaderHeader.Version)
{
case VERSION_VS:
#ifdef CXBX_USE_VS30
DisassemblyPos += sprintf(pDisassembly + DisassemblyPos, "vs.3.0\n");
#else
DisassemblyPos += sprintf(pDisassembly + DisassemblyPos, "vs.1.1\n");
#endif
break;
case VERSION_XVS:
DisassemblyPos += sprintf(pDisassembly + DisassemblyPos, "xvs.1.1\n");
@ -1629,7 +1642,7 @@ static DWORD VshGetDeclarationSize(DWORD *pDeclaration)
{
Pos++;
}
return (Pos + 1) * sizeof(DWORD);
return Pos + 1;
}
#ifndef CXBX_USE_D3D9
@ -1785,7 +1798,10 @@ static inline DWORD VshGetVertexStream(DWORD Token)
return (Token & X_D3DVSD_STREAMNUMBERMASK) >> X_D3DVSD_STREAMNUMBERSHIFT;
}
static void VshConvertToken_NOP(DWORD *pToken)
static void VshConvertToken_NOP(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled
)
{
// D3DVSD_NOP
if(*pToken != DEF_VSH_NOP)
@ -1795,33 +1811,52 @@ static void VshConvertToken_NOP(DWORD *pToken)
DbgVshPrintf("\tD3DVSD_NOP(),\n");
}
static DWORD VshConvertToken_CONSTMEM(DWORD *pToken)
static DWORD VshConvertToken_CONSTMEM(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled
)
{
using namespace XTL;
// D3DVSD_CONST
DbgVshPrintf("\tD3DVSD_CONST(");
DWORD ConstantAddress = (*pToken & X_D3DVSD_CONSTADDRESSMASK) >> X_D3DVSD_CONSTADDRESSSHIFT;
DWORD Count = (*pToken & X_D3DVSD_CONSTCOUNTMASK) >> X_D3DVSD_CONSTCOUNTSHIFT;
DbgVshPrintf("%d, %d),\n", ConstantAddress, Count);
//pToken = D3DVSD_CONST(ConstantAddress, Count);
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = D3DVSD_CONST(ConstantAddress, Count);
#endif
for (uint i = 0; i < Count; i++)
{
pToken++;
pRecompiled++;
DbgVshPrintf("\t0x%08X,\n", pToken);
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = *pToken;
#endif
}
return Count;
}
static void VshConverToken_TESSELATOR(DWORD *pToken,
boolean IsFixedFunction)
static void VshConvertToken_TESSELATOR(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled,
boolean IsFixedFunction
)
{
using namespace XTL;
// TODO: Investigate why Xb2PCRegisterType is only used for fixed function vertex shaders
// D3DVSD_TESSUV
if(*pToken & 0x10000000)
if(*pToken & X_D3DVSD_MASK_TESSUV)
{
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
XTL::DWORD NewVertexRegister = VertexRegister;
@ -1830,8 +1865,14 @@ static void VshConverToken_TESSELATOR(DWORD *pToken,
NewVertexRegister = Xb2PCRegisterType(VertexRegister, IsFixedFunction);
DbgVshPrintf("),\n");
*pToken = D3DVSD_TESSUV(NewVertexRegister);
}
#ifdef CXBX_USE_D3D9
// TODO : Expand on the setting of this TESSUV register element :
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegister);
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
#else
*pRecompiled = D3DVSD_TESSUV(NewVertexRegister);
#endif
}
// D3DVSD_TESSNORMAL
else
{
@ -1844,10 +1885,23 @@ static void VshConverToken_TESSELATOR(DWORD *pToken,
DbgVshPrintf("\tD3DVSD_TESSNORMAL(");
NewVertexRegisterIn = Xb2PCRegisterType(VertexRegisterIn, IsFixedFunction);
DbgVshPrintf(", ");
#ifdef CXBX_USE_D3D9
// TODO : Expand on the setting of this TESSNORMAL input register element :
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterIn);
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
#endif
NewVertexRegisterOut = Xb2PCRegisterType(VertexRegisterOut, IsFixedFunction);
DbgVshPrintf("),\n");
*pToken = D3DVSD_TESSNORMAL(NewVertexRegisterIn, NewVertexRegisterOut);
}
#ifdef CXBX_USE_D3D9
// TODO : Expand on the setting of this TESSNORMAL output register element :
pRecompiled++;
pRecompiled->Usage = D3DDECLUSAGE(NewVertexRegisterOut);
pRecompiled->UsageIndex = 0; // TODO : Get Index from Xb2PCRegisterType
#else
*pRecompiled = D3DVSD_TESSNORMAL(NewVertexRegisterIn, NewVertexRegisterOut);
#endif
}
}
static void VshEndPreviousStreamPatch(CxbxVertexShaderPatch *pPatchData)
@ -1857,13 +1911,24 @@ static void VshEndPreviousStreamPatch(CxbxVertexShaderPatch *pPatchData)
}
}
static void VshConvertToken_STREAM(DWORD *pToken,
CxbxVertexShaderPatch *pPatchData)
static void VshConvertToken_STREAM(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled,
CxbxVertexShaderPatch *pPatchData
)
{
using namespace XTL;
// D3DVSD_STREAM_TESS
if(*pToken & D3DVSD_STREAMTESSMASK)
if(*pToken & X_D3DVSD_STREAMTESSMASK)
{
DbgVshPrintf("\tD3DVSD_STREAM_TESS(),\n");
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = D3DVSD_STREAM_TESS();
#endif
}
// D3DVSD_STREAM
else
@ -1881,40 +1946,80 @@ static void VshConvertToken_STREAM(DWORD *pToken,
// Dxbx note : Use Dophin(s), FieldRender, MatrixPaletteSkinning and PersistDisplay as a testcase
DbgVshPrintf("\tD3DVSD_STREAM(%u),\n", StreamNumber);
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = D3DVSD_STREAM(StreamNumber);
#endif
pPatchData->pVertexShaderInfoToSet->NumberOfVertexStreams++;
// TODO : Keep a bitmask for all StreamNumber's seen?
}
}
static void VshConvertToken_STREAMDATA_SKIP(DWORD *pToken)
static void VshConvertToken_STREAMDATA_SKIP(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled
)
{
using namespace XTL;
XTL::DWORD SkipCount = (*pToken & X_D3DVSD_SKIPCOUNTMASK) >> X_D3DVSD_SKIPCOUNTSHIFT;
DbgVshPrintf("\tD3DVSD_SKIP(%d),\n", SkipCount);
// No need to convert; D3DVSD_SKIP is encoded identically on host Direct3D8.
#ifdef CXBX_USE_D3D9
// TODO : Expand on the setting of this TESSNORMAL output register element :
#else
// D3DVSD_SKIP is encoded identically on host Direct3D8.
*pRecompiled = D3DVSD_SKIP(SkipCount);
#endif
}
static void VshConvertToken_STREAMDATA_SKIPBYTES(DWORD *pToken)
static void VshConvertToken_STREAMDATA_SKIPBYTES(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled
)
{
using namespace XTL;
XTL::DWORD SkipBytesCount = (*pToken & X_D3DVSD_SKIPCOUNTMASK) >> X_D3DVSD_SKIPCOUNTSHIFT;
DbgVshPrintf("\tD3DVSD_SKIPBYTES(%d), /* xbox ext. */\n", SkipBytesCount);
if(SkipBytesCount % sizeof(XTL::DWORD))
{
if (SkipBytesCount % sizeof(XTL::DWORD)) {
EmuWarning("D3DVSD_SKIPBYTES can't be converted to D3DVSD_SKIP, not divisble by 4.");
}
*pToken = D3DVSD_SKIP(SkipBytesCount / sizeof(XTL::DWORD));
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = D3DVSD_SKIP(SkipBytesCount / sizeof(XTL::DWORD));
#endif
}
static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData)
static void VshConvertToken_STREAMDATA_REG(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData
)
{
using namespace XTL;
#if CXBX_USE_D3D9
extern XTL::D3DCAPS g_D3DCaps;
#endif
#if !CXBX_USE_D3D9 // For simpler support for both Direct3D 8 and 9, use these '9' constants in below '8' code paths too:
#define D3DDECLTYPE_FLOAT1 D3DVSDT_FLOAT1
#define D3DDECLTYPE_FLOAT2 D3DVSDT_FLOAT2
#define D3DDECLTYPE_FLOAT3 D3DVSDT_FLOAT3
#define D3DDECLTYPE_FLOAT4 D3DVSDT_FLOAT4
#define D3DDECLTYPE_D3DCOLOR D3DVSDT_D3DCOLOR
#define D3DDECLTYPE_SHORT2 D3DVSDT_SHORT2
#define D3DDECLTYPE_SHORT4 D3DVSDT_SHORT4
#define D3DDECLTYPE_UNUSED 0xFF
#endif
XTL::DWORD VertexRegister = VshGetVertexRegister(*pToken);
XTL::DWORD HostVertexRegister;
XTL::BOOL NeedPatching = FALSE;
@ -1927,122 +2032,198 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
XTL::DWORD HostVertexElementDataType = 0;
XTL::DWORD HostVertexElementByteSize = 0;
switch(XboxVertexElementDataType)
{
switch (XboxVertexElementDataType)
{
case X_D3DVSDT_FLOAT1: // 0x12:
DbgVshPrintf("D3DVSDT_FLOAT1");
HostVertexElementDataType = D3DVSDT_FLOAT1;
HostVertexElementByteSize = 1*sizeof(FLOAT);
break;
DbgVshPrintf("D3DVSDT_FLOAT1");
HostVertexElementDataType = D3DDECLTYPE_FLOAT1;
HostVertexElementByteSize = 1 * sizeof(FLOAT);
break;
case X_D3DVSDT_FLOAT2: // 0x22:
DbgVshPrintf("D3DVSDT_FLOAT2");
HostVertexElementDataType = D3DVSDT_FLOAT2;
HostVertexElementByteSize = 2*sizeof(FLOAT);
break;
DbgVshPrintf("D3DVSDT_FLOAT2");
HostVertexElementDataType = D3DDECLTYPE_FLOAT2;
HostVertexElementByteSize = 2 * sizeof(FLOAT);
break;
case X_D3DVSDT_FLOAT3: // 0x32:
DbgVshPrintf("D3DVSDT_FLOAT3");
HostVertexElementDataType = D3DVSDT_FLOAT3;
HostVertexElementByteSize = 3*sizeof(FLOAT);
break;
DbgVshPrintf("D3DVSDT_FLOAT3");
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
HostVertexElementByteSize = 3 * sizeof(FLOAT);
break;
case X_D3DVSDT_FLOAT4: // 0x42:
DbgVshPrintf("D3DVSDT_FLOAT4");
HostVertexElementDataType = D3DVSDT_FLOAT4;
HostVertexElementByteSize = 4*sizeof(FLOAT);
break;
DbgVshPrintf("D3DVSDT_FLOAT4");
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
HostVertexElementByteSize = 4 * sizeof(FLOAT);
break;
case X_D3DVSDT_D3DCOLOR: // 0x40:
DbgVshPrintf("D3DVSDT_D3DCOLOR");
HostVertexElementDataType = D3DVSDT_D3DCOLOR;
HostVertexElementByteSize = sizeof(D3DCOLOR);
break;
DbgVshPrintf("D3DVSDT_D3DCOLOR");
HostVertexElementDataType = D3DDECLTYPE_D3DCOLOR;
HostVertexElementByteSize = 1 * sizeof(D3DCOLOR);
break;
case X_D3DVSDT_SHORT2: // 0x25:
DbgVshPrintf("D3DVSDT_SHORT2");
HostVertexElementDataType = D3DVSDT_SHORT2;
HostVertexElementByteSize = 2*sizeof(XTL::SHORT);
break;
DbgVshPrintf("D3DVSDT_SHORT2");
HostVertexElementDataType = D3DDECLTYPE_SHORT2;
HostVertexElementByteSize = 2 * sizeof(XTL::SHORT);
break;
case X_D3DVSDT_SHORT4: // 0x45:
DbgVshPrintf("D3DVSDT_SHORT4");
HostVertexElementDataType = D3DVSDT_SHORT4;
HostVertexElementByteSize = 4*sizeof(XTL::SHORT);
break;
DbgVshPrintf("D3DVSDT_SHORT4");
HostVertexElementDataType = D3DDECLTYPE_SHORT4;
HostVertexElementByteSize = 4 * sizeof(XTL::SHORT);
break;
case X_D3DVSDT_NORMSHORT1: // 0x11:
DbgVshPrintf("D3DVSDT_NORMSHORT1 /* xbox ext. */");
HostVertexElementDataType = D3DVSDT_FLOAT1; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT2 in Direct3D9 ?
HostVertexElementByteSize = sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMSHORT2: // 0x21:
DbgVshPrintf("D3DVSDT_NORMSHORT2 /* xbox ext. */");
HostVertexElementDataType = D3DVSDT_FLOAT2;
HostVertexElementByteSize = 2*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMSHORT3: // 0x31:
DbgVshPrintf("D3DVSDT_NORMSHORT3 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_FLOAT3; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT4 in Direct3D9 ?
HostVertexElementByteSize = 3*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMSHORT4: // 0x41:
DbgVshPrintf("D3DVSDT_NORMSHORT4 /* xbox ext. */");
HostVertexElementDataType = D3DVSDT_FLOAT4;
HostVertexElementByteSize = 4*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMPACKED3: // 0x16:
DbgVshPrintf("D3DVSDT_NORMPACKED3 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_FLOAT3;
HostVertexElementByteSize = 3*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_SHORT1: // 0x15:
DbgVshPrintf("D3DVSDT_SHORT1 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_SHORT2;
HostVertexElementByteSize = 2*sizeof(XTL::SHORT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_SHORT3: // 0x35:
DbgVshPrintf("D3DVSDT_SHORT3 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_SHORT4;
HostVertexElementByteSize = 4*sizeof(XTL::SHORT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE1: // 0x14:
DbgVshPrintf("D3DVSDT_PBYTE1 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_FLOAT1; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT2 in Direct3D9 ?
HostVertexElementByteSize = 1*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE2: // 0x24:
DbgVshPrintf("D3DVSDT_PBYTE2 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_FLOAT2; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT2 in Direct3D9 ?
HostVertexElementByteSize = 2*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE3: // 0x34:
DbgVshPrintf("D3DVSDT_PBYTE3 /* xbox ext. nsp */");
HostVertexElementDataType = D3DVSDT_FLOAT3; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT4 in Direct3D9 ?
HostVertexElementByteSize = 3*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE4: // 0x44: // Hit by Panzer
DbgVshPrintf("D3DVSDT_PBYTE4 /* xbox ext. */");
HostVertexElementDataType = D3DVSDT_FLOAT4; // TODO -oDxbx : Is it better to use D3DVSDT_NORMSHORT4 or D3DDECLTYPE_UBYTE4N (if in caps) in Direct3D9 ?
HostVertexElementByteSize = 4*sizeof(FLOAT);
DbgVshPrintf("D3DVSDT_NORMSHORT1 /* xbox ext. */");
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT2N) {
HostVertexElementDataType = D3DDECLTYPE_SHORT2N;
HostVertexElementByteSize = 2 * sizeof(SHORT);
}
else
#endif
{
HostVertexElementDataType = D3DDECLTYPE_FLOAT1;
HostVertexElementByteSize = 1 * sizeof(FLOAT);
}
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMSHORT2: // 0x21:
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT2N) {
DbgVshPrintf("D3DVSDT_NORMSHORT2");
HostVertexElementDataType = D3DDECLTYPE_SHORT2N;
HostVertexElementByteSize = 2 * sizeof(SHORT);
// No need for patching in D3D9
}
else
#endif
{
DbgVshPrintf("D3DVSDT_NORMSHORT2 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_FLOAT2;
HostVertexElementByteSize = 2 * sizeof(FLOAT);
NeedPatching = TRUE;
}
break;
case X_D3DVSDT_NORMSHORT3: // 0x31:
DbgVshPrintf("D3DVSDT_NORMSHORT3 /* xbox ext. */");
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT4N) {
HostVertexElementDataType = D3DDECLTYPE_SHORT4N;
HostVertexElementByteSize = 4 * sizeof(SHORT);
}
else
#endif
{
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
HostVertexElementByteSize = 3 * sizeof(FLOAT);
}
NeedPatching = TRUE;
break;
case X_D3DVSDT_NORMSHORT4: // 0x41:
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_SHORT4N) {
DbgVshPrintf("D3DVSDT_NORMSHORT4");
HostVertexElementDataType = D3DDECLTYPE_SHORT4N;
HostVertexElementByteSize = 4 * sizeof(SHORT);
// No need for patching in D3D9
}
else
#endif
{
DbgVshPrintf("D3DVSDT_NORMSHORT4 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
HostVertexElementByteSize = 4 * sizeof(FLOAT);
NeedPatching = TRUE;
}
break;
case X_D3DVSDT_NORMPACKED3: // 0x16:
DbgVshPrintf("D3DVSDT_NORMPACKED3 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
HostVertexElementByteSize = 3 * sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_SHORT1: // 0x15:
DbgVshPrintf("D3DVSDT_SHORT1 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_SHORT2;
HostVertexElementByteSize = 2 * sizeof(XTL::SHORT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_SHORT3: // 0x35:
DbgVshPrintf("D3DVSDT_SHORT3 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_SHORT4;
HostVertexElementByteSize = 4 * sizeof(XTL::SHORT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE1: // 0x14:
DbgVshPrintf("D3DVSDT_PBYTE1 /* xbox ext. */");
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
HostVertexElementDataType = D3DDECLTYPE_UBYTE4N;
HostVertexElementByteSize = 4 * sizeof(BYTE);
}
else
#endif
{
HostVertexElementDataType = D3DDECLTYPE_FLOAT1;
HostVertexElementByteSize = 1 * sizeof(FLOAT);
}
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE2: // 0x24:
DbgVshPrintf("D3DVSDT_PBYTE2 /* xbox ext. */");
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
HostVertexElementDataType = D3DDECLTYPE_UBYTE4N;
HostVertexElementByteSize = 4 * sizeof(BYTE);
}
else
#endif
{
HostVertexElementDataType = D3DDECLTYPE_FLOAT2;
HostVertexElementByteSize = 2 * sizeof(FLOAT);
}
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE3: // 0x34:
DbgVshPrintf("D3DVSDT_PBYTE3 /* xbox ext. */");
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
HostVertexElementDataType = D3DDECLTYPE_UBYTE4N;
HostVertexElementByteSize = 4 * sizeof(BYTE);
}
else
#endif
{
HostVertexElementDataType = D3DDECLTYPE_FLOAT3;
HostVertexElementByteSize = 3 * sizeof(FLOAT);
}
NeedPatching = TRUE;
break;
case X_D3DVSDT_PBYTE4: // 0x44:
// Test-case : Panzer
#if CXBX_USE_D3D9
if (g_D3DCaps.DeclTypes & D3DDTCAPS_UBYTE4N) {
DbgVshPrintf("D3DVSDT_PBYTE4");
HostVertexElementDataType = D3DDECLTYPE_UBYTE4N;
HostVertexElementByteSize = 4 * sizeof(BYTE);
// No need for patching when D3D9 supports D3DDECLTYPE_UBYTE4N
}
else
#endif
{
DbgVshPrintf("D3DVSDT_PBYTE4 /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
HostVertexElementByteSize = 4 * sizeof(FLOAT);
NeedPatching = TRUE;
}
break;
case X_D3DVSDT_FLOAT2H: // 0x72:
DbgVshPrintf("D3DVSDT_FLOAT2H /* xbox ext. */");
HostVertexElementDataType = D3DVSDT_FLOAT4;
HostVertexElementDataType = D3DDECLTYPE_FLOAT4;
HostVertexElementByteSize = 4*sizeof(FLOAT);
NeedPatching = TRUE;
break;
case X_D3DVSDT_NONE: // 0x02:
DbgVshPrintf("D3DVSDT_NONE /* xbox ext. nsp */");
#if CXBX_USE_D3D9
HostVertexElementDataType = D3DVSDT_NONE;
#endif
// TODO -oDxbx: Use D3DVSD_NOP ?
HostVertexElementDataType = 0xFF;
DbgVshPrintf("D3DVSDT_NONE /* xbox ext. */");
HostVertexElementDataType = D3DDECLTYPE_UNUSED;
// NeedPatching = TRUE; // TODO : This seems to cause regressions?
break;
default:
DbgVshPrintf("Unknown data type for D3DVSD_REG: 0x%02X\n", XboxVertexElementDataType);
@ -2056,46 +2237,51 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
pPatchData->pCurrentVertexShaderStreamInfo->NumberOfVertexElements++;
pPatchData->pCurrentVertexShaderStreamInfo->NeedPatch |= NeedPatching;
*pToken = D3DVSD_REG(HostVertexRegister, HostVertexElementDataType);
#ifdef CXBX_USE_D3D9
// TODO
#else
*pRecompiled = D3DVSD_REG(HostVertexRegister, HostVertexElementDataType);
#endif
pPatchData->pCurrentVertexShaderStreamInfo->HostVertexStride += HostVertexElementByteSize;
DbgVshPrintf("),\n");
if(HostVertexElementDataType == 0xFF)
if(HostVertexElementDataType == D3DDECLTYPE_UNUSED)
{
EmuWarning("/* WARNING: Fatal type mismatch, no fitting type! */");
}
}
#define D3DVSD_MASK_TESSUV 0x10000000
#define D3DVSD_MASK_SKIP 0x10000000 // Skips (normally) dwords
#define D3DVSD_MASK_SKIPBYTES 0x08000000 // Skips bytes (no, really?!)
static void VshConvertToken_STREAMDATA(DWORD *pToken,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData)
static void VshConvertToken_STREAMDATA(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *pRecompiled,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData
)
{
using namespace XTL;
if (*pToken & D3DVSD_MASK_SKIP)
if (*pToken & X_D3DVSD_MASK_SKIP)
{
// For D3D9, use D3DDECLTYPE_UNUSED ?
if (*pToken & D3DVSD_MASK_SKIPBYTES) {
VshConvertToken_STREAMDATA_SKIPBYTES(pToken);
if (*pToken & X_D3DVSD_MASK_SKIPBYTES) {
VshConvertToken_STREAMDATA_SKIPBYTES(pToken, pRecompiled);
} else {
VshConvertToken_STREAMDATA_SKIP(pToken);
VshConvertToken_STREAMDATA_SKIP(pToken, pRecompiled);
}
}
else // D3DVSD_REG
{
VshConvertToken_STREAMDATA_REG(pToken, IsFixedFunction, pPatchData);
VshConvertToken_STREAMDATA_REG(pToken, pRecompiled, IsFixedFunction, pPatchData);
}
}
static DWORD VshRecompileToken(DWORD *pToken,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData)
static DWORD VshRecompileToken(
DWORD *pToken,
XTL::D3DVERTEXELEMENT *&pRecompiled,
boolean IsFixedFunction,
CxbxVertexShaderPatch *pPatchData
)
{
using namespace XTL;
@ -2103,27 +2289,27 @@ static DWORD VshRecompileToken(DWORD *pToken,
switch(VshGetTokenType(*pToken))
{
case D3DVSD_TOKEN_NOP:
VshConvertToken_NOP(pToken);
case X_D3DVSD_TOKEN_NOP:
VshConvertToken_NOP(pToken, pRecompiled);
break;
case D3DVSD_TOKEN_STREAM:
case X_D3DVSD_TOKEN_STREAM:
{
VshConvertToken_STREAM(pToken, pPatchData);
VshConvertToken_STREAM(pToken, pRecompiled, pPatchData);
break;
}
case D3DVSD_TOKEN_STREAMDATA:
case X_D3DVSD_TOKEN_STREAMDATA:
{
VshConvertToken_STREAMDATA(pToken, IsFixedFunction, pPatchData);
VshConvertToken_STREAMDATA(pToken, pRecompiled, IsFixedFunction, pPatchData);
break;
}
case D3DVSD_TOKEN_TESSELLATOR:
case X_D3DVSD_TOKEN_TESSELLATOR:
{
VshConverToken_TESSELATOR(pToken, IsFixedFunction);
VshConvertToken_TESSELATOR(pToken, pRecompiled, IsFixedFunction);
break;
}
case D3DVSD_TOKEN_CONSTMEM:
case X_D3DVSD_TOKEN_CONSTMEM:
{
Step = VshConvertToken_CONSTMEM(pToken);
Step = VshConvertToken_CONSTMEM(pToken, pRecompiled);
break;
}
default:
@ -2137,7 +2323,7 @@ static DWORD VshRecompileToken(DWORD *pToken,
DWORD XTL::EmuRecompileVshDeclaration
(
DWORD *pDeclaration,
DWORD **ppRecompiledDeclaration,
D3DVERTEXELEMENT **ppRecompiledDeclaration,
DWORD *pDeclarationSize,
boolean IsFixedFunction,
CxbxVertexShaderInfo *pVertexShaderInfo
@ -2153,8 +2339,19 @@ DWORD XTL::EmuRecompileVshDeclaration
// Calculate size of declaration
DWORD DeclarationSize = VshGetDeclarationSize(pDeclaration);
DWORD *pRecompiled = (DWORD *)malloc(DeclarationSize);
#ifdef CXBX_USE_D3D9
// For Direct3D9, we need to reserve at least twice the number of elements, as one token can generate two registers (in and out) :
DeclarationSize *= sizeof(D3DVERTEXELEMENT) * 2;
#else
// For Direct3D8, tokens are the same size as on Xbox (DWORD) and are translated in-place :
DeclarationSize *= sizeof(DWORD);
#endif
D3DVERTEXELEMENT *pRecompiled = (D3DVERTEXELEMENT *)malloc(DeclarationSize);
#ifdef CXBX_USE_D3D9
memset(pRecompiled, 0, DeclarationSize);
#else
memcpy(pRecompiled, pDeclaration, DeclarationSize);
#endif
uint8_t *pRecompiledBufferOverflow = ((uint8_t*)pRecompiled) + DeclarationSize;
*ppRecompiledDeclaration = pRecompiled;
*pDeclarationSize = DeclarationSize;
@ -2164,18 +2361,21 @@ DWORD XTL::EmuRecompileVshDeclaration
DbgVshPrintf("DWORD dwVSHDecl[] =\n{\n");
while (*pRecompiled != DEF_VSH_END)
while (*pDeclaration != DEF_VSH_END)
{
if ((uint8*)pRecompiled >= pRecompiledBufferOverflow) {
DbgVshPrintf("Detected buffer-overflow, breaking out...\n");
break;
}
DWORD Step = VshRecompileToken(pRecompiled, IsFixedFunction, &PatchData);
pRecompiled += Step;
}
VshEndPreviousStreamPatch(&PatchData);
DWORD Step = VshRecompileToken(pDeclaration, pRecompiled, IsFixedFunction, &PatchData);
pDeclaration += Step;
#ifndef CXBX_USE_D3D9
pRecompiled += Step;
#endif
}
VshEndPreviousStreamPatch(&PatchData);
DbgVshPrintf("\tD3DVSD_END()\n};\n");
DbgVshPrintf("// NbrStreams: %d\n", PatchData.pVertexShaderInfoToSet->NumberOfVertexStreams);
@ -2207,10 +2407,10 @@ extern HRESULT XTL::EmuRecompileVshFunction
bool declaredRegisters[13];
DWORD* pDeclToken = pRecompiledDeclaration;
do {
DWORD regNum = *pDeclToken & D3DVSD_VERTEXREGMASK;
DWORD regNum = *pDeclToken & X_D3DVSD_VERTEXREGMASK;
declaredRegisters[regNum] = true;
pDeclToken++;
} while (*pDeclToken != D3DVSD_END());
} while (*pDeclToken != X_D3DVSD_END());
// TODO: support this situation..
if(pFunction == NULL)
@ -2375,4 +2575,4 @@ XTL::CxbxVertexShaderInfo *GetCxbxVertexShaderInfo(DWORD Handle)
}
}
return NULL;
}
}

View File

@ -53,7 +53,7 @@ VSH_SHADER_HEADER;
extern DWORD EmuRecompileVshDeclaration
(
DWORD *pDeclaration,
DWORD **ppRecompiledDeclaration,
D3DVERTEXELEMENT **ppRecompiledDeclaration,
DWORD *pDeclarationSize,
boolean IsFixedFunction,
XTL::CxbxVertexShaderInfo *pVertexShaderInfo

View File

@ -70,9 +70,11 @@
#define D3DXAssembleShader D3DXCompileShader
#define FullScreen_PresentationInterval PresentationInterval // a field in D3DPRESENT_PARAMETERS
#define D3DLockData void
#define PixelShaderConstantType float
#define D3DADAPTER_IDENTIFIER D3DADAPTER_IDENTIFIER9
#define D3DCAPS D3DCAPS9
#define D3DVERTEXELEMENT D3DVERTEXELEMENT9
#define D3DVIEWPORT D3DVIEWPORT9
#define IDirect3D IDirect3D9
@ -112,9 +114,11 @@ typedef D3DVIEWPORT9 X_D3DVIEWPORT8;
#define DXGetErrorString DXGetErrorString8A
#define DXGetErrorDescription DXGetErrorDescription8A
#define D3DLockData BYTE
#define PixelShaderConstantType void
#define D3DADAPTER_IDENTIFIER D3DADAPTER_IDENTIFIER8
#define D3DCAPS D3DCAPS8
#define D3DVERTEXELEMENT DWORD
#define D3DVIEWPORT D3DVIEWPORT8
#define IDirect3D IDirect3D8
@ -1204,6 +1208,18 @@ const int MAX_NBR_STREAMS = 16;
typedef WORD INDEX16;
typedef enum _X_D3DVSD_TOKENTYPE
{
X_D3DVSD_TOKEN_NOP = 0, // NOP or extension
X_D3DVSD_TOKEN_STREAM, // stream selector
X_D3DVSD_TOKEN_STREAMDATA, // stream data definition (map to vertex input memory)
X_D3DVSD_TOKEN_TESSELLATOR, // vertex input memory from tessellator
X_D3DVSD_TOKEN_CONSTMEM, // constant memory from shader
X_D3DVSD_TOKEN_EXT, // extension
X_D3DVSD_TOKEN_END = 7, // end-of-array (requires all DWORD bits to be 1)
X_D3DVSD_FORCE_DWORD = 0x7fffffff,// force 32-bit size enum
} X_D3DVSD_TOKENTYPE;
#define X_D3DVSD_TOKENTYPESHIFT 29
#define X_D3DVSD_TOKENTYPEMASK (7 << X_D3DVSD_TOKENTYPESHIFT)
@ -1240,4 +1256,6 @@ typedef WORD INDEX16;
#define X_D3DVSD_EXTINFOSHIFT 0
#define X_D3DVSD_EXTINFOMASK (0xFFFFFF << X_D3DVSD_EXTINFOSHIFT)
#define X_D3DVSD_END() 0xFFFFFFFF
#endif