Change IVB to an array of 4-float slots

Will fix Halo logo and menu text rendering (once it's visible!)
- Remove references to fixed function concepts, since slots might contain anything
e.g. don't exclude the 4th component of the slot corresponding to NORMAL in fixed function mode
- Use the IVB table directly for simplicity. Copy all table data to the vertex buffer
This commit is contained in:
Anthony 2021-05-07 00:52:22 +12:00
parent 2397ece059
commit 0453e451f1
4 changed files with 35 additions and 277 deletions

View File

@ -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;

View File

@ -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<D3DIVB> 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);
}
}

View File

@ -27,6 +27,7 @@
#include <unordered_map>
#include <list>
#include <array>
#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<D3DXVECTOR4, 16> Slots;
} D3DIVB;

View File

@ -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;
}
}