diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index d116d9d5a..fb82c1a4b 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -2878,6 +2878,20 @@ 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) { + scaleX = 1; + scaleY = 1; + + // With fixed-function mode, titles don't have to account for these scale factors, + // so we don't have reverse them. + // Test cases: + // Fixed-func passthrough, title does not apply SSAA scale: + // - Shenmue II (Menu) + // Fixed-func passthrough, title does not apply backbuffer scale: + // - Antialias sample(background gradient) + if (g_Xbox_VertexShaderMode != VertexShaderMode::ShaderProgram) { + return; + } + // Example: // NFS HP2 renders in-game at 640*480 // The title uses MSAA, which increases the rendertarget size, but leaves the screen scale unaffected @@ -2894,35 +2908,25 @@ void GetScreenScaleFactors(float& scaleX, float& scaleY) { if (isMultiSampleEnabled && isSuperSampleMode) { GetMultiSampleScaleRaw(scaleX, scaleY); } - else { - scaleX = 1; - scaleY = 1; - } // Account for the backbuffer scale - // Fixed-function rendering doesn't have to account for backbuffer scale - // So XYZRHW passthrough vertex positions will not be pre-scaled by the title // Test cases: - // Fixed function passthrough (title does not apply backbuffer scale): - // - 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_VertexShaderMode != VertexShaderMode::Passthrough) { - scaleX *= g_Xbox_BackbufferScaleX; - scaleY *= g_Xbox_BackbufferScaleY; - } + scaleX *= g_Xbox_BackbufferScaleX; + scaleY *= g_Xbox_BackbufferScaleY; } // Get the raw subpixel dimensions of the rendertarget buffer -void GetRenderTargetRawDimensions(float& x, float&y) { - x = (float) GetPixelContainerWidth(g_pXbox_RenderTarget); - y = (float) GetPixelContainerHeight(g_pXbox_RenderTarget); +void GetRenderTargetRawDimensions(float& x, float&y, xbox::X_D3DSurface* rt) { + x = (float) GetPixelContainerWidth(rt); + y = (float) GetPixelContainerHeight(rt); } // Get the base rendertarget dimensions excluding multisample scaling // e.g. a raw 1280*960 rendertarget with 2x MSAA would be have a base 640*480 void GetRenderTargetBaseDimensions(float& x, float& y) { - GetRenderTargetRawDimensions(x, y); + GetRenderTargetRawDimensions(x, y, g_pXbox_RenderTarget); float aaX, aaY; GetMultiSampleScaleRaw(aaX, aaY); @@ -2931,6 +2935,19 @@ void GetRenderTargetBaseDimensions(float& x, float& y) { y /= aaY; } +// Get the pixel dimensions of the backbuffer, accounting for multisample mode +void GetBackBufferPixelDimensions(float& x, float& y) { + GetRenderTargetRawDimensions(x, y, g_pXbox_BackBufferSurface); + + // MSAA introduces subpixels, so scale them away + if (g_Xbox_MultiSampleType & xbox::X_D3DMULTISAMPLE_SAMPLING_MULTI) { + float aaX, aaY; + GetMultiSampleScaleRaw(aaX, aaY); + x /= aaX; + y /= aaY; + } +} + void Direct3D_CreateDevice_Start ( const xbox::X_D3DPRESENT_PARAMETERS *pPresentationParameters @@ -7381,9 +7398,20 @@ void CxbxUpdateHostTextureScaling() // Set scaling factor for this texture, which will be applied to // all texture-coordinates in CxbxVertexShaderTemplate.hlsl // Note : Linear textures are two-dimensional at most (right?) + float width, height; + if ((xbox::X_D3DSurface*)pXboxBaseTexture == g_pXbox_BackBufferSurface) { + // Account for MSAA + // Test case: Max Payne 2 (bullet time) + GetBackBufferPixelDimensions(width, height); + } + else { + width = (float)GetPixelContainerWidth(pXboxBaseTexture); + height = (float)GetPixelContainerHeight(pXboxBaseTexture); + } + *texCoordScale = { - (float)GetPixelContainerWidth(pXboxBaseTexture), - (float)GetPixelContainerHeight(pXboxBaseTexture), + width, + height, (float)CxbxGetPixelContainerDepth(pXboxBaseTexture), 1.0f };