diff --git a/src/core/hle/D3D8/XbD3D8Types.h b/src/core/hle/D3D8/XbD3D8Types.h index d7a468002..c5d5dc88d 100644 --- a/src/core/hle/D3D8/XbD3D8Types.h +++ b/src/core/hle/D3D8/XbD3D8Types.h @@ -1177,6 +1177,7 @@ struct X_D3DVertexShader // vertex shader input registers for fixed function vertex shader // Name Register number D3DFVF +const int X_D3DVSDE_VERTEX = -1; // Xbox extension for Begin/End drawing - equivalent to POSITION const int X_D3DVSDE_POSITION = 0; // Corresponds to X_D3DFVF_XYZ const int X_D3DVSDE_BLENDWEIGHT = 1; // Corresponds to X_D3DFVF_XYZB1? (was X_D3DFVF_XYZRHW?) const int X_D3DVSDE_NORMAL = 2; // Corresponds to X_D3DFVF_NORMAL @@ -1190,7 +1191,6 @@ const int X_D3DVSDE_TEXCOORD0 = 9; // Corresponds to X_D3DFVF_TEX1 (not X_D3D const int X_D3DVSDE_TEXCOORD1 = 10; // Corresponds to X_D3DFVF_TEX2 const int X_D3DVSDE_TEXCOORD2 = 11; // Corresponds to X_D3DFVF_TEX3 const int X_D3DVSDE_TEXCOORD3 = 12; // Corresponds to X_D3DFVF_TEX4 -const int X_D3DVSDE_VERTEX = 0xFFFFFFFF; // Xbox extension for Begin/End drawing (data is a D3DVSDT_FLOAT4) //typedef X_D3DVSDE = X_D3DVSDE_POSITION..High(DWORD)-2; // Unique declaration to make overloads possible; diff --git a/src/core/hle/D3D8/XbVertexBuffer.cpp b/src/core/hle/D3D8/XbVertexBuffer.cpp index 05391e2a6..de44da34d 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.cpp +++ b/src/core/hle/D3D8/XbVertexBuffer.cpp @@ -50,14 +50,11 @@ CxbxVertexBufferConverter VertexBufferConverter = {}; // Inline vertex buffer emulation xbox::X_D3DPRIMITIVETYPE g_InlineVertexBuffer_PrimitiveType = xbox::X_D3DPT_INVALID; -uint32_t g_InlineVertexBuffer_WrittenRegisters = 0; // A bitmask, indicating which registers have been set in g_InlineVertexBuffer_Table xbox::X_VERTEXATTRIBUTEFORMAT g_InlineVertexBuffer_AttributeFormat = {}; bool g_InlineVertexBuffer_DeclarationOverride = false; std::vector g_InlineVertexBuffer_Table; UINT g_InlineVertexBuffer_TableLength = 0; UINT g_InlineVertexBuffer_TableOffset = 0; -FLOAT *g_InlineVertexBuffer_pData = nullptr; -UINT g_InlineVertexBuffer_DataSize = 0; // Copy of active Xbox D3D Vertex Streams (and strides), set by [D3DDevice|CxbxImpl]_SetStreamSource* xbox::X_STREAMINPUT g_Xbox_SetStreamSource[X_VSH_MAX_STREAMS] = { 0 }; // Note : .Offset member is never set (so always 0) @@ -69,28 +66,6 @@ bool GetHostRenderTargetDimensions(DWORD* pHostWidth, DWORD* pHostHeight, IDirec uint32_t GetPixelContainerWidth(xbox::X_D3DPixelContainer* pPixelContainer); uint32_t GetPixelContainerHeight(xbox::X_D3DPixelContainer* pPixelContainer); -struct _D3DIVB &_D3DIVB::operator=(const struct _D3DIVB &Val) -{ - Position.x = Val.Position.x; - Position.y = Val.Position.y; - Position.z = Val.Position.z; - Rhw = Val.Rhw; - std::copy(std::begin(Val.Blend), std::end(Val.Blend), std::begin(Blend)); - Normal.x = Val.Normal.x; - Normal.y = Val.Normal.y; - Normal.z = Val.Normal.z; - Diffuse = Val.Diffuse; - Specular = Val.Specular; - Fog = Val.Fog; - PointSize = Val.PointSize; - BackDiffuse = Val.BackDiffuse; - BackSpecular = Val.BackSpecular; - std::copy(std::begin(Val.TexCoord), std::end(Val.TexCoord), std::begin(TexCoord)); - std::copy(std::begin(Val.Reg13Up), std::end(Val.Reg13Up), std::begin(Reg13Up)); - - return *this; -} - void CxbxPatchedStream::Activate(CxbxDrawContext *pDrawContext, UINT HostStreamNumber) const { //LOG_INIT // Allows use of DEBUG_D3DRESULT @@ -716,134 +691,27 @@ void CxbxSetVertexAttribute(int Register, FLOAT a, FLOAT b, FLOAT c, FLOAT d) g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VREGDEFAULTS_BASE + Register, attribute_floats, 1); } -DWORD Float4ToDWORD(float* floats) -{ - // Inverse of D3DDevice_SetVertexDataColor - uint8_t a = uint8_t(floats[0] * 255.0f); - uint8_t b = uint8_t(floats[1] * 255.0f); - uint8_t c = uint8_t(floats[2] * 255.0f); - uint8_t d = uint8_t(floats[3] * 255.0f); - uint32_t value = a + (b << 8) + (c << 16) + (d << 24); - return value; -} - void CxbxImpl_Begin(xbox::X_D3DPRIMITIVETYPE PrimitiveType) { g_InlineVertexBuffer_PrimitiveType = PrimitiveType; g_InlineVertexBuffer_TableOffset = 0; - g_InlineVertexBuffer_WrittenRegisters = 0; } void CxbxImpl_End() { using namespace xbox; -#ifndef FIELD_OFFSET -#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) -#endif - static const LONG OffsetPerRegister[X_VSH_MAX_ATTRIBUTES] = { - /*X_D3DVSDE_POSITION = 0:*/FIELD_OFFSET(D3DIVB, Position), - /*X_D3DVSDE_BLENDWEIGHT = 1:*/FIELD_OFFSET(D3DIVB, Blend), - /*X_D3DVSDE_NORMAL = 2:*/FIELD_OFFSET(D3DIVB, Normal), - /*X_D3DVSDE_DIFFUSE = 3:*/FIELD_OFFSET(D3DIVB, Diffuse), - /*X_D3DVSDE_SPECULAR = 4:*/FIELD_OFFSET(D3DIVB, Specular), - /*X_D3DVSDE_FOG = 5:*/FIELD_OFFSET(D3DIVB, Fog), - /*X_D3DVSDE_POINTSIZE = 6:*/FIELD_OFFSET(D3DIVB, PointSize), - /*X_D3DVSDE_BACKDIFFUSE = 7:*/FIELD_OFFSET(D3DIVB, BackDiffuse), - /*X_D3DVSDE_BACKSPECULAR = 8:*/FIELD_OFFSET(D3DIVB, BackSpecular), - /*X_D3DVSDE_TEXCOORD0 = 9:*/FIELD_OFFSET(D3DIVB, TexCoord[0]), - /*X_D3DVSDE_TEXCOORD1 = 10:*/FIELD_OFFSET(D3DIVB, TexCoord[1]), - /*X_D3DVSDE_TEXCOORD2 = 11:*/FIELD_OFFSET(D3DIVB, TexCoord[2]), - /*X_D3DVSDE_TEXCOORD3 = 12:*/FIELD_OFFSET(D3DIVB, TexCoord[3]), - /* 13:*/FIELD_OFFSET(D3DIVB, Reg13Up[0]), - /* 14:*/FIELD_OFFSET(D3DIVB, Reg13Up[1]), - /* 15:*/FIELD_OFFSET(D3DIVB, Reg13Up[2]) - }; - static const LONG FormatPerRegister[X_VSH_MAX_ATTRIBUTES] = { - /*X_D3DVSDE_POSITION = 0:*/X_D3DVSDT_FLOAT4, - /*X_D3DVSDE_BLENDWEIGHT = 1:*/X_D3DVSDT_FLOAT4, - /*X_D3DVSDE_NORMAL = 2:*/X_D3DVSDT_FLOAT3, - /*X_D3DVSDE_DIFFUSE = 3:*/X_D3DVSDT_D3DCOLOR, - /*X_D3DVSDE_SPECULAR = 4:*/X_D3DVSDT_D3DCOLOR, - /*X_D3DVSDE_FOG = 5:*/X_D3DVSDT_FLOAT1, - /*X_D3DVSDE_POINTSIZE = 6:*/X_D3DVSDT_FLOAT1, - /*X_D3DVSDE_BACKDIFFUSE = 7:*/X_D3DVSDT_D3DCOLOR, - /*X_D3DVSDE_BACKSPECULAR = 8:*/X_D3DVSDT_D3DCOLOR, - /*X_D3DVSDE_TEXCOORD0 = 9:*/X_D3DVSDT_FLOAT4, - /*X_D3DVSDE_TEXCOORD1 = 10:*/X_D3DVSDT_FLOAT4, - /*X_D3DVSDE_TEXCOORD2 = 11:*/X_D3DVSDT_FLOAT4, - /*X_D3DVSDE_TEXCOORD3 = 12:*/X_D3DVSDT_FLOAT4, - /* 13:*/X_D3DVSDT_FLOAT4, - /* 14:*/X_D3DVSDT_FLOAT4, - /* 15:*/X_D3DVSDT_FLOAT4 - }; - static const DWORD SizePerRegister[X_VSH_MAX_ATTRIBUTES] = { - /*X_D3DVSDE_POSITION = 0:*/sizeof(float) * 4, - /*X_D3DVSDE_BLENDWEIGHT = 1:*/sizeof(float) * 4, - /*X_D3DVSDE_NORMAL = 2:*/sizeof(float) * 3, - /*X_D3DVSDE_DIFFUSE = 3:*/sizeof(DWORD), - /*X_D3DVSDE_SPECULAR = 4:*/sizeof(DWORD), - /*X_D3DVSDE_FOG = 5:*/sizeof(float) * 1, - /*X_D3DVSDE_POINTSIZE = 6:*/sizeof(float) * 1, - /*X_D3DVSDE_BACKDIFFUSE = 7:*/sizeof(DWORD), - /*X_D3DVSDE_BACKSPECULAR = 8:*/sizeof(DWORD), - /*X_D3DVSDE_TEXCOORD0 = 9:*/sizeof(float) * 4, - /*X_D3DVSDE_TEXCOORD1 = 10:*/sizeof(float) * 4, - /*X_D3DVSDE_TEXCOORD2 = 11:*/sizeof(float) * 4, - /*X_D3DVSDE_TEXCOORD3 = 12:*/sizeof(float) * 4, - /* 13:*/sizeof(float) * 4, - /* 14:*/sizeof(float) * 4, - /* 15:*/sizeof(float) * 4 - }; - if (g_InlineVertexBuffer_TableOffset <= 0) { return; } - // Compose an Xbox vertex attribute format according to the registers that have been written to : + // Compose an Xbox vertex attribute format to pass through all registers UINT uiStride = 0; g_InlineVertexBuffer_AttributeFormat = {}; for (int reg = 0; reg < X_VSH_MAX_ATTRIBUTES; reg++) { - if (g_InlineVertexBuffer_WrittenRegisters & (1 << reg)) { - g_InlineVertexBuffer_AttributeFormat.Slots[reg].Format = FormatPerRegister[reg]; - g_InlineVertexBuffer_AttributeFormat.Slots[reg].Offset = uiStride; - uiStride += SizePerRegister[reg]; - } else { - g_InlineVertexBuffer_AttributeFormat.Slots[reg].Format = X_D3DVSDT_NONE; - } - } - - // Make sure the output buffer is big enough - UINT NeededSize = g_InlineVertexBuffer_TableOffset * uiStride; - if (g_InlineVertexBuffer_DataSize < NeededSize) { - g_InlineVertexBuffer_DataSize = NeededSize; - if (g_InlineVertexBuffer_pData != nullptr) { - free(g_InlineVertexBuffer_pData); - } - - g_InlineVertexBuffer_pData = (FLOAT*)malloc(g_InlineVertexBuffer_DataSize); - } - - // For each register that ever got written, copy the data over from - // g_InlineVertexBuffer_Table to pVertexBufferData, but adjacent - // to eachother. This, so that host accepts this as a vertex declaration. - // Note, that if we figure out how to draw using vertex buffers that - // contain gaps, the following copy is no longer needed, and we could - // draw straight from g_InlineVertexBuffer_Table instead! - uint8_t* pVertexBufferData = (uint8_t*)g_InlineVertexBuffer_pData; - for (unsigned int v = 0; v < g_InlineVertexBuffer_TableOffset; v++) { - auto vertex_ptr = (uint8_t*)&(g_InlineVertexBuffer_Table[v]); - for (unsigned int reg = 0; reg < X_VSH_MAX_ATTRIBUTES; reg++) { - if (g_InlineVertexBuffer_WrittenRegisters & (1 << reg)) { - auto source = vertex_ptr + OffsetPerRegister[reg]; - auto size = SizePerRegister[reg]; - // Note, that g_InlineVertexBuffer_AttributeFormat is declared with - // data types (in g_InlineVertexBuffer_Table ) that are host-compatible, - // so we can do a straight copy here, there's no conversion needed : - memcpy(pVertexBufferData, source, size); - pVertexBufferData += size; - } - } + g_InlineVertexBuffer_AttributeFormat.Slots[reg].Format = X_D3DVSDT_FLOAT4; + g_InlineVertexBuffer_AttributeFormat.Slots[reg].Offset = uiStride; + uiStride += sizeof(float) * 4; } // Arrange for g_InlineVertexBuffer_AttributeFormat to be returned in CxbxGetVertexDeclaration, @@ -859,7 +727,7 @@ void CxbxImpl_End() DrawContext.XboxPrimitiveType = g_InlineVertexBuffer_PrimitiveType; DrawContext.dwVertexCount = g_InlineVertexBuffer_TableOffset; - DrawContext.pXboxVertexStreamZeroData = g_InlineVertexBuffer_pData; + DrawContext.pXboxVertexStreamZeroData = g_InlineVertexBuffer_Table.data(); DrawContext.uiXboxVertexStreamZeroStride = uiStride; CxbxDrawPrimitiveUP(DrawContext); @@ -904,134 +772,34 @@ void CxbxImpl_SetVertexData4f(int Register, FLOAT a, FLOAT b, FLOAT c, FLOAT d) } // Is this the initial call after D3DDevice_Begin() ? - if (g_InlineVertexBuffer_WrittenRegisters == 0) { + if (g_InlineVertexBuffer_TableOffset == 0) { // Read starting values for all inline vertex attributes from HLE NV2A pgraph (converting them to required types) : - g_InlineVertexBuffer_Table[0].Position = D3DXVECTOR3(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_POSITION)); - g_InlineVertexBuffer_Table[0].Rhw = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_POSITION)[3]; - g_InlineVertexBuffer_Table[0].Blend[0] = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BLENDWEIGHT)[0]; - g_InlineVertexBuffer_Table[0].Blend[1] = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BLENDWEIGHT)[1]; - g_InlineVertexBuffer_Table[0].Blend[2] = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BLENDWEIGHT)[2]; - g_InlineVertexBuffer_Table[0].Blend[3] = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BLENDWEIGHT)[3]; - g_InlineVertexBuffer_Table[0].Normal = D3DXVECTOR3(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_NORMAL)); - g_InlineVertexBuffer_Table[0].Diffuse = Float4ToDWORD(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_DIFFUSE)); - g_InlineVertexBuffer_Table[0].Specular = Float4ToDWORD(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_SPECULAR)); - g_InlineVertexBuffer_Table[0].Fog = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_FOG)[0]; - g_InlineVertexBuffer_Table[0].PointSize = HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_POINTSIZE)[0]; - g_InlineVertexBuffer_Table[0].BackDiffuse = Float4ToDWORD(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BACKDIFFUSE)); - g_InlineVertexBuffer_Table[0].BackSpecular = Float4ToDWORD(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_BACKSPECULAR)); - g_InlineVertexBuffer_Table[0].TexCoord[0] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_TEXCOORD0)); - g_InlineVertexBuffer_Table[0].TexCoord[1] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_TEXCOORD1)); - g_InlineVertexBuffer_Table[0].TexCoord[2] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_TEXCOORD2)); - g_InlineVertexBuffer_Table[0].TexCoord[3] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(X_D3DVSDE_TEXCOORD3)); - g_InlineVertexBuffer_Table[0].Reg13Up[0] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(13)); - g_InlineVertexBuffer_Table[0].Reg13Up[1] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(14)); - g_InlineVertexBuffer_Table[0].Reg13Up[2] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(15)); + for (int i = 0; i < X_VSH_MAX_ATTRIBUTES; i++) { + g_InlineVertexBuffer_Table[0].Slots[i] = D3DXVECTOR4(HLE_get_NV2A_vertex_attribute_value_pointer(i)); + } // Note : Because all members are assigned an initial value, there's no need for a clearing constructor for _D3DIVB! } - if (Register == X_D3DVSDE_VERTEX) - g_InlineVertexBuffer_WrittenRegisters |= (1 << X_D3DVSDE_POSITION); - else if (Register < 16) - g_InlineVertexBuffer_WrittenRegisters |= (1 << Register); + // Write vertex data to the IVB table + if (Register >= X_D3DVSDE_VERTEX && Register <= X_VSH_MAX_ATTRIBUTES) { + // The slot index is usually the register value, but + // VERTEX (-1) maps to POSITION (0) + int index = Register; + if (Register == X_D3DVSDE_VERTEX) + index = X_D3DVSDE_POSITION; - unsigned o = g_InlineVertexBuffer_TableOffset; + unsigned o = g_InlineVertexBuffer_TableOffset; + g_InlineVertexBuffer_Table[o].Slots[index] = D3DXVECTOR4(a, b, c, d); - switch (Register) - { - case X_D3DVSDE_VERTEX: - case X_D3DVSDE_POSITION: - { - // Note : Setting position signals completion of a vertex - g_InlineVertexBuffer_Table[o].Position.x = a; - g_InlineVertexBuffer_Table[o].Position.y = b; - g_InlineVertexBuffer_Table[o].Position.z = c; - g_InlineVertexBuffer_Table[o].Rhw = d; - // Start a new vertex - g_InlineVertexBuffer_TableOffset++; - // Copy all attributes of the prior vertex to the new one, to simulate persistent attribute values - g_InlineVertexBuffer_Table[g_InlineVertexBuffer_TableOffset] = g_InlineVertexBuffer_Table[o]; - break; + // Writing to the POSITION slot completes the current vertex + if (index == X_D3DVSDE_POSITION) { + // Start a new vertex + g_InlineVertexBuffer_TableOffset++; + // Copy all attributes of the prior vertex to the new one, to simulate persistent attribute values + g_InlineVertexBuffer_Table[g_InlineVertexBuffer_TableOffset] = g_InlineVertexBuffer_Table[o]; + } } - - case X_D3DVSDE_BLENDWEIGHT: - { - g_InlineVertexBuffer_Table[o].Blend[0] = a; - g_InlineVertexBuffer_Table[o].Blend[1] = b; - g_InlineVertexBuffer_Table[o].Blend[2] = c; - g_InlineVertexBuffer_Table[o].Blend[3] = d; - break; - } - - case X_D3DVSDE_NORMAL: - { - g_InlineVertexBuffer_Table[o].Normal.x = a; - g_InlineVertexBuffer_Table[o].Normal.y = b; - g_InlineVertexBuffer_Table[o].Normal.z = c; - break; - } - - case X_D3DVSDE_DIFFUSE: - { - g_InlineVertexBuffer_Table[o].Diffuse = D3DCOLOR_COLORVALUE(a, b, c, d); - break; - } - - case X_D3DVSDE_SPECULAR: - { - g_InlineVertexBuffer_Table[o].Specular = D3DCOLOR_COLORVALUE(a, b, c, d); - break; - } - - case X_D3DVSDE_FOG: // Xbox extension - { - g_InlineVertexBuffer_Table[o].Fog = a; // TODO : What about the other (b, c and d) arguments? - break; - } - - case X_D3DVSDE_POINTSIZE: - { - g_InlineVertexBuffer_Table[o].PointSize = a; // TODO : What about the other (b, c and d) arguments? - break; - } - - case X_D3DVSDE_BACKDIFFUSE: // Xbox extension - { - g_InlineVertexBuffer_Table[o].BackDiffuse = D3DCOLOR_COLORVALUE(a, b, c, d); - break; - } - - case X_D3DVSDE_BACKSPECULAR: // Xbox extension - { - g_InlineVertexBuffer_Table[o].BackSpecular = D3DCOLOR_COLORVALUE(a, b, c, d); - break; - } - - case X_D3DVSDE_TEXCOORD0: - case X_D3DVSDE_TEXCOORD1: - case X_D3DVSDE_TEXCOORD2: - case X_D3DVSDE_TEXCOORD3: - { - unsigned i = Register - X_D3DVSDE_TEXCOORD0; - g_InlineVertexBuffer_Table[o].TexCoord[i].x = a; - g_InlineVertexBuffer_Table[o].TexCoord[i].y = b; - g_InlineVertexBuffer_Table[o].TexCoord[i].z = c; - g_InlineVertexBuffer_Table[o].TexCoord[i].w = d; - break; - } - - case 13: - case 14: - case 15: - { - unsigned i = Register - 13; - g_InlineVertexBuffer_Table[o].Reg13Up[i].x = a; - g_InlineVertexBuffer_Table[o].Reg13Up[i].y = b; - g_InlineVertexBuffer_Table[o].Reg13Up[i].z = c; - g_InlineVertexBuffer_Table[o].Reg13Up[i].w = d; - break; - } - - default: + else { EmuLog(LOG_LEVEL::WARNING, "Unknown IVB Register : %d", Register); } } diff --git a/src/core/hle/D3D8/XbVertexBuffer.h b/src/core/hle/D3D8/XbVertexBuffer.h index 45c6be246..e9af48d56 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.h +++ b/src/core/hle/D3D8/XbVertexBuffer.h @@ -27,6 +27,7 @@ #include #include +#include #include "Cxbx.h" @@ -123,23 +124,7 @@ extern xbox::X_D3DPRIMITIVETYPE g_InlineVertexBuffer_PrimitiveType; typedef struct _D3DIVB { - D3DXVECTOR3 Position; // X_D3DVSDE_POSITION (*) > D3DFVF_XYZ / D3DFVF_XYZRHW - FLOAT Rhw; // X_D3DVSDE_VERTEX (*) > D3DFVF_XYZ / D3DFVF_XYZRHW - FLOAT Blend[4]; // X_D3DVSDE_BLENDWEIGHT > D3DFVF_XYZB1 (and 3 more up to D3DFVF_XYZB4) - D3DXVECTOR3 Normal; // X_D3DVSDE_NORMAL > D3DFVF_NORMAL - D3DCOLOR Diffuse; // X_D3DVSDE_DIFFUSE > D3DFVF_DIFFUSE - D3DCOLOR Specular; // X_D3DVSDE_SPECULAR > D3DFVF_SPECULAR - FLOAT Fog; // X_D3DVSDE_FOG > D3DFVF_FOG unavailable; TODO : How to handle? - FLOAT PointSize; // X_D3DVSDE_POINTSIZE > D3DFVF_POINTSIZE unavailable; TODO : How to handle? - D3DCOLOR BackDiffuse; // X_D3DVSDE_BACKDIFFUSE > D3DFVF_BACKDIFFUSE unavailable; TODO : How to handle? - D3DCOLOR BackSpecular; // X_D3DVSDE_BACKSPECULAR > D3DFVF_BACKSPECULAR unavailable; TODO : How to handle? - D3DXVECTOR4 TexCoord[4]; // X_D3DVSDE_TEXCOORD0 > D3DFVF_TEX1, (and 3 more up to D3DFVF_TEX4) - D3DXVECTOR4 Reg13Up[3]; - // (*) X_D3DVSDE_POSITION and X_D3DVSDE_VERTEX both set Position, but Rhw seems optional, - // hence, selection for D3DFVF_XYZ or D3DFVF_XYZRHW is rather fuzzy. We DO know that once - // D3DFVF_NORMAL is given, D3DFVF_XYZRHW is forbidden (see D3DDevice_SetVertexData4f) - - struct _D3DIVB &operator=(const struct _D3DIVB &Val); + std::array Slots; } D3DIVB; diff --git a/src/core/hle/D3D8/XbVertexShader.cpp b/src/core/hle/D3D8/XbVertexShader.cpp index d9918f1ae..fd47d2cbf 100644 --- a/src/core/hle/D3D8/XbVertexShader.cpp +++ b/src/core/hle/D3D8/XbVertexShader.cpp @@ -714,7 +714,12 @@ private: case xbox::X_D3DVSDE_TEXCOORD1 /*=10*/: UsageIndex = 1; return D3DDECLUSAGE_TEXCOORD; case xbox::X_D3DVSDE_TEXCOORD2 /*=11*/: UsageIndex = 2; return D3DDECLUSAGE_TEXCOORD; case xbox::X_D3DVSDE_TEXCOORD3 /*=12*/: UsageIndex = 3; return D3DDECLUSAGE_TEXCOORD; - default /*13-15*/ : + // Unused registers. Assign them a semantic anyway so we don't have to worry about + // binding a vertex declaration with them in it + case 13: UsageIndex = 4; return D3DDECLUSAGE_TEXCOORD; + case 14: UsageIndex = 5; return D3DDECLUSAGE_TEXCOORD; + case 15: UsageIndex = 6; return D3DDECLUSAGE_TEXCOORD; + default: return D3DDECLUSAGE_UNSUPPORTED; } }