Enable fixed function vertex shader
- Various bits of glue code - Toggle Shader/D3D9 with F2 - Replace vertex shader mode flags with enum
This commit is contained in:
parent
5720444c6b
commit
f98d040a65
|
@ -1908,6 +1908,10 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
|
|||
extern void DSound_PrintStats(); //TODO: move into plugin class usage.
|
||||
DSound_PrintStats();
|
||||
}
|
||||
else if (wParam == VK_F2)
|
||||
{
|
||||
g_UseFixedFunctionVertexShader = !g_UseFixedFunctionVertexShader;
|
||||
}
|
||||
else if (wParam == VK_F3)
|
||||
{
|
||||
g_bClipCursor = !g_bClipCursor;
|
||||
|
@ -2885,8 +2889,6 @@ void GetMultiSampleScaleRaw(float& xScale, float& yScale) {
|
|||
// Titles can render pre-transformed vertices to screen space (using XYZRHW vertex position data or otherwise)
|
||||
// so we need to know the space they are in to interpret it correctly
|
||||
void GetScreenScaleFactors(float& scaleX, float& scaleY) {
|
||||
extern bool g_Xbox_VertexShader_IsPassthrough;
|
||||
|
||||
// Example:
|
||||
// NFS HP2 renders in-game at 640*480
|
||||
// The title uses MSAA, which increases the rendertarget size, but leaves the screen scale unaffected
|
||||
|
@ -2916,7 +2918,7 @@ void GetScreenScaleFactors(float& scaleX, float& scaleY) {
|
|||
// - Antialias sample (background gradient)
|
||||
// Vertex program passthrough equivalent (title does apply backbuffer scale):
|
||||
// - NFS:HP2 (car speed and other in-game UI elements)
|
||||
if (!g_Xbox_VertexShader_IsPassthrough) {
|
||||
if (g_Xbox_VertexShaderMode != VertexShaderMode::Passthrough) {
|
||||
scaleX *= g_Xbox_BackbufferScaleX;
|
||||
scaleY *= g_Xbox_BackbufferScaleY;
|
||||
}
|
||||
|
@ -4169,8 +4171,6 @@ void GetXboxViewportOffsetAndScale(float (&vOffset)[4], float(&vScale)[4])
|
|||
|
||||
void CxbxUpdateHostViewPortOffsetAndScaleConstants()
|
||||
{
|
||||
extern bool g_Xbox_VertexShader_IsPassthrough;
|
||||
|
||||
float vScaleOffset[2][4]; // 0 - scale 1 - offset
|
||||
GetXboxViewportOffsetAndScale(vScaleOffset[1], vScaleOffset[0]);
|
||||
|
||||
|
@ -4196,7 +4196,7 @@ void CxbxUpdateHostViewPortOffsetAndScaleConstants()
|
|||
|
||||
// Passthrough should range 0 to 1, instead of 0 to zbuffer depth
|
||||
// Test case: DoA3 character select
|
||||
float zOutputScale = g_Xbox_VertexShader_IsPassthrough ? 1 : g_ZScale;
|
||||
float zOutputScale = g_Xbox_VertexShaderMode == VertexShaderMode::Passthrough ? 1 : g_ZScale;
|
||||
|
||||
float screenspaceScale[4] = { xboxScreenspaceWidth / 2, -xboxScreenspaceHeight / 2, zOutputScale, 1 };
|
||||
float screenspaceOffset[4] = { xboxScreenspaceWidth / 2 + aaOffsetX, xboxScreenspaceHeight / 2 + aaOffsetY, 0, 0 };
|
||||
|
@ -7343,7 +7343,7 @@ void CxbxUpdateHostTextureScaling()
|
|||
|
||||
// Texcoord index. Just the texture stage unless fixed function mode
|
||||
int texCoordIndex = stage;
|
||||
if (g_Xbox_VertexShader_IsFixedFunction) {
|
||||
if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction) {
|
||||
// Get TEXCOORDINDEX for the current texture stage's state
|
||||
// Stores both the texture stage index and information for generating coordinates
|
||||
// See D3DTSS_TEXCOORDINDEX
|
||||
|
@ -7434,7 +7434,7 @@ void CxbxUpdateHostViewport() {
|
|||
aaScaleX *= g_RenderTargetUpscaleFactor;
|
||||
aaScaleY *= g_RenderTargetUpscaleFactor;
|
||||
|
||||
if (g_Xbox_VertexShader_IsFixedFunction) {
|
||||
if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction) {
|
||||
// Set viewport
|
||||
D3DVIEWPORT hostViewport = g_Xbox_Viewport;
|
||||
hostViewport.X *= aaScaleX;
|
||||
|
@ -7495,6 +7495,11 @@ void CxbxUpdateNativeD3DResources()
|
|||
CxbxUpdateHostVertexShaderConstants();
|
||||
|
||||
CxbxUpdateHostViewport();
|
||||
|
||||
// Update fixed function vertex shader state
|
||||
if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction && g_UseFixedFunctionVertexShader) {
|
||||
UpdateFixedFunctionVertexShaderState();
|
||||
}
|
||||
|
||||
// NOTE: Order is important here
|
||||
// Some Texture States depend on RenderState values (Point Sprites)
|
||||
|
|
|
@ -844,7 +844,7 @@ void CxbxImpl_End()
|
|||
// Arrange for g_InlineVertexBuffer_AttributeFormat to be returned in CxbxGetVertexDeclaration,
|
||||
// so that our above composed declaration will be used for the next draw :
|
||||
g_InlineVertexBuffer_DeclarationOverride = true;
|
||||
// Note, that g_Xbox_VertexShader_IsFixedFunction should be left untouched,
|
||||
// Note, that g_Xbox_VertexShaderMode should be left untouched,
|
||||
// because except for the declaration override, the Xbox shader (either FVF
|
||||
// or a program, or even passthrough shaders) should still be in effect!
|
||||
|
||||
|
|
|
@ -58,9 +58,9 @@ extern XboxRenderStateConverter XboxRenderStates; // Declared in Direct3D9.cpp
|
|||
xbox::X_STREAMINPUT g_Xbox_SetVertexShaderInput_Data[X_VSH_MAX_STREAMS] = { 0 }; // Active when g_Xbox_SetVertexShaderInput_Count > 0
|
||||
xbox::X_VERTEXATTRIBUTEFORMAT g_Xbox_SetVertexShaderInput_Attributes = { 0 }; // Read by GetXboxVertexAttributes when g_Xbox_SetVertexShaderInput_Count > 0
|
||||
|
||||
// Variables set by [D3DDevice|CxbxImpl]_SetVertexShader() and [D3DDevice|CxbxImpl]_SelectVertexShader() :
|
||||
bool g_Xbox_VertexShader_IsFixedFunction = true;
|
||||
bool g_Xbox_VertexShader_IsPassthrough = false;
|
||||
VertexShaderMode g_Xbox_VertexShaderMode = VertexShaderMode::FixedFunction;
|
||||
bool g_UseFixedFunctionVertexShader = true;
|
||||
|
||||
xbox::dword_xt g_Xbox_VertexShader_Handle = 0;
|
||||
#ifdef CXBX_USE_GLOBAL_VERTEXSHADER_POINTER // TODO : Would this be more accurate / simpler?
|
||||
xbox::X_D3DVertexShader *g_Xbox_VertexShader_Ptr = nullptr;
|
||||
|
@ -1092,7 +1092,9 @@ VertexDeclarationKey GetXboxVertexAttributesKey(xbox::X_VERTEXATTRIBUTEFORMAT* p
|
|||
auto attributeHash = ComputeHash((void*)pXboxVertexAttributeFormat, sizeof(xbox::X_VERTEXATTRIBUTEFORMAT));
|
||||
// For now, we use different declarations depending on if the fixed function pipeline
|
||||
// is in use, even if the attributes are the same
|
||||
return attributeHash ^ (VertexDeclarationKey)g_Xbox_VertexShader_IsFixedFunction;
|
||||
return g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction
|
||||
? attributeHash
|
||||
: attributeHash ^ 1;
|
||||
}
|
||||
|
||||
std::unordered_map<VertexDeclarationKey, CxbxVertexDeclaration*> g_CxbxVertexDeclarations;
|
||||
|
@ -1139,18 +1141,27 @@ void CxbxUpdateHostVertexShader()
|
|||
|
||||
LOG_INIT; // Allows use of DEBUG_D3DRESULT
|
||||
|
||||
if (g_Xbox_VertexShader_IsFixedFunction) {
|
||||
HRESULT hRet = g_pD3DDevice->SetVertexShader(nullptr);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetVertexShader");
|
||||
// TODO : Once available, start using host Fixed Function HLSL shader
|
||||
// instead of using deprecated host fixed function (by setting a null
|
||||
// vertex shader).
|
||||
// As for the required host vertex declaration :
|
||||
// CxbxUpdateHostVertexDeclaration already been
|
||||
// called, which sets host vertex declaration based on the
|
||||
// declaration that XboxVertexShaderFromFVF generated.
|
||||
if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction) {
|
||||
IDirect3DVertexShader* fixedFunctionShader = nullptr;
|
||||
HRESULT hRet;
|
||||
|
||||
if (g_UseFixedFunctionVertexShader) {
|
||||
static IDirect3DVertexShader* ffHlsl = nullptr;
|
||||
if (ffHlsl == nullptr) {
|
||||
ID3DBlob* pBlob = nullptr;
|
||||
EmuCompileFixedFunction(&pBlob);
|
||||
if (pBlob) {
|
||||
hRet = g_pD3DDevice->CreateVertexShader((DWORD*)pBlob->GetBufferPointer(), &ffHlsl);
|
||||
if (FAILED(hRet)) CxbxKrnlCleanup("Failed to create fixed-function shader");
|
||||
}
|
||||
}
|
||||
fixedFunctionShader = ffHlsl;
|
||||
}
|
||||
|
||||
hRet = g_pD3DDevice->SetVertexShader(fixedFunctionShader);
|
||||
if (FAILED(hRet)) CxbxKrnlCleanup("Failed to set fixed-function shader");
|
||||
}
|
||||
else if (g_Xbox_VertexShader_IsPassthrough && g_bUsePassthroughHLSL) {
|
||||
else if (g_Xbox_VertexShaderMode == VertexShaderMode::Passthrough && g_bUsePassthroughHLSL) {
|
||||
if (passthroughshader == nullptr) {
|
||||
ID3DBlob* pBlob = nullptr;
|
||||
EmuCompileXboxPassthrough(&pBlob);
|
||||
|
@ -1264,7 +1275,7 @@ CxbxVertexDeclaration* CxbxGetVertexDeclaration()
|
|||
// Convert Xbox vertex attributes towards host Direct3D 9 vertex element
|
||||
D3DVERTEXELEMENT* pRecompiledVertexElements = EmuRecompileVshDeclaration(
|
||||
pXboxVertexAttributeFormat,
|
||||
g_Xbox_VertexShader_IsFixedFunction,
|
||||
g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction,
|
||||
pCxbxVertexDeclaration);
|
||||
|
||||
// Create the vertex declaration
|
||||
|
@ -1354,6 +1365,8 @@ void CxbxImpl_SelectVertexShader(DWORD Handle, DWORD Address)
|
|||
// Either way, the given address slot is selected as the start of the current vertex shader program
|
||||
g_Xbox_VertexShader_FunctionSlots_StartAddress = Address;
|
||||
|
||||
g_Xbox_VertexShaderMode = VertexShaderMode::ShaderProgram;
|
||||
|
||||
if (Handle) {
|
||||
if (!VshHandleIsVertexShader(Handle))
|
||||
LOG_TEST_CASE("Non-zero handle must be a VertexShader!");
|
||||
|
@ -1362,8 +1375,6 @@ void CxbxImpl_SelectVertexShader(DWORD Handle, DWORD Address)
|
|||
g_Xbox_VertexShader_Ptr = VshHandleToXboxVertexShader(Handle);
|
||||
#endif
|
||||
g_Xbox_VertexShader_Handle = Handle;
|
||||
g_Xbox_VertexShader_IsFixedFunction = false;
|
||||
g_Xbox_VertexShader_IsPassthrough = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1450,7 +1461,6 @@ void CxbxImpl_SetVertexShader(DWORD Handle)
|
|||
HRESULT hRet = D3D_OK;
|
||||
|
||||
xbox::X_D3DVertexShader* pXboxVertexShader = CxbxGetXboxVertexShaderForHandle(Handle);
|
||||
g_Xbox_VertexShader_IsPassthrough = false;
|
||||
|
||||
if ((pXboxVertexShader->Flags & g_X_VERTEXSHADER_FLAG_VALID_MASK) != pXboxVertexShader->Flags) {
|
||||
LOG_TEST_CASE("Unknown vertex shader flag");
|
||||
|
@ -1470,8 +1480,8 @@ void CxbxImpl_SetVertexShader(DWORD Handle)
|
|||
LOG_TEST_CASE("g_Xbox_VertexShader_FunctionSlots_StartAddress != 0");
|
||||
bHackCallSelectAgain = true;
|
||||
}
|
||||
if (g_Xbox_VertexShader_IsFixedFunction != false) {
|
||||
LOG_TEST_CASE("g_Xbox_VertexShader_IsFixedFunction != false");
|
||||
if (g_Xbox_VertexShaderMode != VertexShaderMode::ShaderProgram) {
|
||||
LOG_TEST_CASE("Not in shader program mode after SetVertexShader trampoline");
|
||||
bHackCallSelectAgain = true;
|
||||
}
|
||||
|
||||
|
@ -1480,7 +1490,6 @@ void CxbxImpl_SetVertexShader(DWORD Handle)
|
|||
// _SelectVertexShader isn't applied;
|
||||
// 'solve' that by calling it here instead.
|
||||
CxbxImpl_SelectVertexShader(Handle, 0);
|
||||
g_Xbox_VertexShader_IsFixedFunction = false;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
@ -1511,12 +1520,11 @@ void CxbxImpl_SetVertexShader(DWORD Handle)
|
|||
// Switch to passthrough program, if so required
|
||||
if (pXboxVertexShader->Flags & X_VERTEXSHADER_FLAG_PASSTHROUGH) {
|
||||
CxbxSetVertexShaderPassthroughProgram();
|
||||
g_Xbox_VertexShader_IsFixedFunction = false;
|
||||
g_Xbox_VertexShader_IsPassthrough = true;
|
||||
g_Xbox_VertexShaderMode = VertexShaderMode::Passthrough;
|
||||
} else {
|
||||
// Test-case : Many XDK samples, Crazy taxi 3
|
||||
//LOG_TEST_CASE("Other or no vertex shader flags");
|
||||
g_Xbox_VertexShader_IsFixedFunction = true;
|
||||
g_Xbox_VertexShaderMode = VertexShaderMode::FixedFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,17 @@ typedef struct _CxbxVertexDeclaration
|
|||
}
|
||||
CxbxVertexDeclaration;
|
||||
|
||||
enum class VertexShaderMode {
|
||||
FixedFunction,
|
||||
// When titles use Xbox fixed function with pre-transformed vertices
|
||||
// it actually uses a special "passthrough" shader program
|
||||
Passthrough,
|
||||
ShaderProgram
|
||||
};
|
||||
|
||||
extern VertexShaderMode g_Xbox_VertexShaderMode;
|
||||
extern bool g_UseFixedFunctionVertexShader;
|
||||
|
||||
// Intermediate vertex shader structures
|
||||
|
||||
enum VSH_OREG_NAME {
|
||||
|
@ -217,4 +228,5 @@ extern void CxbxImpl_SetVertexShaderInput(DWORD Handle, UINT StreamCount, xbox::
|
|||
extern void CxbxImpl_SetVertexShaderConstant(INT Register, PVOID pConstantData, DWORD ConstantCount);
|
||||
extern void CxbxImpl_DeleteVertexShader(DWORD Handle);
|
||||
extern void CxbxVertexShaderSetFlags();
|
||||
extern HRESULT SetVertexShader(IDirect3DVertexShader* pShader);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue