Merge pull request #1881 from NZJenkins/improve_slots
Improve shader slot emulation
This commit is contained in:
commit
db640d5b6f
|
@ -154,10 +154,6 @@ static bool g_bHack_DisableHostGPUQueries = false; // TO
|
|||
static IDirect3DQuery *g_pHostQueryWaitForIdle = nullptr;
|
||||
static IDirect3DQuery *g_pHostQueryCallbackEvent = nullptr;
|
||||
|
||||
// Vertex shader symbols, declared in XbVertexShader.cpp :
|
||||
extern void CxbxImpl_SelectVertexShaderDirect(XTL::X_VERTEXATTRIBUTEFORMAT* pVAF, DWORD Address);
|
||||
extern void CxbxImpl_SetVertexShaderInput(DWORD Handle, UINT StreamCount, XTL::X_STREAMINPUT* pStreamInputs);
|
||||
|
||||
// Vertex buffer symbols, declared in XbVertexBuffer.cpp
|
||||
extern void CxbxImpl_SetStreamSource(UINT StreamNumber, XTL::X_D3DVertexBuffer* pStreamData, UINT Stride);
|
||||
|
||||
|
@ -195,7 +191,6 @@ static XTL::DWORD *g_Xbox_D3DDevice; // TODO: This should be a
|
|||
static DWORD g_dwVertexShaderUsage = 0; // Unused. If needed, move to XbVertexShader.cpp
|
||||
*/
|
||||
|
||||
static XTL::DWORD g_VertexShaderSlots[X_VSH_MAX_INSTRUCTION_COUNT];
|
||||
XTL::DWORD g_Xbox_VertexShader_Handle = 0;
|
||||
|
||||
// Static Function(s)
|
||||
|
@ -266,15 +261,6 @@ struct EmuD3D8CreateDeviceProxyData
|
|||
}
|
||||
g_EmuCDPD = {0};
|
||||
|
||||
#define DEBUG_D3DRESULT(hRet, message) \
|
||||
do { \
|
||||
LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { \
|
||||
if (FAILED(hRet)) \
|
||||
if(g_bPrintfOn) \
|
||||
printf("%s%s : %s D3D error (0x%.08X: %s)\n", _logThreadPrefix.c_str(), _logFuncPrefix.c_str(), message, hRet, D3DErrorString(hRet)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Declare trampolines
|
||||
#define XB_TRAMPOLINES(XB_MACRO) \
|
||||
XB_MACRO(HRESULT, WINAPI, D3DDevice_CreateVertexShader, (CONST DWORD*, CONST DWORD*, DWORD*, DWORD) ); \
|
||||
|
@ -856,7 +842,6 @@ typedef struct {
|
|||
typedef std::unordered_map<resource_key_t, resource_info_t, resource_key_hash> resource_cache_t;
|
||||
resource_cache_t g_Cxbx_Cached_Direct3DResources;
|
||||
resource_cache_t g_Cxbx_Cached_PaletizedTextures;
|
||||
VertexShaderSource g_VertexShaderSource = VertexShaderSource();
|
||||
|
||||
bool IsResourceAPixelContainer(XTL::DWORD XboxResource_Common)
|
||||
{
|
||||
|
@ -984,48 +969,6 @@ IDirect3DResource *GetHostResource(XTL::X_D3DResource *pXboxResource, DWORD D3DU
|
|||
return it->second.pHostResource;
|
||||
}
|
||||
|
||||
void SetCxbxVertexShader(CxbxVertexShader* pCxbxVertexShader) {
|
||||
|
||||
LOG_INIT
|
||||
|
||||
HRESULT hRet;
|
||||
|
||||
// Get vertex shader if we have a key
|
||||
auto pHostShader = pCxbxVertexShader->VertexShaderKey
|
||||
? g_VertexShaderSource.GetShader(pCxbxVertexShader->VertexShaderKey)
|
||||
: nullptr;
|
||||
|
||||
// Set vertex shader
|
||||
hRet = g_pD3DDevice->SetVertexShader(pHostShader);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");
|
||||
|
||||
// Set either FVF or the vertex declaration
|
||||
if (pCxbxVertexShader->HostFVF)
|
||||
{
|
||||
// Set the FVF
|
||||
hRet = g_pD3DDevice->SetFVF(pCxbxVertexShader->HostFVF);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetFVF");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set vertex declaration
|
||||
hRet = g_pD3DDevice->SetVertexDeclaration(pCxbxVertexShader->pHostVertexDeclaration);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexDeclaration");
|
||||
}
|
||||
|
||||
// Set vertex shader constants if necessary
|
||||
if (pHostShader) {
|
||||
// Titles can specify default values for registers via calls like SetVertexData4f
|
||||
// HLSL shaders need to know whether to use vertex data or default vertex shader values
|
||||
// Any register not in the vertex declaration should be set to the default value
|
||||
float vertexDefaultFlags[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
vertexDefaultFlags[i] = pCxbxVertexShader->VertexShaderInfo.vRegisterInDeclaration[i] ? 0.0f : 1.0f;
|
||||
}
|
||||
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_CONSTREG_VREGDEFAULTS_FLAG_BASE, vertexDefaultFlags, 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward declaration of CxbxGetPixelContainerMeasures to prevent
|
||||
// polluting the diff too much by reshuffling functions around
|
||||
VOID CxbxGetPixelContainerMeasures
|
||||
|
@ -3539,18 +3482,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_LoadVertexShader)
|
|||
LOG_FUNC_ARG(Address)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Handle is always address of an X_D3DVertexShader struct, thus always or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// Address is the slot (offset) from which the program must be written onwards (as whole DWORDS)
|
||||
// D3DDevice_LoadVertexShader pushes the program contained in the Xbox VertexShader struct to the NV2A
|
||||
if(Address < 136) {
|
||||
CxbxVertexShader * pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
if (pCxbxVertexShader) {
|
||||
for (DWORD i = Address; i < pCxbxVertexShader->XboxNrAddressSlots; i++) {
|
||||
// TODO: This seems very fishy
|
||||
g_VertexShaderSlots[i] = Handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
CxbxImpl_LoadVertexShader(Handle, Address);
|
||||
}
|
||||
|
||||
// LTCG specific D3DDevice_SelectVertexShader function...
|
||||
|
@ -3599,56 +3531,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SelectVertexShader)
|
|||
LOG_FUNC_ARG(Address)
|
||||
LOG_FUNC_END;
|
||||
|
||||
HRESULT hRet = D3D_OK;
|
||||
|
||||
// Address always indicates a previously loaded vertex shader slot (from where the program is used).
|
||||
// Handle can be null if the current Xbox VertexShader is assigned
|
||||
// Handle can be an address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// If Handle is assigned, it becomes the new current Xbox VertexShader,
|
||||
// which resets a bit of state (nv2a execution mode, viewport, ?)
|
||||
// Either way, the given address slot is selected as the start of the current vertex shader program
|
||||
g_Xbox_VertexShader_Handle = Handle;
|
||||
|
||||
CxbxVertexShader *pCxbxVertexShader = nullptr;
|
||||
DWORD HostFVF = 0;
|
||||
|
||||
if(VshHandleIsVertexShader(Handle))
|
||||
{
|
||||
pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
SetCxbxVertexShader(pCxbxVertexShader);
|
||||
}
|
||||
else if(Handle == xbnull)
|
||||
{
|
||||
HostFVF = D3DFVF_XYZ | D3DFVF_TEX0;
|
||||
// Clear any vertex shader that may be set
|
||||
hRet = g_pD3DDevice->SetVertexShader(nullptr);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader()");
|
||||
// Set the FVF
|
||||
hRet = g_pD3DDevice->SetFVF(HostFVF);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX0)");
|
||||
}
|
||||
else if(Address < 136)
|
||||
{
|
||||
X_D3DVertexShader *pXboxVertexShader = (X_D3DVertexShader*)g_VertexShaderSlots[Address];
|
||||
|
||||
if(pXboxVertexShader != nullptr)
|
||||
{
|
||||
LOG_TEST_CASE("Assigned g_VertexShaderSlots");
|
||||
// Was : pCxbxVertexShader = (CxbxVertexShader *)(pXboxVertexShader->CxbxVertexShaderHandle);
|
||||
// However, the CxbxVertexShaderHandle union is never set, so could lead to using undefined data!
|
||||
}
|
||||
else
|
||||
{
|
||||
EmuLog(LOG_LEVEL::WARNING, "g_VertexShaderSlots[%d] = 0", Address);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hRet))
|
||||
{
|
||||
EmuLog(LOG_LEVEL::WARNING, "We're lying about setting a vertext shader!");
|
||||
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
CxbxImpl_SelectVertexShader(Handle, Address);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -4193,102 +4076,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
|
|||
*pHandle = ((DWORD)malloc(sizeof(X_D3DVertexShader)) & D3DFVF_RESERVED0);
|
||||
}
|
||||
|
||||
if (g_pD3DDevice == nullptr) {
|
||||
LOG_TEST_CASE("D3DDevice_CreateVertexShader called before Direct3D_CreateDevice");
|
||||
// We lie to allow the game to continue for now, but it probably won't work well
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// HACK: TODO: support this situation
|
||||
if(pDeclaration == nullptr) {
|
||||
LOG_TEST_CASE("Vertex shader without declaration");
|
||||
*pHandle = xbnull;
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
// Now, we can create the host vertex shader
|
||||
DWORD XboxDeclarationCount = 0;
|
||||
CxbxVertexShader* pCxbxVertexShader = (CxbxVertexShader*)calloc(1, sizeof(CxbxVertexShader));
|
||||
D3DVERTEXELEMENT *pRecompiledDeclaration = nullptr;
|
||||
|
||||
pRecompiledDeclaration = EmuRecompileVshDeclaration((DWORD*)pDeclaration,
|
||||
/*bIsFixedFunction=*/pFunction == xbnullptr,
|
||||
&XboxDeclarationCount,
|
||||
&pCxbxVertexShader->VertexShaderInfo);
|
||||
|
||||
// Create the vertex declaration
|
||||
hRet = g_pD3DDevice->CreateVertexDeclaration(pRecompiledDeclaration, &pCxbxVertexShader->pHostVertexDeclaration);
|
||||
free(pRecompiledDeclaration);
|
||||
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->CreateVertexDeclaration");
|
||||
|
||||
if (FAILED(hRet)) {
|
||||
// NOTE: This is a fatal error because it ALWAYS triggers a crash within DrawVertices if not set
|
||||
CxbxKrnlCleanup("Failed to create Vertex Declaration");
|
||||
}
|
||||
g_pD3DDevice->SetVertexDeclaration(pCxbxVertexShader->pHostVertexDeclaration);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexDeclaration");
|
||||
|
||||
uint64_t vertexShaderKey = 0;
|
||||
DWORD XboxFunctionSize = 0;
|
||||
if (SUCCEEDED(hRet) && pFunction)
|
||||
{
|
||||
vertexShaderKey = g_VertexShaderSource.CreateShader(pFunction, &XboxFunctionSize);
|
||||
}
|
||||
|
||||
pCxbxVertexShader->pXboxDeclarationCopy = (DWORD*)malloc(XboxDeclarationCount * sizeof(DWORD));
|
||||
memcpy(pCxbxVertexShader->pXboxDeclarationCopy, pDeclaration, XboxDeclarationCount * sizeof(DWORD));
|
||||
pCxbxVertexShader->XboxFunctionSize = 0;
|
||||
pCxbxVertexShader->pXboxFunctionCopy = nullptr;
|
||||
pCxbxVertexShader->XboxVertexShaderType = X_VST_NORMAL; // TODO : This can vary
|
||||
pCxbxVertexShader->XboxNrAddressSlots = (XboxFunctionSize - sizeof(X_VSH_SHADER_HEADER)) / X_VSH_INSTRUCTION_SIZE_BYTES;
|
||||
pCxbxVertexShader->HostFVF = 0;
|
||||
pCxbxVertexShader->VertexShaderKey = vertexShaderKey;
|
||||
pCxbxVertexShader->XboxDeclarationCount = XboxDeclarationCount;
|
||||
// Save the status, to remove things later
|
||||
// pCxbxVertexShader->XboxStatus = hRet; // Not even used by VshHandleIsValidShader()
|
||||
|
||||
if(SUCCEEDED(hRet))
|
||||
{
|
||||
if(pFunction != xbnullptr)
|
||||
{
|
||||
pCxbxVertexShader->XboxFunctionSize = XboxFunctionSize;
|
||||
pCxbxVertexShader->pXboxFunctionCopy = (DWORD*)malloc(XboxFunctionSize);
|
||||
memcpy(pCxbxVertexShader->pXboxFunctionCopy, pFunction, XboxFunctionSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TEST_CASE("Falling back to FVF shader");
|
||||
pCxbxVertexShader->HostFVF = D3DFVF_XYZ | D3DFVF_TEX0;
|
||||
}
|
||||
|
||||
// Register the host Vertex Shader
|
||||
SetCxbxVertexShader(*pHandle, pCxbxVertexShader);
|
||||
|
||||
if(FAILED(hRet))
|
||||
{
|
||||
#ifdef _DEBUG_TRACK_VS
|
||||
if (pFunction)
|
||||
{
|
||||
char pFileName[30];
|
||||
static int FailedShaderCount = 0;
|
||||
X_VSH_SHADER_HEADER *pHeader = (X_VSH_SHADER_HEADER*)pFunction;
|
||||
EmuLog(LOG_LEVEL::WARNING, "Couldn't create vertex shader!");
|
||||
sprintf(pFileName, "failed%05d.xvu", FailedShaderCount);
|
||||
FILE *f = fopen(pFileName, "wb");
|
||||
if(f)
|
||||
{
|
||||
fwrite(pFunction, sizeof(X_VSH_SHADER_HEADER) + pHeader->NumInst * 16, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
FailedShaderCount++;
|
||||
}
|
||||
#endif // _DEBUG_TRACK_VS
|
||||
//hRet = D3D_OK;
|
||||
}
|
||||
|
||||
return hRet;
|
||||
return CxbxImpl_CreateVertexShader(pDeclaration, pFunction, pHandle, Usage);
|
||||
}
|
||||
|
||||
// LTCG specific D3DDevice_SetVertexShaderConstant function...
|
||||
|
@ -4330,37 +4118,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexShaderConstant)
|
|||
LOG_FUNC_ARG(ConstantCount)
|
||||
LOG_FUNC_END;
|
||||
|
||||
/*#ifdef _DEBUG_TRACK_VS_CONST
|
||||
for (uint32_t i = 0; i < ConstantCount; i++)
|
||||
{
|
||||
printf("SetVertexShaderConstant, c%d = { %f, %f, %f, %f }\n",
|
||||
Register + i,
|
||||
*((float*)pConstantData + 4 * i),
|
||||
*((float*)pConstantData + 4 * i + 1),
|
||||
*((float*)pConstantData + 4 * i + 2),
|
||||
*((float*)pConstantData + 4 * i + 3));
|
||||
}
|
||||
#endif*/ // _DEBUG_TRACK_VS_CONST
|
||||
|
||||
// Xbox vertex shader constants range from -96 to 95
|
||||
// The host does not support negative, so we adjust to 0..191
|
||||
Register += X_D3DSCM_CORRECTION;
|
||||
|
||||
if (Register < 0) LOG_TEST_CASE("Register < 0");
|
||||
if (Register + ConstantCount > X_D3DVS_CONSTREG_COUNT) LOG_TEST_CASE("Register + ConstantCount > X_D3DVS_CONSTREG_COUNT");
|
||||
HRESULT hRet;
|
||||
hRet = g_pD3DDevice->SetVertexShaderConstantF(
|
||||
Register,
|
||||
(float*)pConstantData,
|
||||
ConstantCount
|
||||
);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShaderConstant");
|
||||
|
||||
if(FAILED(hRet))
|
||||
{
|
||||
EmuLog(LOG_LEVEL::WARNING, "We're lying about setting a vertex shader constant!");
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
CxbxImpl_SetVertexShaderConstant(Register, pConstantData, ConstantCount);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -6714,29 +6472,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetVertexShader)
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(Handle);
|
||||
|
||||
// Checks if the Handle has bit 0 set - if not, it's a FVF
|
||||
// which is converted to a global Xbox Vertex Shader struct
|
||||
// Otherwise bit 0 is cleared and the resulting address is
|
||||
// validated to be a valid Xbox Vertex Shader
|
||||
// D3D state fields are updated.
|
||||
// If the shader contains a program, the handle is passed to
|
||||
// D3DDevice_LoadVertexShader and D3DDevice_SelectVertexShader.
|
||||
// Otherwise the shader is send using push buffer commands.
|
||||
|
||||
HRESULT hRet = D3D_OK;
|
||||
|
||||
g_Xbox_VertexShader_Handle = Handle;
|
||||
|
||||
if (VshHandleIsVertexShader(Handle)) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
SetCxbxVertexShader(pCxbxVertexShader);
|
||||
|
||||
} else {
|
||||
hRet = g_pD3DDevice->SetVertexShader(nullptr);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");
|
||||
hRet = g_pD3DDevice->SetFVF(Handle);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetFVF");
|
||||
}
|
||||
CxbxImpl_SetVertexShader(Handle);
|
||||
|
||||
UpdateViewPortOffsetAndScaleConstants();
|
||||
}
|
||||
|
@ -7936,36 +7672,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DeleteVertexShader)
|
|||
|
||||
XB_TRMP(D3DDevice_DeleteVertexShader)(Handle);
|
||||
|
||||
// Handle is always address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// It's reference count is lowered. If it reaches zero (0), the struct is freed.
|
||||
|
||||
if (VshHandleIsVertexShader(Handle))
|
||||
{
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
SetCxbxVertexShader(Handle, nullptr);
|
||||
|
||||
if (pCxbxVertexShader->pHostVertexDeclaration) {
|
||||
HRESULT hRet = pCxbxVertexShader->pHostVertexDeclaration->Release();
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->DeleteVertexShader(pHostVertexDeclaration)");
|
||||
}
|
||||
|
||||
// Release the host vertex shader
|
||||
g_VertexShaderSource.ReleaseShader(pCxbxVertexShader->VertexShaderKey);
|
||||
|
||||
if (pCxbxVertexShader->pXboxDeclarationCopy)
|
||||
{
|
||||
free(pCxbxVertexShader->pXboxDeclarationCopy);
|
||||
}
|
||||
|
||||
if (pCxbxVertexShader->pXboxFunctionCopy)
|
||||
{
|
||||
free(pCxbxVertexShader->pXboxFunctionCopy);
|
||||
}
|
||||
|
||||
FreeVertexDynamicPatch(pCxbxVertexShader);
|
||||
|
||||
free(pCxbxVertexShader);
|
||||
}
|
||||
CxbxImpl_DeleteVertexShader(Handle);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -8140,232 +7847,21 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_RunVertexStateShader)
|
|||
LOG_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
// Maps pFunction defintions to pre-compiled shaders
|
||||
// to reduce the speed impact of LoadVertexShaderProgram
|
||||
typedef uint64_t load_shader_program_key_t;
|
||||
std::unordered_map<load_shader_program_key_t, DWORD> g_LoadVertexShaderProgramCache;
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_LoadVertexShaderProgram
|
||||
// ******************************************************************
|
||||
VOID WINAPI XTL::EMUPATCH(D3DDevice_LoadVertexShaderProgram)
|
||||
(
|
||||
CONST DWORD *pFunction,
|
||||
DWORD Address
|
||||
)
|
||||
CONST DWORD *pFunction,
|
||||
DWORD Address
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(pFunction)
|
||||
LOG_FUNC_ARG(Address)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// D3DDevice_LoadVertexShaderProgram splits the given function buffer into batch-wise pushes to the NV2A
|
||||
|
||||
load_shader_program_key_t shaderCacheKey = ((load_shader_program_key_t)g_Xbox_VertexShader_Handle << 32) | (DWORD)pFunction;
|
||||
|
||||
// If the shader key was located in the cache, use the cached shader
|
||||
// TODO: When do we clear the cache? In this approach, shaders are
|
||||
// never freed...
|
||||
auto it = g_LoadVertexShaderProgramCache.find(shaderCacheKey);
|
||||
if (it != g_LoadVertexShaderProgramCache.end()) {
|
||||
EMUPATCH(D3DDevice_LoadVertexShader)(it->second, Address);
|
||||
EMUPATCH(D3DDevice_SelectVertexShader)(it->second, Address);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD *pXboxVertexDeclaration = nullptr;
|
||||
|
||||
if (VshHandleIsVertexShader(g_Xbox_VertexShader_Handle)) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(g_Xbox_VertexShader_Handle);
|
||||
|
||||
// If we failed to fetch an active pixel shader, log and do nothing
|
||||
if (pCxbxVertexShader == nullptr) {
|
||||
LOG_TEST_CASE("D3DDevice_LoadVertexShaderProgram: Failed to locate original shader");
|
||||
return;
|
||||
}
|
||||
|
||||
// Simply retrieve the contents of the existing vertex shader program
|
||||
pXboxVertexDeclaration = pCxbxVertexShader->pXboxDeclarationCopy;
|
||||
} else {
|
||||
// This is an unusual scenario in which an FVF-based shader is being replaced with an actual shader
|
||||
// But without calling CreateVertexShader: This means we need to parse the current FVF and generate
|
||||
// our own Xbox-like declaration to use when converting/setting this new shader
|
||||
|
||||
// Define a large enough definition to contain all possible FVF types
|
||||
// 20 is maximum possible size
|
||||
DWORD CxbxXboxVertexDeclaration[20] = { 0 };
|
||||
int index = 0;
|
||||
|
||||
// Write the Stream Number (always 0 for FVF)
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_STREAM(0);
|
||||
|
||||
// Write Position
|
||||
DWORD position = (g_Xbox_VertexShader_Handle & X_D3DFVF_POSITION_MASK);
|
||||
if (position == X_D3DFVF_XYZRHW) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_POSITION, X_D3DVSDT_FLOAT4);
|
||||
} else {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_POSITION, X_D3DVSDT_FLOAT3);
|
||||
}
|
||||
|
||||
// Write Blend Weights
|
||||
if (position == X_D3DFVF_XYZB1) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_BLENDWEIGHT, X_D3DVSDT_FLOAT1);
|
||||
}
|
||||
if (position == X_D3DFVF_XYZB2) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_BLENDWEIGHT, X_D3DVSDT_FLOAT2);
|
||||
}
|
||||
if (position == X_D3DFVF_XYZB3) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_BLENDWEIGHT, X_D3DVSDT_FLOAT3);
|
||||
}
|
||||
if (position == X_D3DFVF_XYZB4) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_BLENDWEIGHT, X_D3DVSDT_FLOAT4);
|
||||
}
|
||||
|
||||
// Write Normal, Diffuse, and Specular
|
||||
if (g_Xbox_VertexShader_Handle & X_D3DFVF_NORMAL) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_NORMAL, X_D3DVSDT_FLOAT3);
|
||||
}
|
||||
if (g_Xbox_VertexShader_Handle & X_D3DFVF_DIFFUSE) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_DIFFUSE, X_D3DVSDT_D3DCOLOR);
|
||||
}
|
||||
if (g_Xbox_VertexShader_Handle & X_D3DFVF_SPECULAR) {
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_SPECULAR, X_D3DVSDT_D3DCOLOR);
|
||||
}
|
||||
|
||||
// Write Texture Coordinates
|
||||
int textureCount = (g_Xbox_VertexShader_Handle & X_D3DFVF_TEXCOUNT_MASK) >> X_D3DFVF_TEXCOUNT_SHIFT;
|
||||
assert(textureCount <= 4); // Safeguard, since the X_D3DFVF_TEXCOUNT bitfield could contain invalid values (5 up to 15)
|
||||
for (int i = 0; i < textureCount; i++) {
|
||||
int numberOfCoordinates = 0;
|
||||
|
||||
if ((g_Xbox_VertexShader_Handle & X_D3DFVF_TEXCOORDSIZE1(i)) == (DWORD)X_D3DFVF_TEXCOORDSIZE1(i)) {
|
||||
numberOfCoordinates = X_D3DVSDT_FLOAT1;
|
||||
}
|
||||
if ((g_Xbox_VertexShader_Handle & X_D3DFVF_TEXCOORDSIZE2(i)) == (DWORD)X_D3DFVF_TEXCOORDSIZE2(i)) {
|
||||
numberOfCoordinates = X_D3DVSDT_FLOAT2;
|
||||
}
|
||||
if ((g_Xbox_VertexShader_Handle & X_D3DFVF_TEXCOORDSIZE3(i)) == (DWORD)X_D3DFVF_TEXCOORDSIZE3(i)) {
|
||||
numberOfCoordinates = X_D3DVSDT_FLOAT3;
|
||||
}
|
||||
if ((g_Xbox_VertexShader_Handle & X_D3DFVF_TEXCOORDSIZE4(i)) == (DWORD)X_D3DFVF_TEXCOORDSIZE4(i)) {
|
||||
numberOfCoordinates = X_D3DVSDT_FLOAT4;
|
||||
}
|
||||
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_REG(X_D3DVSDE_TEXCOORD0 + i, numberOfCoordinates);
|
||||
}
|
||||
|
||||
// Write Declaration End
|
||||
CxbxXboxVertexDeclaration[index++] = X_D3DVSD_END();
|
||||
|
||||
pXboxVertexDeclaration = CxbxXboxVertexDeclaration;
|
||||
// Now we can fall through and create a new vertex shader
|
||||
}
|
||||
|
||||
// Create a vertex shader with the new vertex program data
|
||||
DWORD hNewXboxShader = 0;
|
||||
HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)(pXboxVertexDeclaration, pFunction, &hNewXboxShader, 0);
|
||||
|
||||
if( FAILED( hr ) )
|
||||
CxbxKrnlCleanup("Error creating new vertex shader!" );
|
||||
|
||||
EMUPATCH(D3DDevice_LoadVertexShader)(hNewXboxShader, Address);
|
||||
EMUPATCH(D3DDevice_SelectVertexShader)(hNewXboxShader, Address);
|
||||
|
||||
g_LoadVertexShaderProgramCache[shaderCacheKey] = hNewXboxShader;
|
||||
|
||||
EmuLog(LOG_LEVEL::WARNING, "Vertex Shader Cache Size: %d", g_LoadVertexShaderProgramCache.size());
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_GetVertexShaderDeclaration
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetVertexShaderDeclaration)
|
||||
(
|
||||
DWORD Handle,
|
||||
PVOID pData,
|
||||
DWORD *pSizeOfData
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(Handle)
|
||||
LOG_FUNC_ARG(pData)
|
||||
LOG_FUNC_ARG(pSizeOfData)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Handle is always address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// If the pData buffer pointer is given, pSizeOfData is the address of it's size (in bytes)
|
||||
// If pData is null, pSizeOfData is still given (to receive the required data size)
|
||||
|
||||
|
||||
// The VertexShader is converted back into the contained program and it's size.
|
||||
// In any case, *pSizeOfData will be set to the program size.
|
||||
// If the pData is null, no further action it taken.
|
||||
// If the pData buffer pointer is given, but the given *pSizeOfData is smaller than the program size, an error is returned.
|
||||
// Otherwise, the program is unbatched and copied into the pData buffer.
|
||||
|
||||
HRESULT hRet = D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSizeOfData) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
if (pCxbxVertexShader) {
|
||||
DWORD sizeOfData = pCxbxVertexShader->XboxDeclarationCount * sizeof(DWORD);
|
||||
if (*pSizeOfData < sizeOfData || !pData) {
|
||||
*pSizeOfData = sizeOfData;
|
||||
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
else {
|
||||
memcpy(pData, pCxbxVertexShader->pXboxDeclarationCopy, pCxbxVertexShader->XboxDeclarationCount * sizeof(DWORD));
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hRet;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_GetVertexShaderFunction
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetVertexShaderFunction)
|
||||
(
|
||||
DWORD Handle,
|
||||
PVOID *pData,
|
||||
DWORD *pSizeOfData
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(Handle)
|
||||
LOG_FUNC_ARG(pData)
|
||||
LOG_FUNC_ARG(pSizeOfData)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Handle is always address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// If the pData buffer pointer is given, pSizeOfData is the address of it's size (in bytes)
|
||||
// If pData is null, pSizeOfData is still given (to receive the required data size)
|
||||
|
||||
// The VertexShader is parsed and converted back into the underlying declaration and it's size.
|
||||
// In any case, *pSizeOfData will be set to the declaration size.
|
||||
// If the pData is null, no further action it taken.
|
||||
// If the pData buffer pointer is given, but the given *pSizeOfData is smaller than the declaration size, an error is returned.
|
||||
// Otherwise, the declaration is copied into the pData buffer.
|
||||
|
||||
HRESULT hRet = D3DERR_INVALIDCALL;
|
||||
|
||||
if(pSizeOfData) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
if (pCxbxVertexShader) {
|
||||
if (*pSizeOfData < pCxbxVertexShader->XboxFunctionSize || !pData) {
|
||||
*pSizeOfData = pCxbxVertexShader->XboxFunctionSize;
|
||||
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
else {
|
||||
memcpy(pData, pCxbxVertexShader->pXboxFunctionCopy, pCxbxVertexShader->XboxFunctionSize);
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hRet;
|
||||
CxbxImpl_LoadVertexShaderProgram(pFunction, Address);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -4043,3 +4043,95 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_GetViewportOffsetAndScale)
|
|||
pScale->z = vScale[2];
|
||||
pScale->w = vScale[3];
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_GetVertexShaderDeclaration
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetVertexShaderDeclaration)
|
||||
(
|
||||
DWORD Handle,
|
||||
PVOID pData,
|
||||
DWORD *pSizeOfData
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(Handle)
|
||||
LOG_FUNC_ARG(pData)
|
||||
LOG_FUNC_ARG(pSizeOfData)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Handle is always address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// If the pData buffer pointer is given, pSizeOfData is the address of it's size (in bytes)
|
||||
// If pData is null, pSizeOfData is still given (to receive the required data size)
|
||||
|
||||
|
||||
// The VertexShader is converted back into the contained program and it's size.
|
||||
// In any case, *pSizeOfData will be set to the program size.
|
||||
// If the pData is null, no further action it taken.
|
||||
// If the pData buffer pointer is given, but the given *pSizeOfData is smaller than the program size, an error is returned.
|
||||
// Otherwise, the program is unbatched and copied into the pData buffer.
|
||||
|
||||
HRESULT hRet = D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSizeOfData) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
if (pCxbxVertexShader) {
|
||||
DWORD sizeOfData = pCxbxVertexShader->Declaration.XboxDeclarationCount * sizeof(DWORD);
|
||||
if (*pSizeOfData < sizeOfData || !pData) {
|
||||
*pSizeOfData = sizeOfData;
|
||||
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
else {
|
||||
memcpy(pData, pCxbxVertexShader->Declaration.pXboxDeclarationCopy, pCxbxVertexShader->Declaration.XboxDeclarationCount * sizeof(DWORD));
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hRet;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: D3DDevice_GetVertexShaderFunction
|
||||
// ******************************************************************
|
||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_GetVertexShaderFunction)
|
||||
(
|
||||
DWORD Handle,
|
||||
PVOID *pData,
|
||||
DWORD *pSizeOfData
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(Handle)
|
||||
LOG_FUNC_ARG(pData)
|
||||
LOG_FUNC_ARG(pSizeOfData)
|
||||
LOG_FUNC_END;
|
||||
|
||||
// Handle is always address of an Xbox VertexShader struct, or-ed with 1 (X_D3DFVF_RESERVED0)
|
||||
// If the pData buffer pointer is given, pSizeOfData is the address of it's size (in bytes)
|
||||
// If pData is null, pSizeOfData is still given (to receive the required data size)
|
||||
|
||||
// The VertexShader is parsed and converted back into the underlying declaration and it's size.
|
||||
// In any case, *pSizeOfData will be set to the declaration size.
|
||||
// If the pData is null, no further action it taken.
|
||||
// If the pData buffer pointer is given, but the given *pSizeOfData is smaller than the declaration size, an error is returned.
|
||||
// Otherwise, the declaration is copied into the pData buffer.
|
||||
|
||||
HRESULT hRet = D3DERR_INVALIDCALL;
|
||||
|
||||
if(pSizeOfData) {
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(Handle);
|
||||
if (pCxbxVertexShader) {
|
||||
if (*pSizeOfData < pCxbxVertexShader->XboxFunctionSize || !pData) {
|
||||
*pSizeOfData = pCxbxVertexShader->XboxFunctionSize;
|
||||
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
|
||||
}
|
||||
else {
|
||||
memcpy(pData, pCxbxVertexShader->pXboxFunctionCopy, pCxbxVertexShader->XboxFunctionSize);
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hRet;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ void BuildShader(IntermediateVertexShader* pShader, std::stringstream& hlsl)
|
|||
/*ILU_LIT:*/"x_lit" // = 7 - all values of the 3 bits are used
|
||||
};
|
||||
|
||||
for (int i = 0; i < pShader->Instructions.size(); i++) {
|
||||
for (size_t i = 0; i < pShader->Instructions.size(); i++) {
|
||||
VSH_INTERMEDIATE_FORMAT& IntermediateInstruction = pShader->Instructions[i];
|
||||
|
||||
std::string str;
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include "Logging.h"
|
||||
#include "util/hasher.h"
|
||||
#include "core/kernel/support/Emu.h"
|
||||
|
||||
VertexShaderSource g_VertexShaderSource = VertexShaderSource();
|
||||
// FIXME : This should really be released and created in step with the D3D device lifecycle rather than being a thing on its own
|
||||
// (And the ResetD3DDevice method should be removed)
|
||||
|
||||
ID3DBlob* AsyncCreateVertexShader(IntermediateVertexShader intermediateShader, ShaderKey key) {
|
||||
// HACK set thread affinity every call to reduce interference with Xbox main thread
|
||||
|
@ -40,13 +44,14 @@ ID3DBlob* AsyncCreateVertexShader(IntermediateVertexShader intermediateShader, S
|
|||
// Create a new shader
|
||||
// If the shader was already created, just increase its reference count
|
||||
ShaderKey VertexShaderSource::CreateShader(const DWORD* pXboxFunction, DWORD *pXboxFunctionSize) {
|
||||
IntermediateVertexShader intermediateShader;
|
||||
IntermediateVertexShader intermediateShader;
|
||||
|
||||
// Parse into intermediate format
|
||||
EmuParseVshFunction((DWORD*)pXboxFunction,
|
||||
pXboxFunctionSize,
|
||||
&intermediateShader);
|
||||
|
||||
|
||||
// FIXME ignore shader header when creating key
|
||||
ShaderKey key = ComputeHash((void*)pXboxFunction, *pXboxFunctionSize);
|
||||
|
||||
// Check if we need to create the shader
|
||||
|
|
|
@ -41,5 +41,7 @@ private:
|
|||
|
||||
bool VertexShaderSource::_FindShader(ShaderKey key, LazyVertexShader** ppLazyShader);
|
||||
};
|
||||
|
||||
extern VertexShaderSource g_VertexShaderSource;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,17 @@
|
|||
|
||||
#include "Logging.h"
|
||||
#include "XbD3D8Types.h"
|
||||
|
||||
extern const char* D3DErrorString(HRESULT hResult); // Implemented in Direct3D9.cpp
|
||||
|
||||
#define DEBUG_D3DRESULT(hRet, message) \
|
||||
do { \
|
||||
LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { \
|
||||
if (FAILED(hRet)) \
|
||||
if(g_bPrintfOn) \
|
||||
printf("%s%s : %s D3D error (0x%.08X: %s)\n", _logThreadPrefix.c_str(), _logFuncPrefix.c_str(), message, hRet, D3DErrorString(hRet)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Additional types, exclusively for logging (not really enums) :
|
||||
enum D3DVS20CAPS : int;
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "core\kernel\support\Emu.h"
|
||||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For g_pD3DDevice, g_pXbox_PixelShader
|
||||
#include "core\hle\D3D8\XbPixelShader.h"
|
||||
#include "core\hle\D3D8\XbD3D8Logging.h" // For D3DErrorString()
|
||||
|
||||
#include "core\kernel\init\CxbxKrnl.h" // For CxbxKrnlCleanup()
|
||||
|
||||
|
@ -5920,8 +5921,6 @@ static const
|
|||
);
|
||||
|
||||
if (hRet != D3D_OK) {
|
||||
extern const char *D3DErrorString(HRESULT hResult);
|
||||
|
||||
printf(D3DErrorString(hRet));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,9 +180,9 @@ DWORD CxbxGetStrideFromVertexShaderHandle(DWORD dwVertexShader)
|
|||
|
||||
CxbxVertexShader *pCxbxVertexShader = GetCxbxVertexShader(dwVertexShader);
|
||||
if (pCxbxVertexShader) {
|
||||
if (pCxbxVertexShader->VertexShaderInfo.NumberOfVertexStreams == 1) {
|
||||
if (pCxbxVertexShader->Declaration.NumberOfVertexStreams == 1) {
|
||||
// Note : This assumes that the only stream in use will be stream zero :
|
||||
Stride = pCxbxVertexShader->VertexShaderInfo.VertexStreams[0].HostVertexStride;
|
||||
Stride = pCxbxVertexShader->Declaration.VertexStreams[0].HostVertexStride;
|
||||
}
|
||||
else {
|
||||
LOG_TEST_CASE("Non-FVF Vertex Shaders with multiple streams not supported for PushBuffer emulation!");
|
||||
|
|
|
@ -113,7 +113,7 @@ CxbxPatchedStream::~CxbxPatchedStream()
|
|||
CxbxVertexBufferConverter::CxbxVertexBufferConverter()
|
||||
{
|
||||
m_uiNbrStreams = 0;
|
||||
m_pVertexShaderInfo = nullptr;
|
||||
m_pCxbxVertexDeclaration = nullptr;
|
||||
}
|
||||
|
||||
int CountActiveD3DStreams()
|
||||
|
@ -128,7 +128,7 @@ int CountActiveD3DStreams()
|
|||
return lastStreamIndex;
|
||||
}
|
||||
|
||||
CxbxVertexShaderInfo *GetCxbxVertexShaderInfo(DWORD XboxVertexShaderHandle); // forward
|
||||
CxbxVertexDeclaration *GetCxbxVertexDeclaration(DWORD XboxVertexShaderHandle); // forward
|
||||
|
||||
UINT CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pDrawContext)
|
||||
{
|
||||
|
@ -138,13 +138,13 @@ UINT CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pDrawContext)
|
|||
}
|
||||
|
||||
if(VshHandleIsVertexShader(g_Xbox_VertexShader_Handle)) {
|
||||
CxbxVertexShaderInfo *pVertexShaderInfo = GetCxbxVertexShaderInfo(g_Xbox_VertexShader_Handle);
|
||||
if (pVertexShaderInfo) {
|
||||
if (pVertexShaderInfo->NumberOfVertexStreams <= X_VSH_MAX_STREAMS) {
|
||||
return pVertexShaderInfo->NumberOfVertexStreams;
|
||||
CxbxVertexDeclaration *pDecl = GetCxbxVertexDeclaration(g_Xbox_VertexShader_Handle);
|
||||
if (pDecl) {
|
||||
if (pDecl->NumberOfVertexStreams <= X_VSH_MAX_STREAMS) {
|
||||
return pDecl->NumberOfVertexStreams;
|
||||
}
|
||||
|
||||
// If we reached here, pVertexShaderInfo was set,but with invalid data
|
||||
// If we reached here, pDecl was set,but with invalid data
|
||||
LOG_TEST_CASE("NumberOfVertexStreams > 16");
|
||||
}
|
||||
|
||||
|
@ -261,13 +261,13 @@ void CxbxVertexBufferConverter::ConvertStream
|
|||
}
|
||||
|
||||
CxbxVertexShaderStreamInfo *pVertexShaderStreamInfo = nullptr;
|
||||
if (m_pVertexShaderInfo != nullptr) {
|
||||
if (uiStream > m_pVertexShaderInfo->NumberOfVertexStreams + 1) {
|
||||
if (m_pCxbxVertexDeclaration != nullptr) {
|
||||
if (uiStream > m_pCxbxVertexDeclaration->NumberOfVertexStreams + 1) {
|
||||
LOG_TEST_CASE("uiStream > NumberOfVertexStreams");
|
||||
return;
|
||||
}
|
||||
|
||||
pVertexShaderStreamInfo = &(m_pVertexShaderInfo->VertexStreams[uiStream]);
|
||||
pVertexShaderStreamInfo = &(m_pCxbxVertexDeclaration->VertexStreams[uiStream]);
|
||||
}
|
||||
|
||||
bool bNeedVertexPatching = (pVertexShaderStreamInfo != nullptr && pVertexShaderStreamInfo->NeedPatch);
|
||||
|
@ -759,9 +759,9 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
|
|||
if ((pDrawContext->XboxPrimitiveType < XTL::X_D3DPT_POINTLIST) || (pDrawContext->XboxPrimitiveType > XTL::X_D3DPT_POLYGON))
|
||||
CxbxKrnlCleanup("Unknown primitive type: 0x%.02X\n", pDrawContext->XboxPrimitiveType);
|
||||
|
||||
m_pVertexShaderInfo = nullptr;
|
||||
m_pCxbxVertexDeclaration = nullptr;
|
||||
if (VshHandleIsVertexShader(g_Xbox_VertexShader_Handle)) {
|
||||
m_pVertexShaderInfo = &(GetCxbxVertexShader(g_Xbox_VertexShader_Handle)->VertexShaderInfo);
|
||||
m_pCxbxVertexDeclaration = &(GetCxbxVertexShader(g_Xbox_VertexShader_Handle)->Declaration);
|
||||
}
|
||||
|
||||
// If we are drawing from an offset, we know that the vertex count must have
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "Cxbx.h"
|
||||
|
||||
#include "core\hle\D3D8\XbVertexShader.h" // for CxbxVertexShaderInfo
|
||||
#include "core\hle\D3D8\XbVertexShader.h"
|
||||
|
||||
typedef struct _CxbxDrawContext
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ class CxbxVertexBufferConverter
|
|||
std::list<CxbxPatchedStream> m_PatchedStreamUsageList; // Linked list of vertex streams, least recently used is last in the list
|
||||
CxbxPatchedStream& GetPatchedStream(uint64_t); // Fetches (or inserts) a patched stream associated with the given key
|
||||
|
||||
CxbxVertexShaderInfo *m_pVertexShaderInfo;
|
||||
CxbxVertexDeclaration *m_pCxbxVertexDeclaration;
|
||||
|
||||
// Returns the number of streams of a patch
|
||||
UINT GetNbrStreams(CxbxDrawContext *pPatchDesc);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -68,21 +68,22 @@ typedef struct _CxbxVertexShaderStreamInfo
|
|||
}
|
||||
CxbxVertexShaderStreamInfo;
|
||||
|
||||
typedef struct _CxbxVertexShaderInfo
|
||||
typedef struct _CxbxVertexDeclaration
|
||||
{
|
||||
UINT NumberOfVertexStreams; // The number of streams the vertex shader uses
|
||||
CxbxVertexShaderStreamInfo VertexStreams[X_VSH_MAX_STREAMS];
|
||||
bool vRegisterInDeclaration[16];
|
||||
IDirect3DVertexDeclaration* pHostVertexDeclaration;
|
||||
DWORD* pXboxDeclarationCopy;
|
||||
DWORD XboxDeclarationCount; // Xbox's number of DWORD-sized X_D3DVSD* tokens
|
||||
UINT NumberOfVertexStreams; // The number of streams the vertex shader uses
|
||||
bool vRegisterInDeclaration[X_VSH_MAX_ATTRIBUTES];
|
||||
}
|
||||
CxbxVertexShaderInfo;
|
||||
CxbxVertexDeclaration;
|
||||
|
||||
|
||||
typedef struct _CxbxVertexShader
|
||||
{
|
||||
// These are the parameters given by the XBE,
|
||||
// we save them to be able to return them when necessary.
|
||||
DWORD* pXboxDeclarationCopy;
|
||||
DWORD XboxDeclarationCount; // Xbox's number of DWORD-sized X_D3DVSD* tokens
|
||||
DWORD XboxFunctionSize;
|
||||
DWORD* pXboxFunctionCopy;
|
||||
UINT XboxNrAddressSlots;
|
||||
|
@ -90,12 +91,10 @@ typedef struct _CxbxVertexShader
|
|||
// DWORD XboxStatus; // Used by VshHandleIsValidShader()
|
||||
|
||||
// The resulting host variables
|
||||
DWORD HostFVF; // Flexible Vertex Format (used when there's no host vertex shader)
|
||||
uint64_t VertexShaderKey; // if nullptr, use SetFVF(HostFVF);
|
||||
IDirect3DVertexDeclaration* pHostVertexDeclaration;
|
||||
uint64_t VertexShaderKey;
|
||||
|
||||
// Needed for dynamic stream patching
|
||||
CxbxVertexShaderInfo VertexShaderInfo;
|
||||
CxbxVertexDeclaration Declaration;
|
||||
}
|
||||
CxbxVertexShader;
|
||||
|
||||
|
@ -105,7 +104,7 @@ extern D3DVERTEXELEMENT *EmuRecompileVshDeclaration
|
|||
DWORD *pXboxDeclaration,
|
||||
bool bIsFixedFunction,
|
||||
DWORD *pXboxDeclarationCount,
|
||||
CxbxVertexShaderInfo *pCxbxVertexShaderInfo
|
||||
CxbxVertexDeclaration *pCxbxVertexDeclaration
|
||||
);
|
||||
|
||||
// Intermediate vertex shader structures
|
||||
|
@ -233,8 +232,17 @@ extern boolean IsValidCurrentShader(void);
|
|||
inline boolean VshHandleIsVertexShader(DWORD Handle) { return (Handle & X_D3DFVF_RESERVED0) ? TRUE : FALSE; }
|
||||
inline boolean VshHandleIsFVF(DWORD Handle) { return !VshHandleIsVertexShader(Handle); }
|
||||
inline XTL::X_D3DVertexShader *VshHandleToXboxVertexShader(DWORD Handle) { return (XTL::X_D3DVertexShader *)(Handle & ~X_D3DFVF_RESERVED0);}
|
||||
|
||||
extern CxbxVertexShader* GetCxbxVertexShader(DWORD XboxVertexShaderHandle);
|
||||
extern void SetCxbxVertexShader(DWORD XboxVertexShaderHandle, CxbxVertexShader* shader);
|
||||
|
||||
extern CxbxVertexShader* GetCxbxVertexShader(DWORD XboxVertexShaderHandle);
|
||||
|
||||
extern void CxbxImpl_LoadVertexShaderProgram(CONST DWORD* pFunction, DWORD Address);
|
||||
extern void CxbxImpl_LoadVertexShader(DWORD Handle, DWORD Address);
|
||||
extern void CxbxImpl_SetVertexShader(DWORD Handle);
|
||||
extern void CxbxImpl_SelectVertexShaderDirect(XTL::X_VERTEXATTRIBUTEFORMAT* pVAF, DWORD Address);
|
||||
extern void CxbxImpl_SelectVertexShader(DWORD Handle, DWORD Address);
|
||||
extern void CxbxImpl_SetVertexShaderInput(DWORD Handle, UINT StreamCount, XTL::X_STREAMINPUT* pStreamInputs);
|
||||
extern void CxbxImpl_SetVertexShaderConstant(INT Register, PVOID pConstantData, DWORD ConstantCount);
|
||||
extern HRESULT CxbxImpl_CreateVertexShader(CONST DWORD *pDeclaration, CONST DWORD *pFunction, DWORD *pHandle, DWORD Usage);
|
||||
extern void CxbxImpl_DeleteVertexShader(DWORD Handle);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,8 +92,8 @@ std::map<const std::string, const xbox_patch_t> g_PatchTable = {
|
|||
PATCH_ENTRY("D3DDevice_GetTransform", XTL::EMUPATCH(D3DDevice_GetTransform), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_GetVertexShader", XTL::EMUPATCH(D3DDevice_GetVertexShader), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_GetVertexShaderConstant", XTL::EMUPATCH(D3DDevice_GetVertexShaderConstant), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_GetVertexShaderDeclaration", XTL::EMUPATCH(D3DDevice_GetVertexShaderDeclaration), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_GetVertexShaderFunction", XTL::EMUPATCH(D3DDevice_GetVertexShaderFunction), PATCH_HLE_D3D),
|
||||
//PATCH_ENTRY("D3DDevice_GetVertexShaderDeclaration", XTL::EMUPATCH(D3DDevice_GetVertexShaderDeclaration), PATCH_HLE_D3D),
|
||||
//PATCH_ENTRY("D3DDevice_GetVertexShaderFunction", XTL::EMUPATCH(D3DDevice_GetVertexShaderFunction), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_GetVertexShaderInput", XTL::EMUPATCH(D3DDevice_GetVertexShaderInput), PATCH_HLE_D3D),
|
||||
//PATCH_ENTRY("D3DDevice_GetVertexShaderSize", XTL::EMUPATCH(D3DDevice_GetVertexShaderSize), PATCH_HLE_D3D),
|
||||
//PATCH_ENTRY("D3DDevice_GetVertexShaderType", XTL::EMUPATCH(D3DDevice_GetVertexShaderType), PATCH_HLE_D3D),
|
||||
|
|
Loading…
Reference in New Issue