Upscale rendertargets and depth surfaces consistently

Rather than just upscaling the backbuffer
Allows high resolution rendering in some games that rendered to textures
Fixes Amped shadows when upscaling, due to SetRenderTarget failure (probably mixing scaled and unscaled RT & Depth)
This commit is contained in:
Anthony 2021-03-20 12:03:19 +13:00
parent d9b994c357
commit 4938b13bc5
1 changed files with 34 additions and 33 deletions

View File

@ -145,7 +145,6 @@ static bool g_bHack_DisableHostGPUQueries = false; // TO
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
@ -2357,7 +2356,6 @@ static void CreateDefaultD3D9Device
// Apply render scale factor for high-resolution rendering
g_RenderUpscaleFactor = g_XBVideo.renderScaleFactor;
g_RenderTargetUpscaleFactor = 1;
// Setup the HostPresentationParameters
SetupPresentationParameters(pPresentationParameters);
@ -3008,9 +3006,7 @@ void Direct3D_CreateDevice_End
CxbxKrnlCleanup("Unable to determine default Xbox backbuffer");
}
// We must also properly setup the host state
// Update only the Back buffer, not the depth buffer
// This will also update g_RenderTargetUpscaleFactor and g_ZScale
// Set the backbuffer as the initial rendertarget
CxbxImpl_SetRenderTarget(g_pXbox_BackBufferSurface, xbox::zeroptr);
}
@ -4097,8 +4093,8 @@ 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_RenderTargetUpscaleFactor;
DWORD XboxRenderTarget_Height_Scaled = XboxRenderTarget_Height * g_RenderTargetUpscaleFactor;
DWORD XboxRenderTarget_Width_Scaled = XboxRenderTarget_Width * g_RenderUpscaleFactor;
DWORD XboxRenderTarget_Height_Scaled = XboxRenderTarget_Height * g_RenderUpscaleFactor;
if (HostRenderTarget_Width != XboxRenderTarget_Width_Scaled || HostRenderTarget_Height != XboxRenderTarget_Height_Scaled) {
LOG_TEST_CASE("Existing RenderTarget width/height changed");
@ -4935,8 +4931,8 @@ 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;
aaX *= g_RenderUpscaleFactor;
aaY *= g_RenderUpscaleFactor;
std::vector<D3DRECT> rects(Count);
for (DWORD i = 0; i < Count; i++) {
@ -5710,10 +5706,19 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
bool bCompressed = EmuXBFormatIsCompressed(X_Format);
UINT dwBPP = EmuXBFormatBytesPerPixel(X_Format);
UINT dwMipMapLevels = CxbxGetPixelContainerMipMapLevels(pPixelContainer);
UINT dwWidth, dwHeight, dwDepth, dwRowPitch, dwSlicePitch;
UINT xboxWidth, xboxHeight, dwDepth, dwRowPitch, dwSlicePitch;
// Interpret Width/Height/BPP
CxbxGetPixelContainerMeasures(pPixelContainer, 0, &dwWidth, &dwHeight, &dwDepth, &dwRowPitch, &dwSlicePitch);
CxbxGetPixelContainerMeasures(pPixelContainer, 0, &xboxWidth, &xboxHeight, &dwDepth, &dwRowPitch, &dwSlicePitch);
// Host width and height dimensions
UINT hostWidth = xboxWidth;
UINT hostHeight = xboxHeight;
// Upscale rendertargets and depth surfaces
if (D3DUsage & (X_D3DUSAGE_DEPTHSTENCIL | X_D3DUSAGE_RENDERTARGET)) {
hostWidth *= g_RenderUpscaleFactor;
hostHeight *= g_RenderUpscaleFactor;
}
// Each mip-map level is 1/2 the size of the previous level
// D3D9 forbids creation of a texture with more mip-map levels than it is divisible
@ -5722,7 +5727,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
if (dwMipMapLevels > 0) {
// Calculate how many mip-map levels it takes to get to a texture of 1 pixels in either dimension
UINT highestMipMapLevel = 1;
UINT width = dwWidth; UINT height = dwHeight;
UINT width = xboxWidth; UINT height = xboxHeight;
while (width > 1 || height > 1) {
width /= 2;
height /= 2;
@ -5758,7 +5763,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_RenderUpscaleFactor, dwHeight * g_RenderUpscaleFactor, PCFormat,
hRet = g_pD3DDevice->CreateDepthStencilSurface(hostWidth, hostHeight, PCFormat,
g_EmuCDPD.HostPresentationParameters.MultiSampleType,
0, // MultisampleQuality
false, // Discard
@ -5769,7 +5774,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_RenderUpscaleFactor, dwHeight * g_RenderUpscaleFactor,
hRet = g_pD3DDevice->CreateTexture(hostWidth, hostHeight,
1, // Levels
D3DUSAGE_RENDERTARGET, // Usage always as render target
PCFormat,
@ -5800,7 +5805,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
}
EmuLog(LOG_LEVEL::WARNING, "Trying Fallback");
hRet = g_pD3DDevice->CreateOffscreenPlainSurface(dwWidth, dwHeight, PCFormat, D3DPool, &pNewHostSurface, nullptr);
hRet = g_pD3DDevice->CreateOffscreenPlainSurface(hostWidth, hostHeight, PCFormat, D3DPool, &pNewHostSurface, nullptr);
}
// If the fallback failed, show an error and exit execution.
@ -5814,7 +5819,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
ResourceTypeName, pResource, pNewHostSurface);
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Width : %d, Height : %d, Format : %d",
dwWidth, dwHeight, PCFormat);
hostWidth, hostHeight, PCFormat);
break;
}
@ -5832,7 +5837,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
}
case xbox::X_D3DRTYPE_TEXTURE: {
hRet = g_pD3DDevice->CreateTexture(dwWidth, dwHeight, dwMipMapLevels,
hRet = g_pD3DDevice->CreateTexture(hostWidth, hostHeight, dwMipMapLevels,
D3DUsage, PCFormat, D3DPool, &pNewHostTexture,
nullptr
);
@ -5840,7 +5845,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
// If the above failed, we might be able to use an ARGB texture instead
if ((hRet != D3D_OK) && (PCFormat != D3DFMT_A8R8G8B8) && EmuXBFormatCanBeConvertedToARGB(X_Format)) {
hRet = g_pD3DDevice->CreateTexture(dwWidth, dwHeight, dwMipMapLevels,
hRet = g_pD3DDevice->CreateTexture(hostWidth, hostHeight, dwMipMapLevels,
D3DUsage, D3DFMT_A8R8G8B8, D3DPool, &pNewHostTexture,
nullptr
);
@ -5855,7 +5860,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
// Now create our intermediate texture for UpdateTexture, but not for render targets or depth stencils
if (hRet == D3D_OK && (D3DUsage & D3DUSAGE_RENDERTARGET) == 0 && (D3DUsage & D3DUSAGE_DEPTHSTENCIL) == 0) {
hRet = g_pD3DDevice->CreateTexture(dwWidth, dwHeight, dwMipMapLevels,
hRet = g_pD3DDevice->CreateTexture(hostWidth, hostHeight, dwMipMapLevels,
0, PCFormat, D3DPOOL_SYSTEMMEM, &pIntermediateHostTexture,
nullptr
);
@ -5875,7 +5880,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
if (hRet != D3D_OK) {
CxbxKrnlCleanup("CreateTexture Failed!\n\n"
"Error: 0x%X\nFormat: %d\nDimensions: %dx%d", hRet, PCFormat, dwWidth, dwHeight);
"Error: 0x%X\nFormat: %d\nDimensions: %dx%d", hRet, PCFormat, hostWidth, hostHeight);
}
SetHostTexture(pResource, pNewHostTexture, iTextureStage);
@ -5885,7 +5890,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
}
case xbox::X_D3DRTYPE_VOLUMETEXTURE: {
hRet = g_pD3DDevice->CreateVolumeTexture(dwWidth, dwHeight, dwDepth,
hRet = g_pD3DDevice->CreateVolumeTexture(hostWidth, hostHeight, dwDepth,
dwMipMapLevels, D3DUsage, PCFormat, D3DPool, &pNewHostVolumeTexture,
nullptr
);
@ -5893,7 +5898,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
// Now create our intermediate texture for UpdateTexture, but not for render targets or depth stencils
if (hRet == D3D_OK && (D3DUsage & D3DUSAGE_RENDERTARGET) == 0 && (D3DUsage & D3DUSAGE_DEPTHSTENCIL) == 0) {
hRet = g_pD3DDevice->CreateVolumeTexture(dwWidth, dwHeight, dwDepth,
hRet = g_pD3DDevice->CreateVolumeTexture(hostWidth, hostHeight, dwDepth,
dwMipMapLevels, 0, PCFormat, D3DPOOL_SYSTEMMEM, &pIntermediateHostVolumeTexture,
nullptr
);
@ -5911,10 +5916,10 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
}
case xbox::X_D3DRTYPE_CUBETEXTURE: {
EmuLog(LOG_LEVEL::DEBUG, "CreateCubeTexture(%d, %d, 0, %d, D3DPOOL_DEFAULT)", dwWidth,
EmuLog(LOG_LEVEL::DEBUG, "CreateCubeTexture(%d, %d, 0, %d, D3DPOOL_DEFAULT)", hostWidth,
dwMipMapLevels, PCFormat);
hRet = g_pD3DDevice->CreateCubeTexture(dwWidth, dwMipMapLevels, D3DUsage,
hRet = g_pD3DDevice->CreateCubeTexture(hostWidth, dwMipMapLevels, D3DUsage,
PCFormat, D3DPool, &pNewHostCubeTexture,
nullptr
);
@ -5922,7 +5927,7 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
// Now create our intermediate texture for UpdateTexture, but not for render targets or depth stencils
if (hRet == D3D_OK && (D3DUsage & D3DUSAGE_RENDERTARGET) == 0 && (D3DUsage & D3DUSAGE_DEPTHSTENCIL) == 0) {
hRet = g_pD3DDevice->CreateCubeTexture(dwWidth, dwMipMapLevels, 0,
hRet = g_pD3DDevice->CreateCubeTexture(hostWidth, dwMipMapLevels, 0,
PCFormat, D3DPOOL_SYSTEMMEM, &pIntermediateHostCubeTexture,
nullptr
);
@ -5968,8 +5973,8 @@ void CreateHostResource(xbox::X_D3DResource *pResource, DWORD D3DUsage, int iTex
for (int face = D3DCUBEMAP_FACE_POSITIVE_X; face <= last_face; face++) {
// As we iterate through mipmap levels, we'll adjust the source resource offset
DWORD dwMipOffset = 0;
DWORD pxMipWidth = dwWidth;
DWORD pxMipHeight = dwHeight;
DWORD pxMipWidth = xboxWidth;
DWORD pxMipHeight = xboxHeight;
DWORD pxMipDepth = dwDepth;
DWORD dwMipRowPitch = dwRowPitch;
DWORD dwSrcSlicePitch = dwMipRowPitch * pxMipHeight; // TODO
@ -7465,8 +7470,8 @@ void CxbxUpdateHostViewport() {
LOG_TEST_CASE("Could not get rendertarget dimensions while setting the viewport");
}
aaScaleX *= g_RenderTargetUpscaleFactor;
aaScaleY *= g_RenderTargetUpscaleFactor;
aaScaleX *= g_RenderUpscaleFactor;
aaScaleY *= g_RenderUpscaleFactor;
if (g_Xbox_VertexShaderMode == VertexShaderMode::FixedFunction) {
// Set viewport
@ -8223,10 +8228,6 @@ 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