Merge pull request #2040 from NZJenkins/z_fixes

Z fixes
This commit is contained in:
Luke Usher 2020-11-28 13:40:07 +00:00 committed by GitHub
commit 8c986c2480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 40 deletions

View File

@ -155,6 +155,8 @@ static std::queue<s_Xbox_Callback> g_Xbox_CallbackQueue;
static bool g_bHack_DisableHostGPUQueries = false; // TODO : Make configurable
static IDirect3DQuery *g_pHostQueryWaitForIdle = nullptr;
static IDirect3DQuery *g_pHostQueryCallbackEvent = nullptr;
static int g_RenderUpscaleFactor = 1;
static int g_RenderTargetUpscaleFactor = 1;
static std::condition_variable g_VBConditionVariable; // Used in BlockUntilVerticalBlank
static std::mutex g_VBConditionMutex; // Used in BlockUntilVerticalBlank
@ -2274,7 +2276,8 @@ static DWORD WINAPI EmuCreateDeviceProxy(LPVOID)
if (g_EmuCDPD.bCreate) {
// Apply render scale factor for high-resolution rendering
g_RenderScaleFactor = g_XBVideo.renderScaleFactor;
g_RenderUpscaleFactor = g_XBVideo.renderScaleFactor;
g_RenderTargetUpscaleFactor = 1;
// Setup the HostPresentationParameters
{
@ -3154,7 +3157,8 @@ void Direct3D_CreateDevice_End()
}
// We must also properly setup the host state
// Update only the Back buffer
// Update only the Back buffer, not the depth buffer
// This will also update g_RenderTargetUpscaleFactor and g_ZScale
CxbxImpl_SetRenderTarget(g_pXbox_BackBufferSurface, xbox::zeroptr);
}
@ -4112,15 +4116,13 @@ void ValidateRenderTargetDimensions(DWORD HostRenderTarget_Width, DWORD HostRend
// Because of this, we need to validate that the associated host resource still matches the dimensions of the Xbox Render Target
// If not, we must force them to be re-created
// TEST CASE: Chihiro Factory Test Program
DWORD XboxRenderTarget_Width_Scaled = XboxRenderTarget_Width * g_RenderScaleFactor;
DWORD XboxRenderTarget_Height_Scaled = XboxRenderTarget_Height * g_RenderScaleFactor;
DWORD XboxRenderTarget_Width_Scaled = XboxRenderTarget_Width * g_RenderTargetUpscaleFactor;
DWORD XboxRenderTarget_Height_Scaled = XboxRenderTarget_Height * g_RenderTargetUpscaleFactor;
if (HostRenderTarget_Width != XboxRenderTarget_Width_Scaled || HostRenderTarget_Height != XboxRenderTarget_Height_Scaled) {
LOG_TEST_CASE("Existing RenderTarget width/height changed");
if (g_pXbox_RenderTarget == g_pXbox_BackBufferSurface) {
FreeHostResource(GetHostResourceKey(g_pXbox_RenderTarget)); g_pD3DDevice->SetRenderTarget(0, GetHostSurface(g_pXbox_RenderTarget, D3DUSAGE_RENDERTARGET));
FreeHostResource(GetHostResourceKey(g_pXbox_DepthStencil)); g_pD3DDevice->SetDepthStencilSurface(GetHostSurface(g_pXbox_DepthStencil, D3DUSAGE_DEPTHSTENCIL));
}
FreeHostResource(GetHostResourceKey(g_pXbox_RenderTarget)); g_pD3DDevice->SetRenderTarget(0, GetHostSurface(g_pXbox_RenderTarget, D3DUSAGE_RENDERTARGET));
FreeHostResource(GetHostResourceKey(g_pXbox_DepthStencil)); g_pD3DDevice->SetDepthStencilSurface(GetHostSurface(g_pXbox_DepthStencil, D3DUSAGE_DEPTHSTENCIL));
}
}
@ -4180,11 +4182,11 @@ void GetXboxViewportOffsetAndScale(float (&vOffset)[4], float(&vScale)[4])
auto zRange = g_Xbox_Viewport.MaxZ - g_Xbox_Viewport.MinZ;
vScale[0] = scaledWidth / 2;
vScale[1] = -scaledHeight / 2;
vScale[2] = zRange > 0 ? g_ZScale / zRange : g_ZScale; // avoid divide by 0 when MinZ == MaxZ
vScale[2] = zRange * g_ZScale;
vScale[3] = 1;
vOffset[0] = scaledWidth / 2 + scaledX;
vOffset[1] = scaledHeight / 2 + scaledY;
vOffset[2] = -g_Xbox_Viewport.MinZ;
vOffset[2] = g_Xbox_Viewport.MinZ * g_ZScale;
vOffset[3] = 0;
}
@ -4195,11 +4197,6 @@ void CxbxUpdateHostViewPortOffsetAndScaleConstants()
float vScaleOffset[2][4]; // 0 - scale 1 - offset
GetXboxViewportOffsetAndScale(vScaleOffset[1], vScaleOffset[0]);
if (g_Xbox_VertexShader_IsPassthrough) {
// Passthrough should not scale Z
// Test case: DoA3 character select
vScaleOffset[0][2] = 1.0f;
}
// Xbox outputs vertex positions in rendertarget pixel coordinate space, with non-normalized Z
// e.g. 0 < x < 640 and 0 < y < 480
@ -4220,8 +4217,12 @@ void CxbxUpdateHostViewPortOffsetAndScaleConstants()
float xboxScreenspaceWidth = xboxRenderTargetWidth * screenScaleX;
float xboxScreenspaceHeight = xboxRenderTargetHeight * screenScaleY;
float screenspaceScale[4] = { xboxScreenspaceWidth / 2, -xboxScreenspaceHeight / 2, vScaleOffset[0][2], 1 };
float screenspaceOffset[4] = { xboxScreenspaceWidth / 2 + aaOffsetX, xboxScreenspaceHeight / 2 + aaOffsetY, vScaleOffset[1][2], 0 };
// 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 screenspaceScale[4] = { xboxScreenspaceWidth / 2, -xboxScreenspaceHeight / 2, zOutputScale, 1 };
float screenspaceOffset[4] = { xboxScreenspaceWidth / 2 + aaOffsetX, xboxScreenspaceHeight / 2 + aaOffsetY, 0, 0 };
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_SCREENSPACE_SCALE_BASE, screenspaceScale, CXBX_D3DVS_NORMALIZE_SCALE_SIZE);
g_pD3DDevice->SetVertexShaderConstantF(CXBX_D3DVS_SCREENSPACE_OFFSET_BASE, screenspaceOffset, CXBX_D3DVS_NORMALIZE_OFFSET_SIZE);
@ -4857,12 +4858,15 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_Clear)
// Scale the fill based on our scale factor and MSAA scale
float aaX, aaY;
GetMultiSampleScaleRaw(aaX, aaY);
aaX *= g_RenderTargetUpscaleFactor;
aaY *= g_RenderTargetUpscaleFactor;
std::vector<D3DRECT> rects(Count);
for (DWORD i = 0; i < Count; i++) {
rects[i].x1 = static_cast<LONG>(pRects[i].x1 * aaX * g_RenderScaleFactor);
rects[i].x2 = static_cast<LONG>(pRects[i].x2 * aaX * g_RenderScaleFactor);
rects[i].y1 = static_cast<LONG>(pRects[i].y1 * aaY * g_RenderScaleFactor);
rects[i].y2 = static_cast<LONG>(pRects[i].y2 * aaY * g_RenderScaleFactor);
rects[i].x1 = static_cast<LONG>(pRects[i].x1 * aaX);
rects[i].x2 = static_cast<LONG>(pRects[i].x2 * aaX);
rects[i].y1 = static_cast<LONG>(pRects[i].y1 * aaY);
rects[i].y2 = static_cast<LONG>(pRects[i].y2 * aaY);
}
hRet = g_pD3DDevice->Clear(Count, rects.data(), HostFlags, Color, Z, Stencil);
} else {
@ -5692,7 +5696,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
switch (XboxResourceType) {
case xbox::X_D3DRTYPE_SURFACE: {
if (D3DUsage & D3DUSAGE_DEPTHSTENCIL) {
hRet = g_pD3DDevice->CreateDepthStencilSurface(dwWidth * g_RenderScaleFactor, dwHeight * g_RenderScaleFactor, PCFormat,
hRet = g_pD3DDevice->CreateDepthStencilSurface(dwWidth * g_RenderUpscaleFactor, dwHeight * g_RenderUpscaleFactor, PCFormat,
g_EmuCDPD.HostPresentationParameters.MultiSampleType,
0, // MultisampleQuality
false, // Discard
@ -5703,7 +5707,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
}
else {
// Note : This handles both (D3DUsage & D3DUSAGE_RENDERTARGET) and otherwise alike
hRet = g_pD3DDevice->CreateTexture(dwWidth * g_RenderScaleFactor, dwHeight * g_RenderScaleFactor,
hRet = g_pD3DDevice->CreateTexture(dwWidth * g_RenderUpscaleFactor, dwHeight * g_RenderUpscaleFactor,
1, // Levels
D3DUSAGE_RENDERTARGET, // Usage always as render target
PCFormat,
@ -7131,13 +7135,16 @@ void CxbxUpdateHostViewport() {
LOG_TEST_CASE("Could not get rendertarget dimensions while setting the viewport");
}
aaScaleX *= g_RenderTargetUpscaleFactor;
aaScaleY *= g_RenderTargetUpscaleFactor;
if (g_Xbox_VertexShader_IsFixedFunction) {
// Set viewport
D3DVIEWPORT hostViewport = g_Xbox_Viewport;
hostViewport.X *= (aaScaleX * g_RenderScaleFactor);
hostViewport.Y *= (aaScaleY * g_RenderScaleFactor);
hostViewport.Width *= (aaScaleX * g_RenderScaleFactor);
hostViewport.Height *= (aaScaleY * g_RenderScaleFactor);
hostViewport.X *= aaScaleX;
hostViewport.Y *= aaScaleY;
hostViewport.Width *= aaScaleX;
hostViewport.Height *= aaScaleY;
g_pD3DDevice->SetViewport(&hostViewport);
// Reset scissor rect
@ -7169,10 +7176,10 @@ void CxbxUpdateHostViewport() {
// Scissor to viewport
g_pD3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
RECT viewportRect;
viewportRect.left = g_Xbox_Viewport.X * aaScaleX * g_RenderScaleFactor;
viewportRect.top = g_Xbox_Viewport.Y * aaScaleY * g_RenderScaleFactor;
viewportRect.right = viewportRect.left + g_Xbox_Viewport.Width * aaScaleX * g_RenderScaleFactor;
viewportRect.bottom = viewportRect.top + g_Xbox_Viewport.Height * aaScaleY * g_RenderScaleFactor;
viewportRect.left = g_Xbox_Viewport.X * aaScaleX;
viewportRect.top = g_Xbox_Viewport.Y * aaScaleY;
viewportRect.right = viewportRect.left + g_Xbox_Viewport.Width * aaScaleX;
viewportRect.bottom = viewportRect.top + g_Xbox_Viewport.Height * aaScaleY;
g_pD3DDevice->SetScissorRect(&viewportRect);
}
}
@ -7865,6 +7872,10 @@ static void CxbxImpl_SetRenderTarget
}
}
// Get the host upscale factor for the current rendertarget
// Currently, only the host backbuffer is upscaled
g_RenderTargetUpscaleFactor = (g_pXbox_RenderTarget == g_pXbox_BackBufferSurface) ? g_RenderUpscaleFactor : 1;
// Set default viewport now we've updated the rendertarget
// Note the Xbox does this, but before _our_ SetRenderTarget sets up the render target
// Test case: Dashboard

View File

@ -58,10 +58,6 @@ 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)
extern xbox::X_D3DSurface* g_pXbox_RenderTarget;
extern xbox::X_D3DSurface* g_pXbox_BackBufferSurface;
extern xbox::X_D3DMULTISAMPLE_TYPE g_Xbox_MultiSampleType;
extern float *HLE_get_NV2A_vertex_attribute_value_pointer(unsigned VertexSlot); // Declared in PushBuffer.cpp
void *GetDataFromXboxResource(xbox::X_D3DResource *pXboxResource);

View File

@ -1193,9 +1193,6 @@ static void CxbxSetVertexShaderPassthroughProgram()
CxbxSetVertexShaderSlots(&XboxShaderBinaryPassthrough[0], 0, sizeof(XboxShaderBinaryPassthrough) / X_VSH_INSTRUCTION_SIZE_BYTES);
extern float g_ZScale; // TMP glue
extern float GetMultiSampleOffsetDelta(); // TMP glue
// Passthrough programs require scale and offset to be set in constants zero and one (both minus 96)
// (Note, these are different from GetMultiSampleOffsetAndScale / GetViewPortOffsetAndScale)
float scale[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
@ -1208,6 +1205,8 @@ static void CxbxSetVertexShaderPassthroughProgram()
float MultiSampleBias = 0.0f;
if (XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_MULTISAMPLEANTIALIAS) > 0) {
extern float GetMultiSampleOffsetDelta(); // TMP glue
MultiSampleBias = GetMultiSampleOffsetDelta();
}

View File

@ -51,7 +51,6 @@ volatile bool g_bPrintfOn = true;
bool g_DisablePixelShaders = false;
bool g_UseAllCores = false;
bool g_SkipRdtscPatching = false;
int g_RenderScaleFactor = 1;
// Delta added to host SystemTime, used in KiClockIsr and KeSetSystemTime
// This shouldn't need to be atomic, but because raising the IRQL to high lv in KeSetSystemTime doesn't really stop KiClockIsr from running,

View File

@ -95,5 +95,4 @@ typedef WORD INDEX16;
extern bool g_DisablePixelShaders;
extern bool g_UseAllCores;
extern bool g_SkipRdtscPatching;
extern int g_RenderScaleFactor;
#endif