diff options
| author | iwubcode <iwubcode@users.noreply.github.com> | 2017-05-29 17:02:09 -0500 |
|---|---|---|
| committer | iwubcode <iwubcode@users.noreply.github.com> | 2017-11-17 19:47:56 -0600 |
| commit | 79387dddb24ddf035b70cd9379a42368dcd49e93 (patch) | |
| tree | 7b783c46e1ffd052842f11112f58c61993f0af1b /Source/Core/VideoBackends | |
| parent | 84ca9a4aec0048e5ac01caea8f8be9210eb947f6 (diff) | |
Add support for hybrid XFB
Diffstat (limited to 'Source/Core/VideoBackends')
32 files changed, 137 insertions, 755 deletions
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index e766387de8..ff63898039 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -52,7 +52,6 @@ <ClCompile Include="PixelShaderCache.cpp" /> <ClCompile Include="PSTextureEncoder.cpp" /> <ClCompile Include="Render.cpp" /> - <ClCompile Include="Television.cpp" /> <ClCompile Include="TextureCache.cpp" /> <ClCompile Include="VertexManager.cpp" /> <ClCompile Include="VertexShaderCache.cpp" /> @@ -73,7 +72,6 @@ <ClInclude Include="PixelShaderCache.h" /> <ClInclude Include="PSTextureEncoder.h" /> <ClInclude Include="Render.h" /> - <ClInclude Include="Television.h" /> <ClInclude Include="TextureCache.h" /> <ClInclude Include="VertexManager.h" /> <ClInclude Include="VertexShaderCache.h" /> diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters index cc05377bda..e3138ff28f 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters @@ -48,9 +48,6 @@ <ClCompile Include="Render.cpp"> <Filter>Render</Filter> </ClCompile> - <ClCompile Include="Television.cpp"> - <Filter>Render</Filter> - </ClCompile> <ClCompile Include="TextureCache.cpp"> <Filter>Render</Filter> </ClCompile> @@ -108,9 +105,6 @@ <ClInclude Include="Render.h"> <Filter>Render</Filter> </ClInclude> - <ClInclude Include="Television.h"> - <Filter>Render</Filter> - </ClInclude> <ClInclude Include="TextureCache.h"> <Filter>Render</Filter> </ClInclude> diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index 5853b8e849..3ecd3119f8 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -330,12 +330,6 @@ std::pair<u32, u32> FramebufferManager::GetTargetSize() const return std::make_pair(m_target_width, m_target_height); } -void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) -{ - // DX11's XFB decoder does not use this function. - // YUYV data is decoded in Render::Swap. -} - void XFBSource::CopyEFB(float Gamma) { g_renderer->ResetAPIState(); // reset any game specific settings diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h index f38a60edc0..96e76118ee 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.h +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h @@ -50,7 +50,6 @@ struct XFBSource : public XFBSourceBase { XFBSource(D3DTexture2D* _tex, int slices) : tex(_tex), m_slices(slices) {} ~XFBSource() { tex->Release(); } - void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override; void CopyEFB(float Gamma) override; D3DTexture2D* const tex; diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 9b24783f6a..7c05215948 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -41,8 +41,11 @@ void PSTextureEncoder::Init() HRESULT hr; // Create output texture RGBA format + // TODO: This Texture is overly large and parts of it are unused + // EFB2RAM copies use max (EFB_WIDTH * 4) by (EFB_HEIGHT / 4) + // XFB2RAM copies use max (EFB_WIDTH / 2) by (EFB_HEIGHT) D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, EFB_WIDTH * 4, - EFB_HEIGHT / 4, 1, 1, D3D11_BIND_RENDER_TARGET); + EFB_HEIGHT, 1, 1, D3D11_BIND_RENDER_TARGET); hr = D3D::device->CreateTexture2D(&t2dd, nullptr, &m_out); CHECK(SUCCEEDED(hr), "create efb encode output texture"); D3D::SetDebugObjectName(m_out, "efb encoder output texture"); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 5fce3ab961..55d9267b46 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -24,10 +24,10 @@ #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" +#include "VideoBackends/D3D/DXTexture.h" #include "VideoBackends/D3D/FramebufferManager.h" #include "VideoBackends/D3D/GeometryShaderCache.h" #include "VideoBackends/D3D/PixelShaderCache.h" -#include "VideoBackends/D3D/Television.h" #include "VideoBackends/D3D/TextureCache.h" #include "VideoBackends/D3D/VertexShaderCache.h" @@ -40,6 +40,7 @@ #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" +#include "VideoCommon/VideoCommon.h" #include "VideoCommon/XFMemory.h" namespace DX11 @@ -66,11 +67,8 @@ struct GXPipelineState static u32 s_last_multisamples = 1; static bool s_last_stereo_mode = false; -static bool s_last_xfb_mode = false; static bool s_last_fullscreen_mode = false; -static Television s_television; - static std::array<ID3D11BlendState*, 4> s_clear_blend_states{}; static std::array<ID3D11DepthStencilState*, 3> s_clear_depth_states{}; static ID3D11BlendState* s_reset_blend_state = nullptr; @@ -85,8 +83,6 @@ static StateCache s_gx_state_cache; static void SetupDeviceObjects() { - s_television.Init(); - HRESULT hr; D3D11_DEPTH_STENCIL_DESC ddesc; @@ -182,8 +178,6 @@ static void TeardownDeviceObjects() SAFE_RELEASE(s_screenshot_texture); SAFE_RELEASE(s_3d_vision_texture); - s_television.Shutdown(); - s_gx_state_cache.Clear(); } @@ -241,7 +235,6 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH { s_last_multisamples = g_ActiveConfig.iMultisamples; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; - s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; s_last_fullscreen_mode = D3D::GetFullscreenState(); g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height); @@ -640,22 +633,11 @@ void Renderer::SetBlendingState(const BlendingState& state) } // This function has the final picture. We adjust the aspect ratio here. -void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, - const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) { - if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) + if (!m_xfb_written) { Core::Callback_VideoCopiedToXFB(false); - return; - } - - u32 xfbCount = 0; - const XFBSourceBase* const* xfbSourceList = - FramebufferManager::GetXFBSource(xfbAddr, fbStride, fbHeight, &xfbCount); - if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) - { - Core::Callback_VideoCopiedToXFB(false); - return; } ResetAPIState(); @@ -671,67 +653,11 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, // activate linear filtering for the buffer copies D3D::SetLinearCopySampler(); + auto* xfb_texture = static_cast<DXTexture*>(texture); + TargetRectangle source_rc = xfb_texture->config.Rect(); - if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB) - { - // TODO: Television should be used to render Virtual XFB mode as well. - D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)targetRc.left, (float)targetRc.top, - (float)targetRc.GetWidth(), (float)targetRc.GetHeight()); - D3D::context->RSSetViewports(1, &vp); - - s_television.Submit(xfbAddr, fbStride, fbWidth, fbHeight); - s_television.Render(); - } - else if (g_ActiveConfig.bUseXFB) - { - // draw each xfb source - for (u32 i = 0; i < xfbCount; ++i) - { - const auto* const xfbSource = static_cast<const XFBSource*>(xfbSourceList[i]); - - // use virtual xfb with offset - int xfbHeight = xfbSource->srcHeight; - int xfbWidth = xfbSource->srcWidth; - int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbStride * 2); - - TargetRectangle drawRc; - drawRc.top = targetRc.top + hOffset * targetRc.GetHeight() / (s32)fbHeight; - drawRc.bottom = targetRc.top + (hOffset + xfbHeight) * targetRc.GetHeight() / (s32)fbHeight; - drawRc.left = targetRc.left + - (targetRc.GetWidth() - xfbWidth * targetRc.GetWidth() / (s32)fbStride) / 2; - drawRc.right = targetRc.left + - (targetRc.GetWidth() + xfbWidth * targetRc.GetWidth() / (s32)fbStride) / 2; - - // The following code disables auto stretch. Kept for reference. - // scale draw area for a 1 to 1 pixel mapping with the draw target - // float vScale = (float)fbHeight / (float)s_backbuffer_height; - // float hScale = (float)fbWidth / (float)s_backbuffer_width; - // drawRc.top *= vScale; - // drawRc.bottom *= vScale; - // drawRc.left *= hScale; - // drawRc.right *= hScale; - - TargetRectangle sourceRc; - sourceRc.left = xfbSource->sourceRc.left; - sourceRc.top = xfbSource->sourceRc.top; - sourceRc.right = xfbSource->sourceRc.right; - sourceRc.bottom = xfbSource->sourceRc.bottom; - - sourceRc.right -= Renderer::EFBToScaledX(fbStride - fbWidth); - - BlitScreen(sourceRc, drawRc, xfbSource->tex, xfbSource->texWidth, xfbSource->texHeight, - Gamma); - } - } - else - { - TargetRectangle sourceRc = Renderer::ConvertEFBRectangle(rc); - - // TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB - // texture as source - D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture(); - BlitScreen(sourceRc, targetRc, read_texture, GetTargetWidth(), GetTargetHeight(), Gamma); - } + BlitScreen(source_rc, targetRc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, + xfb_texture->config.height, Gamma); // Dump frames if (IsFrameDumping()) @@ -773,33 +699,20 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, g_texture_cache->OnConfigChanged(g_ActiveConfig); VertexShaderCache::RetreiveAsyncShaders(); - SetWindowSize(fbStride, fbHeight); + SetWindowSize(xfb_texture->config.width, xfb_texture->config.height); const bool window_resized = CheckForResize(); const bool fullscreen = D3D::GetFullscreenState(); const bool fs_changed = s_last_fullscreen_mode != fullscreen; - bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB; - - if (FramebufferManagerBase::LastXfbWidth() != fbStride || - FramebufferManagerBase::LastXfbHeight() != fbHeight) - { - xfbchanged = true; - unsigned int xfb_w = (fbStride < 1 || fbStride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbStride; - unsigned int xfb_h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight; - FramebufferManagerBase::SetLastXfbWidth(xfb_w); - FramebufferManagerBase::SetLastXfbHeight(xfb_h); - } - // Flip/present backbuffer to frontbuffer here D3D::Present(); // Resize the back buffers NOW to avoid flickering - if (CalculateTargetSize() || xfbchanged || window_resized || fs_changed || + if (CalculateTargetSize() || window_resized || fs_changed || s_last_multisamples != g_ActiveConfig.iMultisamples || s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0)) { - s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; s_last_multisamples = g_ActiveConfig.iMultisamples; s_last_fullscreen_mode = fullscreen; PixelShaderCache::InvalidateMSAAShaders(); diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index a33eba7cd2..b35e0f9d20 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -46,8 +46,7 @@ public: TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override; - void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, - u64 ticks, float Gamma) override; + void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override; void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) override; diff --git a/Source/Core/VideoBackends/D3D/Television.cpp b/Source/Core/VideoBackends/D3D/Television.cpp deleted file mode 100644 index 79f556cd09..0000000000 --- a/Source/Core/VideoBackends/D3D/Television.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2011 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "VideoBackends/D3D/Television.h" - -#include <vector> - -#include "Core/HW/Memmap.h" -#include "VideoBackends/D3D/D3DBase.h" -#include "VideoBackends/D3D/D3DShader.h" -#include "VideoBackends/D3D/D3DState.h" -#include "VideoBackends/D3D/D3DUtil.h" -#include "VideoBackends/D3D/VertexShaderCache.h" -#include "VideoCommon/VideoCommon.h" -#include "VideoCommon/VideoConfig.h" - -namespace DX11 -{ -static const char YUYV_DECODER_PS[] = - "// dolphin-emu YUYV decoder pixel shader\n" - - "Texture2D Tex0 : register(t0);\n" - "sampler Samp0 : register(s0);\n" - - "static const float3x3 YCBCR_TO_RGB = float3x3(\n" - "1.164, 0.000, 1.596,\n" - "1.164, -0.392, -0.813,\n" - "1.164, 2.017, 0.000\n" - ");\n" - - "void main(out float4 ocol0 : SV_Target, in float4 pos : SV_Position, in float2 uv0 : " - "TEXCOORD0)\n" - "{\n" - "float3 sample = Tex0.Sample(Samp0, uv0).rgb;\n" - - // GameCube/Wii XFB data is in YUYV format with ITU-R Rec. BT.601 color - // primaries, compressed to the range Y in 16..235, U and V in 16..240. - // We want to convert it to RGB format with sRGB color primaries, with - // range 0..255. - - // Recover RGB components - "float3 yuv_601_sub = sample.grb - float3(16.0/255.0, 128.0/255.0, 128.0/255.0);\n" - "float3 rgb_601 = mul(YCBCR_TO_RGB, yuv_601_sub);\n" - - // If we were really obsessed with accuracy, we would correct for the - // differing color primaries between BT.601 and sRGB. However, this may not - // be worth the trouble because: - // - BT.601 defines two sets of primaries: one for NTSC and one for PAL. - // - sRGB's color primaries are actually an intermediate between BT.601's - // NTSC and PAL primaries. - // - If users even noticed any difference at all, they would be confused by - // the slightly-different colors in the NTSC and PAL versions of the same - // game. - // - Even the game designers probably don't pay close attention to this - // stuff. - // Still, instructions on how to do it can be found at - // <http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC20> - - "ocol0 = float4(rgb_601, 1);\n" - "}\n"; - -Television::Television() : m_yuyvTexture(nullptr), m_yuyvTextureSRV(nullptr), m_pShader(nullptr) -{ -} - -void Television::Init() -{ - HRESULT hr; - - // Create YUYV texture for real XFB mode - - // Initialize the texture with YCbCr black - // - // Some games use narrower XFB widths (Nintendo titles are fond of 608), - // so the sampler's BorderColor won't cover the right side - // (see sampler state below) - const unsigned int MAX_XFB_SIZE = 2 * (MAX_XFB_WIDTH)*MAX_XFB_HEIGHT; - std::vector<u8> fill(MAX_XFB_SIZE); - for (size_t i = 0; i < MAX_XFB_SIZE / sizeof(u32); ++i) - reinterpret_cast<u32*>(fill.data())[i] = 0x80108010; - D3D11_SUBRESOURCE_DATA srd = {fill.data(), 2 * (MAX_XFB_WIDTH), 0}; - - // This texture format is designed for YUYV data. - D3D11_TEXTURE2D_DESC t2dd = - CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_G8R8_G8B8_UNORM, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 1, 1); - hr = D3D::device->CreateTexture2D(&t2dd, &srd, &m_yuyvTexture); - CHECK(SUCCEEDED(hr), "create tv yuyv texture"); - D3D::SetDebugObjectName(m_yuyvTexture, "tv yuyv texture"); - - // Create shader resource view for YUYV texture - - D3D11_SHADER_RESOURCE_VIEW_DESC srvd = CD3D11_SHADER_RESOURCE_VIEW_DESC( - m_yuyvTexture, D3D11_SRV_DIMENSION_TEXTURE2D, DXGI_FORMAT_G8R8_G8B8_UNORM); - hr = D3D::device->CreateShaderResourceView(m_yuyvTexture, &srvd, &m_yuyvTextureSRV); - CHECK(SUCCEEDED(hr), "create tv yuyv texture srv"); - D3D::SetDebugObjectName(m_yuyvTextureSRV, "tv yuyv texture srv"); - - // Create YUYV-decoding pixel shader - - m_pShader = D3D::CompileAndCreatePixelShader(YUYV_DECODER_PS); - CHECK(m_pShader != nullptr, "compile and create yuyv decoder pixel shader"); - D3D::SetDebugObjectName(m_pShader, "yuyv decoder pixel shader"); - - // Create sampler state and set border color - // - // The default sampler border color of { 0.f, 0.f, 0.f, 0.f } - // creates a green border around the image - see issue 6483 - // (remember, the XFB is being interpreted as YUYV, and 0,0,0,0 - // is actually two green pixels in YUYV - black should be 16,128,16,128, - // but we reverse the order to match DXGI_FORMAT_G8R8_G8B8_UNORM's ordering) - float border[4] = {128.0f / 255.0f, 16.0f / 255.0f, 128.0f / 255.0f, 16.0f / 255.0f}; - D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC( - D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, - D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f); - hr = D3D::device->CreateSamplerState(&samDesc, &m_samplerState); - CHECK(SUCCEEDED(hr), "create yuyv decoder sampler state"); - D3D::SetDebugObjectName(m_samplerState, "yuyv decoder sampler state"); -} - -void Television::Shutdown() -{ - SAFE_RELEASE(m_pShader); - SAFE_RELEASE(m_yuyvTextureSRV); - SAFE_RELEASE(m_yuyvTexture); - SAFE_RELEASE(m_samplerState); -} - -void Television::Submit(u32 xfbAddr, u32 stride, u32 width, u32 height) -{ - m_curAddr = xfbAddr; - m_curWidth = width; - m_curHeight = height; - - // Load data from GameCube RAM to YUYV texture - u8* yuyvSrc = Memory::GetPointer(xfbAddr); - D3D11_BOX box = CD3D11_BOX(0, 0, 0, stride, height, 1); - D3D::context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2 * stride, 2 * stride * height); -} - -void Television::Render() -{ - if (g_ActiveConfig.bUseRealXFB && g_ActiveConfig.bUseXFB) - { - // Use real XFB mode - // TODO: If this is the lower field, render at a vertical offset of 1 - // line down. We could even consider implementing a deinterlacing - // algorithm. - - D3D11_RECT sourceRc = CD3D11_RECT(0, 0, int(m_curWidth), int(m_curHeight)); - - D3D::stateman->SetSampler(0, m_samplerState); - - D3D::drawShadedTexQuad(m_yuyvTextureSRV, &sourceRc, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, m_pShader, - VertexShaderCache::GetSimpleVertexShader(), - VertexShaderCache::GetSimpleInputLayout()); - } - else if (g_ActiveConfig.bUseXFB) - { - // Use virtual XFB mode - - // TODO: Eventually, Television should render the Virtual XFB mode - // display as well. - } -} -} diff --git a/Source/Core/VideoBackends/D3D/Television.h b/Source/Core/VideoBackends/D3D/Television.h deleted file mode 100644 index 2ad29cdf10..0000000000 --- a/Source/Core/VideoBackends/D3D/Television.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2011 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include "Common/CommonTypes.h" - -struct ID3D11Texture2D; -struct ID3D11ShaderResourceView; -struct ID3D11PixelShader; -struct ID3D11SamplerState; - -namespace DX11 -{ -class Television -{ -public: - Television(); - - void Init(); - void Shutdown(); - - // Submit video data to be drawn. This will change the current state of the - // TV. xfbAddr points to YUYV data stored in GameCube/Wii RAM, but the XFB - // may be virtualized when rendering so the RAM may not actually be read. - void Submit(u32 xfbAddr, u32 stride, u32 width, u32 height); - - // Render the current state of the TV. - void Render(); - -private: - // Properties of last Submit call - u32 m_curAddr; - u32 m_curWidth; - u32 m_curHeight; - - // Used for real XFB mode - - ID3D11Texture2D* m_yuyvTexture; - ID3D11ShaderResourceView* m_yuyvTextureSRV; - ID3D11PixelShader* m_pShader; - ID3D11SamplerState* m_samplerState; -}; -} diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index ced41e2b13..4a0c9c29a5 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -78,6 +78,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsInternalResolutionFrameDumps = false; g_Config.backend_info.bSupportsGPUTextureDecoding = false; g_Config.backend_info.bSupportsST3CTextures = false; + g_Config.backend_info.bSupportsCopyToVram = true; g_Config.backend_info.bSupportsBitfield = false; g_Config.backend_info.bSupportsDynamicSamplerIndexing = false; g_Config.backend_info.bSupportsBPTCTextures = false; diff --git a/Source/Core/VideoBackends/Null/FramebufferManager.h b/Source/Core/VideoBackends/Null/FramebufferManager.h index d68a4a7d1f..0419ee36f8 100644 --- a/Source/Core/VideoBackends/Null/FramebufferManager.h +++ b/Source/Core/VideoBackends/Null/FramebufferManager.h @@ -12,7 +12,6 @@ class XFBSource : public XFBSourceBase { public: - void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override {} void CopyEFB(float gamma) override {} }; diff --git a/Source/Core/VideoBackends/Null/Render.cpp b/Source/Core/VideoBackends/Null/Render.cpp index 084a7b49af..b1a88f7a80 100644 --- a/Source/Core/VideoBackends/Null/Render.cpp +++ b/Source/Core/VideoBackends/Null/Render.cpp @@ -36,7 +36,7 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) return result; } -void Renderer::SwapImpl(u32, u32, u32, u32, const EFBRectangle&, u64, float) +void Renderer::SwapImpl(AbstractTexture*, const EFBRectangle&, u64, float) { UpdateActiveConfig(); } diff --git a/Source/Core/VideoBackends/Null/Render.h b/Source/Core/VideoBackends/Null/Render.h index 2187f147c0..2a21918f81 100644 --- a/Source/Core/VideoBackends/Null/Render.h +++ b/Source/Core/VideoBackends/Null/Render.h @@ -21,8 +21,7 @@ public: void BBoxWrite(int index, u16 value) override {} TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override; - void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc, - u64 ticks, float gamma) override; + void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override; void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) override diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 91be73a9f3..77ef205f2a 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -530,7 +530,7 @@ void FramebufferManager::ResolveEFBStencilTexture() void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { - u8* xfb_in_ram = Memory::GetPointer(xfbAddr); +/* u8* xfb_in_ram = Memory::GetPointer(xfbAddr); if (!xfb_in_ram) { WARN_LOG(VIDEO, "Tried to copy to invalid XFB address"); @@ -539,7 +539,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc); TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, - sourceRc.GetWidth(), fbStride, fbHeight); + sourceRc.GetWidth(), fbStride, fbHeight);*/ } GLuint FramebufferManager::GetResolvedFramebuffer() @@ -615,11 +615,6 @@ XFBSource::~XFBSource() glDeleteTextures(1, &texture); } -void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) -{ - TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture); -} - void XFBSource::CopyEFB(float Gamma) { g_renderer->ResetAPIState(); diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.h b/Source/Core/VideoBackends/OGL/FramebufferManager.h index 62b2f5ce3c..1d3626af36 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.h +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.h @@ -54,7 +54,6 @@ struct XFBSource : public XFBSourceBase ~XFBSource(); void CopyEFB(float Gamma) override; - void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override; const GLuint texture; const int m_layers; diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp index f400bc56ef..08e0d36c6e 100644 --- a/Source/Core/VideoBackends/OGL/PostProcessing.cpp +++ b/Source/Core/VideoBackends/OGL/PostProcessing.cpp @@ -25,7 +25,7 @@ static const char s_vertex_shader[] = "out vec2 uv0;\n" "void main(void) {\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" - " uv0 = rawpos * src_rect.zw + src_rect.xy;\n" + " uv0 = vec2(mix(src_rect.xy, src_rect.zw, rawpos));\n" "}\n"; OpenGLPostProcessing::OpenGLPostProcessing() : m_initialized(false) @@ -52,8 +52,8 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle glUniform4f(m_uniform_resolution, (float)src_width, (float)src_height, 1.0f / (float)src_width, 1.0f / (float)src_height); - glUniform4f(m_uniform_src_rect, src.left / (float)src_width, src.bottom / (float)src_height, - src.GetWidth() / (float)src_width, src.GetHeight() / (float)src_height); + glUniform4f(m_uniform_src_rect, src.left / (float)src_width, src.top / (float)src_height, + src.right / (float)src_width, src.bottom / (float)src_height); glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed()); glUniform1i(m_uniform_layer, layer); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index ccf89b45f2..d53ace17a5 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -66,7 +66,6 @@ static std::unique_ptr<RasterFont> s_raster_font; static int s_MSAASamples = 1; static u32 s_last_multisamples = 1; static bool s_last_stereo_mode = false; -static bool s_last_xfb_mode = false; static bool s_vsync; @@ -726,7 +725,6 @@ Renderer::Renderer() s_MSAASamples = s_last_multisamples; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; - s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; // Handle VSync on/off s_vsync = g_ActiveConfig.IsVSync(); @@ -1331,8 +1329,7 @@ void Renderer::SetBlendingState(const BlendingState& state) } // This function has the final picture. We adjust the aspect ratio here. -void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, - const EFBRectangle& rc, u64 ticks, float Gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) { if (g_ogl_config.bSupportsDebug) { @@ -1342,20 +1339,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, glDisable(GL_DEBUG_OUTPUT); } - if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) - { - Core::Callback_VideoCopiedToXFB(false); - return; - } + auto* xfb_texture = static_cast<OGLTexture*>(texture); - u32 xfbCount = 0; - const XFBSourceBase* const* xfbSourceList = - FramebufferManager::GetXFBSource(xfbAddr, fbStride, fbHeight, &xfbCount); - if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0)) - { - Core::Callback_VideoCopiedToXFB(false); - return; - } + TargetRectangle sourceRc = ConvertEFBRectangle(rc); + sourceRc.left = 0; + sourceRc.right = xfb_texture->config.width; + sourceRc.top = xfb_texture->config.height; + sourceRc.bottom = 0; ResetAPIState(); @@ -1366,7 +1356,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, std::swap(flipped_trc.top, flipped_trc.bottom); // Copy the framebuffer to screen. - DrawFrame(0, flipped_trc, rc, xfbAddr, xfbSourceList, xfbCount, fbWidth, fbStride, fbHeight); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + BlitScreen(sourceRc, flipped_trc, xfb_texture->GetRawTexIdentifier(), xfb_texture->config.width, xfb_texture->config.height); // The FlushFrameDump call here is necessary even after frame dumping is stopped. // If left out, screenshots are "one frame" behind, as an extra frame is dumped and buffered. @@ -1380,7 +1371,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, if (use_offscreen_buffer) { // DumpFrameUsingFBO resets GL_FRAMEBUFFER, so change back to the window for drawing OSD. - DumpFrameUsingFBO(rc, xfbAddr, xfbSourceList, xfbCount, fbWidth, fbStride, fbHeight, ticks); + DumpFrameUsingFBO(sourceRc, ticks); } else { @@ -1391,24 +1382,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, // Finish up the current frame, print some stats - SetWindowSize(fbStride, fbHeight); + SetWindowSize(xfb_texture->config.width, xfb_texture->config.height); GLInterface->Update(); // just updates the render window position and the backbuffer size - bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB; - - if (FramebufferManagerBase::LastXfbWidth() != fbStride || - FramebufferManagerBase::LastXfbHeight() != fbHeight) - { - xfbchanged = true; - unsigned int const last_w = - (fbStride < 1 || fbStride > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbStride; - unsigned int const last_h = - (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight; - FramebufferManagerBase::SetLastXfbWidth(last_w); - FramebufferManagerBase::SetLastXfbHeight(last_h); - } - bool window_resized = false; int window_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 1u)); int window_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 1u)); @@ -1428,9 +1405,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, stencil_buffer_enabled != BoundingBox::NeedsStencilBuffer() || s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0); - if (xfbchanged || window_resized || fb_needs_update) + if (window_resized || fb_needs_update) { - s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; UpdateDrawRectangle(); } if (fb_needs_update) @@ -1523,110 +1499,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, ClearEFBCache(); } -void Renderer::DrawFrame(GLuint framebuffer, const TargetRectangle& target_rc, - const EFBRectangle& source_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height) -{ - if (g_ActiveConfig.bUseXFB) - { - if (g_ActiveConfig.bUseRealXFB) - DrawRealXFB(framebuffer, target_rc, xfb_sources, xfb_count, fb_width, fb_stride, fb_height); - else - DrawVirtualXFB(framebuffer, target_rc, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, - fb_height); - } - else - { - DrawEFB(framebuffer, target_rc, source_rc); - } -} - void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, - const EFBRectangle& source_rc) + const TargetRectangle& source_rc) { - TargetRectangle scaled_source_rc = ConvertEFBRectangle(source_rc); - // for msaa mode, we must resolve the efb content to non-msaa GLuint tex = FramebufferManager::ResolveAndGetRenderTarget(source_rc); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - BlitScreen(scaled_source_rc, target_rc, tex, m_target_width, m_target_height); -} - -void Renderer::DrawVirtualXFB(GLuint framebuffer, const TargetRectangle& target_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height) -{ - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - for (u32 i = 0; i < xfb_count; ++i) - { - const XFBSource* xfbSource = static_cast<const XFBSource*>(xfb_sources[i]); - - TargetRectangle draw_rc; - TargetRectangle source_rc; - source_rc.left = xfbSource->sourceRc.left; - source_rc.right = xfbSource->sourceRc.right; - source_rc.top = xfbSource->sourceRc.top; - source_rc.bottom = xfbSource->sourceRc.bottom; - - // use virtual xfb with offset - int xfbHeight = xfbSource->srcHeight; - int xfbWidth = xfbSource->srcWidth; - int hOffset = (static_cast<s32>(xfbSource->srcAddr) - static_cast<s32>(xfb_addr)) / - (static_cast<s32>(fb_stride) * 2); - - draw_rc.top = target_rc.top - hOffset * target_rc.GetHeight() / static_cast<s32>(fb_height); - draw_rc.bottom = - target_rc.top - (hOffset + xfbHeight) * target_rc.GetHeight() / static_cast<s32>(fb_height); - draw_rc.left = - target_rc.left + - (target_rc.GetWidth() - xfbWidth * target_rc.GetWidth() / static_cast<s32>(fb_stride)) / 2; - draw_rc.right = - target_rc.left + - (target_rc.GetWidth() + xfbWidth * target_rc.GetWidth() / static_cast<s32>(fb_stride)) / 2; - - // The following code disables auto stretch. Kept for reference. - // scale draw area for a 1 to 1 pixel mapping with the draw target - // float h_scale = static_cast<float>(fb_width) / static_cast<float>(target_rc.GetWidth()); - // float v_scale = static_cast<float>(fb_height) / static_cast<float>(target_rc.GetHeight()); - // draw_rc.top *= v_scale; - // draw_rc.bottom *= v_scale; - // draw_rc.left *= h_scale; - // draw_rc.right *= h_scale; - - source_rc.right -= Renderer::EFBToScaledX(fb_stride - fb_width); - - BlitScreen(source_rc, draw_rc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight); - } -} - -void Renderer::DrawRealXFB(GLuint framebuffer, const TargetRectangle& target_rc, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height) -{ - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - for (u32 i = 0; i < xfb_count; ++i) - { - const XFBSource* xfbSource = static_cast<const XFBSource*>(xfb_sources[i]); - - TargetRectangle source_rc; - source_rc.left = xfbSource->sourceRc.left; - source_rc.right = xfbSource->sourceRc.right; - source_rc.top = xfbSource->sourceRc.top; - source_rc.bottom = xfbSource->sourceRc.bottom; - - source_rc.right -= fb_stride - fb_width; - - // RealXFB doesn't call ConvertEFBRectangle for sourceRc, therefore it is still assuming a top- - // left origin. The top offset is always zero (see FramebufferManagerBase::GetRealXFBSource). - source_rc.top = source_rc.bottom; - source_rc.bottom = 0; - - TargetRectangle draw_rc = target_rc; - BlitScreen(source_rc, draw_rc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight); - } + BlitScreen(source_rc, target_rc, tex, m_target_width, m_target_height); } void Renderer::FlushFrameDump() @@ -1683,9 +1562,7 @@ void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks) glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } -void Renderer::DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, - u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks) +void Renderer::DumpFrameUsingFBO(const TargetRectangle& source_rc, u64 ticks) { // This needs to be converted to the GL bottom-up window coordinate system. TargetRectangle render_rc = CalculateFrameDumpDrawRectangle(); @@ -1705,8 +1582,7 @@ void Renderer::DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr, // Render the frame into the frame dump render texture. Disable alpha writes in case the // post-processing shader writes a non-1.0 value. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - DrawFrame(m_frame_dump_render_framebuffer, render_rc, source_rc, xfb_addr, xfb_sources, xfb_count, - fb_width, fb_stride, fb_height); + DrawEFB(m_frame_dump_render_framebuffer, render_rc, source_rc); // Copy frame to output buffer. This assumes that GL_FRAMEBUFFER has been set. DumpFrame(render_rc, ticks); diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index 8efea70bec..a130e9c770 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -98,8 +98,7 @@ public: TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override; - void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, - u64 ticks, float Gamma) override; + void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override; void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) override; @@ -112,27 +111,14 @@ private: void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const void* data); - // Draw either the EFB, or specified XFB sources to the currently-bound framebuffer. - void DrawFrame(GLuint framebuffer, const TargetRectangle& target_rc, - const EFBRectangle& source_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height); - void DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, const EFBRectangle& source_rc); - void DrawVirtualXFB(GLuint framebuffer, const TargetRectangle& target_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height); - void DrawRealXFB(GLuint framebuffer, const TargetRectangle& target_rc, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height); + void DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, const TargetRectangle& source_rc); void BlitScreen(TargetRectangle src, TargetRectangle dst, GLuint src_texture, int src_width, int src_height); void FlushFrameDump(); void DumpFrame(const TargetRectangle& flipped_trc, u64 ticks); - void DumpFrameUsingFBO(const EFBRectangle& source_rc, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height, u64 ticks); + void DumpFrameUsingFBO(const TargetRectangle& source_rc, u64 ticks); // Frame dumping framebuffer, we render to this, then read it back void PrepareFrameDumpRenderTexture(u32 width, u32 height); diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 4b3a7a5daf..f5ccbcd64c 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -91,6 +91,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.bSupportsReversedDepthRange = true; g_Config.backend_info.bSupportsMultithreading = false; g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true; + g_Config.backend_info.bSupportsCopyToVram = true; // TODO: There is a bug here, if texel buffers are not supported the graphics options // will show the option when it is not supported. The only way around this would be diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index 9f6af90c0d..411839c852 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -520,15 +520,6 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe // Scanline buffer, leave room for borders yuv444 scanline[EFB_WIDTH + 2]; - // our internal yuv444 type is not normalized, so black is {0, 0, 0} instead of {16, 128, 128} - yuv444 black; - black.Y = 0; - black.U = 0; - black.V = 0; - - scanline[0] = black; // black border at start - scanline[right + 1] = black; // black border at end - for (u16 y = sourceRc.top; y < sourceRc.bottom; y++) { // Get a scanline of YUV pixels in 4:4:4 format @@ -538,6 +529,10 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe scanline[i] = GetColorYUV(x, y); } + // Flipper clamps the border colors + scanline[0] = scanline[1]; + scanline[right + 1] = scanline[right]; + // And Downsample them to 4:2:2 for (int i = 1, x = left; x < right; i += 2, x += 2) { @@ -562,26 +557,7 @@ void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRe // main memory or doing a yuyv conversion void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { - if (fbWidth * fbHeight > MAX_XFB_WIDTH * MAX_XFB_HEIGHT) - { - ERROR_LOG(VIDEO, "Framebuffer is too large: %ix%i", fbWidth, fbHeight); - return; - } - - size_t textureAddress = 0; - const int left = sourceRc.left; - const int right = sourceRc.right; - - for (u16 y = sourceRc.top; y < sourceRc.bottom; y++) - { - for (u16 x = left; x < right; x++) - { - const u32 color = Common::swap32(GetColor(x, y) | 0xFF); - - std::memcpy(&texture[textureAddress], &color, sizeof(u32)); - textureAddress += sizeof(u32); - } - } + // TODO: Upload directly to texture cache. } bool ZCompare(u16 x, u16 y, u32 z) diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 9d42ff5790..52b2fb02cd 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -9,6 +9,7 @@ #include "Common/Logging/Log.h" #include "VideoBackends/Software/SWOGLWindow.h" +#include "VideoCommon/AbstractTexture.h" std::unique_ptr<SWOGLWindow> SWOGLWindow::s_instance; @@ -53,9 +54,9 @@ void SWOGLWindow::Prepare() std::string frag_shader = "in vec2 TexCoord;\n" "out vec4 ColorOut;\n" - "uniform sampler2D Texture;\n" + "uniform sampler2DArray samp;\n" "void main() {\n" - " ColorOut = texture(Texture, TexCoord);\n" + " ColorOut = texture(samp, vec3(TexCoord, 0.0));\n" "}\n"; std::string vertex_shader = "out vec2 TexCoord;\n" @@ -74,12 +75,9 @@ void SWOGLWindow::Prepare() glUseProgram(m_image_program); - glUniform1i(glGetUniformLocation(m_image_program, "Texture"), 0); + glUniform1i(glGetUniformLocation(m_image_program, "samp"), 0); - glGenTextures(1, &m_image_texture); - glBindTexture(GL_TEXTURE_2D, m_image_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment glGenVertexArrays(1, &m_image_vao); } @@ -89,23 +87,19 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) m_text.push_back({text, x, y, color}); } -void SWOGLWindow::ShowImage(const u8* data, int stride, int width, int height, float aspect) +void SWOGLWindow::ShowImage(AbstractTexture* image, float aspect) { - GLInterface->MakeCurrent(); - GLInterface->Update(); - Prepare(); + GLInterface->Update(); // just updates the render window position and the backbuffer size GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); glViewport(0, 0, glWidth, glHeight); - glBindTexture(GL_TEXTURE_2D, m_image_texture); + image->Bind(0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glUseProgram(m_image_program); @@ -119,7 +113,6 @@ void SWOGLWindow::ShowImage(const u8* data, int stride, int width, int height, f m_text.clear(); GLInterface->Swap(); - GLInterface->ClearCurrent(); } int SWOGLWindow::PeekMessages() diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 110642b3f8..3b5d623846 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -10,17 +10,20 @@ #include "Common/CommonTypes.h" +class AbstractTexture; + class SWOGLWindow { public: static void Init(void* window_handle); static void Shutdown(); + void Prepare(); // Will be printed on the *next* image void PrintText(const std::string& text, int x, int y, u32 color); // Image to show, will be swapped immediately - void ShowImage(const u8* data, int stride, int width, int height, float aspect); + void ShowImage(AbstractTexture* image, float aspect); int PeekMessages(); @@ -28,7 +31,6 @@ public: private: SWOGLWindow() {} - void Prepare(); struct TextData { @@ -40,5 +42,5 @@ private: bool m_init{false}; - u32 m_image_program, m_image_texture, m_image_vao; + u32 m_image_program, m_image_vao; }; diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index dc378cbede..9074a429b9 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -23,26 +23,13 @@ #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" -static u8* s_xfbColorTexture[2]; -static int s_currentColorTexture = 0; - SWRenderer::SWRenderer() : ::Renderer(static_cast<int>(MAX_XFB_WIDTH), static_cast<int>(MAX_XFB_HEIGHT)) { } -SWRenderer::~SWRenderer() -{ - delete[] s_xfbColorTexture[0]; - delete[] s_xfbColorTexture[1]; -} - void SWRenderer::Init() { - s_xfbColorTexture[0] = new u8[MAX_XFB_WIDTH * MAX_XFB_HEIGHT * 4]; - s_xfbColorTexture[1] = new u8[MAX_XFB_WIDTH * MAX_XFB_HEIGHT * 4]; - - s_currentColorTexture = 0; } void SWRenderer::Shutdown() @@ -55,80 +42,16 @@ void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 colo SWOGLWindow::s_instance->PrintText(pstr, left, top, color); } -u8* SWRenderer::GetNextColorTexture() -{ - return s_xfbColorTexture[!s_currentColorTexture]; -} - -u8* SWRenderer::GetCurrentColorTexture() -{ - return s_xfbColorTexture[s_currentColorTexture]; -} - -void SWRenderer::SwapColorTexture() -{ - s_currentColorTexture = !s_currentColorTexture; -} - -void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed* xfb, u32 fbWidth, u32 fbHeight) -{ - if (fbWidth * fbHeight > MAX_XFB_WIDTH * MAX_XFB_HEIGHT) - { - ERROR_LOG(VIDEO, "Framebuffer is too large: %ix%i", fbWidth, fbHeight); - return; - } - - u32 offset = 0; - u8* TexturePointer = GetNextColorTexture(); - - for (u16 y = 0; y < fbHeight; y++) - { - for (u16 x = 0; x < fbWidth; x += 2) - { - // We do this one color sample (aka 2 RGB pixles) at a time - int Y1 = xfb[x].Y - 16; - int Y2 = xfb[x + 1].Y - 16; - int U = int(xfb[x].UV) - 128; - int V = int(xfb[x + 1].UV) - 128; - - // We do the inverse BT.601 conversion for YCbCr to RGB - // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion - TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255); - TexturePointer[offset++] = - MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255); - TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255); - TexturePointer[offset++] = 255; - - TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255); - TexturePointer[offset++] = - MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255); - TexturePointer[offset++] = MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255); - TexturePointer[offset++] = 255; - } - xfb += fbWidth; - } - SwapColorTexture(); -} - // Called on the GPU thread -void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, - const EFBRectangle& rc, u64 ticks, float Gamma) +void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) { - if (g_ActiveConfig.bUseXFB) - { - EfbInterface::yuv422_packed* xfb = (EfbInterface::yuv422_packed*)Memory::GetPointer(xfbAddr); - UpdateColorTexture(xfb, fbWidth, fbHeight); - } - else - { - EfbInterface::BypassXFB(GetCurrentColorTexture(), fbWidth, fbHeight, rc, Gamma); - } + SWOGLWindow::s_instance->ShowImage(texture, 1.0); // Save screenshot if (IsFrameDumping()) { AVIDump::Frame state = AVIDump::FetchState(ticks); - DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state); + //DumpFrameData(GetCurrentColorTexture(), fbWidth, fbHeight, fbWidth * 4, state); FinishFrameData(); } @@ -136,15 +59,9 @@ void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, DrawDebugText(); - SWOGLWindow::s_instance->ShowImage(GetCurrentColorTexture(), fbWidth * 4, fbWidth, fbHeight, 1.0); + SWOGLWindow::s_instance->ShowImage(texture, 1.0); UpdateActiveConfig(); - - // virtual XFB is not supported - if (g_ActiveConfig.bUseXFB) - { - Config::SetCurrent(Config::GFX_USE_REAL_XFB, true); - } } u32 SWRenderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData) diff --git a/Source/Core/VideoBackends/Software/SWRenderer.h b/Source/Core/VideoBackends/Software/SWRenderer.h index b19b9841fd..e30e490bd7 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/SWRenderer.h @@ -14,16 +14,10 @@ class SWRenderer : public Renderer { public: SWRenderer(); - ~SWRenderer() override; static void Init(); static void Shutdown(); - static u8* GetNextColorTexture(); - static u8* GetCurrentColorTexture(); - void SwapColorTexture(); - void UpdateColorTexture(EfbInterface::yuv422_packed* xfb, u32 fbWidth, u32 fbHeight); - void RenderText(const std::string& pstr, int left, int top, u32 color) override; u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {} @@ -32,8 +26,7 @@ public: TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override; - void SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, - u64 ticks, float Gamma) override; + void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override; void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) override; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index dff26e6d86..26a649b010 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -8,16 +8,17 @@ #include <utility> #include "Common/CommonTypes.h" +#include "Common/GL/GLInterfaceBase.h" #include "VideoBackends/Software/Clipper.h" #include "VideoBackends/Software/DebugUtil.h" -#include "VideoBackends/Software/EfbCopy.h" #include "VideoBackends/Software/EfbInterface.h" #include "VideoBackends/Software/Rasterizer.h" #include "VideoBackends/Software/SWOGLWindow.h" #include "VideoBackends/Software/SWRenderer.h" #include "VideoBackends/Software/SWTexture.h" #include "VideoBackends/Software/SWVertexLoader.h" +#include "VideoBackends/Software/TextureCache.h" #include "VideoBackends/Software/VideoBackend.h" #include "VideoCommon/FramebufferManagerBase.h" @@ -46,58 +47,6 @@ public: bool IsFlushed() const override { return true; } }; -class TextureCache : public TextureCacheBase -{ -public: - bool CompileShaders() override { return true; } - void DeleteShaders() override {} - void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette, - TLUTFormat format) override - { - } - void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row, - u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, - bool scale_by_half) override - { - EfbCopy::CopyEfb(); - } - -private: - std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override - { - return std::make_unique<SWTexture>(config); - } - - void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect, - bool scale_by_half, unsigned int cbuf_id, const float* colmat) override - { - EfbCopy::CopyEfb(); - } -}; - -class XFBSource : public XFBSourceBase -{ - void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override {} - void CopyEFB(float Gamma) override {} -}; - -class FramebufferManager : public FramebufferManagerBase -{ - std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width, - unsigned int target_height, - unsigned int layers) override - { - return std::make_unique<XFBSource>(); - } - - std::pair<u32, u32> GetTargetSize() const override { return std::make_pair(0, 0); } - void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, - float Gamma = 1.0f) override - { - EfbCopy::CopyEfb(); - } -}; - std::string VideoSoftware::GetName() const { return "Software Renderer"; @@ -123,6 +72,7 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.bSupportsGPUTextureDecoding = false; g_Config.backend_info.bSupportsST3CTextures = false; g_Config.backend_info.bSupportsBPTCTextures = false; + g_Config.backend_info.bSupportsCopyToVram = false; // aamodes g_Config.backend_info.AAModes = {1}; @@ -169,12 +119,14 @@ void VideoSoftware::Video_Cleanup() // This is called after Video_Initialize() from the Core void VideoSoftware::Video_Prepare() { + GLInterface->MakeCurrent(); + SWOGLWindow::s_instance->Prepare(); + g_renderer = std::make_unique<SWRenderer>(); g_vertex_manager = std::make_unique<SWVertexLoader>(); g_perf_query = std::make_unique<PerfQuery>(); g_texture_cache = std::make_unique<TextureCache>(); SWRenderer::Init(); - g_framebuffer_manager = std::make_unique<FramebufferManager>(); } unsigned int VideoSoftware::PeekMessages() diff --git a/Source/Core/VideoBackends/Software/Software.vcxproj b/Source/Core/VideoBackends/Software/Software.vcxproj index bf13233d67..36d833ba2c 100644 --- a/Source/Core/VideoBackends/Software/Software.vcxproj +++ b/Source/Core/VideoBackends/Software/Software.vcxproj @@ -65,6 +65,7 @@ <ClInclude Include="SWTexture.h" /> <ClInclude Include="SWVertexLoader.h" /> <ClInclude Include="Tev.h" /> + <ClInclude Include="TextureCache.h" /> <ClInclude Include="TextureEncoder.h" /> <ClInclude Include="TextureSampler.h" /> <ClInclude Include="TransformUnit.h" /> diff --git a/Source/Core/VideoBackends/Software/TextureCache.h b/Source/Core/VideoBackends/Software/TextureCache.h new file mode 100644 index 0000000000..82c2ce9f55 --- /dev/null +++ b/Source/Core/VideoBackends/Software/TextureCache.h @@ -0,0 +1,41 @@ +#pragma once + +#include <memory> + +#include "VideoBackends/Software/EfbCopy.h" +#include "VideoBackends/Software/SWTexture.h" +#include "VideoCommon/TextureCacheBase.h" + +namespace SW +{ + +class TextureCache : public TextureCacheBase +{ +public: + bool CompileShaders() override { return true; } + void DeleteShaders() override {} + void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, const void* palette, + TLUTFormat format) override + { + } + void CopyEFB(u8* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row, + u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, + bool scale_by_half) override + { + EfbCopy::CopyEfb(); + } + +private: + std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override + { + return std::make_unique<SWTexture>(config); + } + + void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect, + bool scale_by_half, unsigned int cbuf_id, const float* colmat) override + { + EfbCopy::CopyEfb(); + } +}; + +} // namespace SW diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp index 53351e0325..c23c19b544 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp @@ -89,11 +89,6 @@ MultisamplingState FramebufferManager::GetEFBMultisamplingState() const return ms; } -std::pair<u32, u32> FramebufferManager::GetTargetSize() const -{ - return std::make_pair(GetEFBWidth(), GetEFBHeight()); -} - bool FramebufferManager::Initialize() { if (!CreateEFBRenderPass()) @@ -1450,15 +1445,6 @@ VKTexture* XFBSource::GetTexture() const return static_cast<VKTexture*>(m_texture.get()); } -void XFBSource::DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) -{ - // Guest memory -> GPU EFB Textures - const u8* src_ptr = Memory::GetPointer(xfb_addr); - _assert_(src_ptr); - TextureCache::GetInstance()->GetTextureConverter()->DecodeYUYVTextureFromMemory( - static_cast<VKTexture*>(m_texture.get()), src_ptr, fb_width, fb_width * 2, fb_height); -} - void XFBSource::CopyEFB(float gamma) { // Pending/batched EFB pokes should be included in the copied image. diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h index ca7065c3bb..3f2a251662 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h @@ -43,7 +43,6 @@ public: u32 GetEFBLayers() const; VkSampleCountFlagBits GetEFBSamples() const; MultisamplingState GetEFBMultisamplingState() const; - std::pair<u32, u32> GetTargetSize() const override; std::unique_ptr<XFBSourceBase> CreateXFBSource(unsigned int target_width, unsigned int target_height, @@ -178,8 +177,6 @@ public: ~XFBSource(); VKTexture* GetTexture() const; - // Guest -> GPU EFB Textures - void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override; // Used for virtual XFB void CopyEFB(float gamma) override; diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 3a4907b88c..be442476ad 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -41,6 +41,7 @@ #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/VideoBackendBase.h" +#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" @@ -485,27 +486,19 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) BindEFBToStateTracker(); } -void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, - const EFBRectangle& rc, u64 ticks, float gamma) +void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) { // Pending/batched EFB pokes should be included in the final image. FramebufferManager::GetInstance()->FlushEFBPokes(); // Check that we actually have an image to render in XFB-on modes. - if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height) + if (!m_xfb_written) { Core::Callback_VideoCopiedToXFB(false); - return; - } - u32 xfb_count = 0; - const XFBSourceBase* const* xfb_sources = - FramebufferManager::GetXFBSource(xfb_addr, fb_stride, fb_height, &xfb_count); - if (g_ActiveConfig.VirtualXFBEnabled() && (!xfb_sources || xfb_count == 0)) - { - Core::Callback_VideoCopiedToXFB(false); - return; } + auto* xfb_texture = static_cast<VKTexture*>(texture); + // End the current render pass. StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->OnEndFrame(); @@ -514,14 +507,6 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height // are determined by guest state. Currently, the only way to catch these is to update every frame. UpdateDrawRectangle(); - // Scale the source rectangle to the internal resolution when XFB is disabled. - TargetRectangle scaled_efb_rect = Renderer::ConvertEFBRectangle(rc); - - // If MSAA is enabled, and we're not using XFB, we need to resolve the EFB framebuffer before - // rendering the final image to the screen, or dumping the frame. This is because we can't resolve - // an image within a render pass, which will have already started by the time it is used. - TransitionBuffersForSwap(scaled_efb_rect, xfb_sources, xfb_count); - // Render the frame dump image if enabled. if (IsFrameDumping()) { @@ -529,8 +514,8 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height if (!m_frame_dumping_active) StartFrameDumping(); - DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height, - ticks); + /* DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height, + ticks);*/ } else { @@ -547,7 +532,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height // Draw to the screen if we have a swap chain. if (m_swap_chain) { - DrawScreen(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height); + DrawScreen(xfb_texture); // Submit the current command buffer, signaling rendering finished semaphore when it's done // Because this final command buffer is rendering to the swap chain, we need to wait for @@ -581,15 +566,12 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height // Handle host window resizes. CheckForSurfaceChange(); - // Handle output size changes from the guest. - // There is a downside to doing this here is that if the game changes its XFB source area, - // the changes will be delayed by one frame. For the moment it has to be done here because - // this can cause a target size change, which would result in a black frame if done earlier. - CheckForTargetResize(fb_width, fb_stride, fb_height); + if (CalculateTargetSize()) + ResizeEFBTextures(); // Update the window size based on the frame that was just rendered. // Due to depending on guest state, we need to call this every frame. - SetWindowSize(static_cast<int>(fb_stride), static_cast<int>(fb_height)); + SetWindowSize(xfb_texture->config.width, xfb_texture->config.height); // Clean up stale textures. TextureCache::GetInstance()->Cleanup(frameCount); @@ -714,9 +696,7 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ } } -void Renderer::DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height) +void Renderer::DrawScreen(VKTexture* xfb_texture) { VkResult res; if (!g_command_buffer_mgr->CheckLastPresentFail()) @@ -767,9 +747,9 @@ void Renderer::DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, vkCmdBeginRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer(), &info, VK_SUBPASS_CONTENTS_INLINE); - // Draw guest buffers (EFB or XFB) - DrawFrame(m_swap_chain->GetRenderPass(), GetTargetRectangle(), scaled_efb_rect, xfb_addr, - xfb_sources, xfb_count, fb_width, fb_stride, fb_height); + // Draw + TargetRectangle source_rc = xfb_texture->config.Rect(); + BlitScreen(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rc, xfb_texture->GetRawTexIdentifier()); // Draw OSD Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0, @@ -1055,7 +1035,7 @@ void Renderer::DestroyFrameDumpResources() void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height) { - if (FramebufferManagerBase::LastXfbWidth() == fb_stride && + /*if (FramebufferManagerBase::LastXfbWidth() == fb_stride && FramebufferManagerBase::LastXfbHeight() == fb_height) { return; @@ -1068,7 +1048,7 @@ void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height) // Changing the XFB source area may alter the target size. if (CalculateTargetSize()) - ResizeEFBTextures(); + ResizeEFBTextures();*/ } void Renderer::CheckForSurfaceChange() diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index 5a367f2bcd..b9d746582c 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -23,6 +23,7 @@ class SwapChain; class StagingTexture2D; class Texture2D; class RasterFont; +class VKTexture; class Renderer : public ::Renderer { @@ -43,8 +44,7 @@ public: void BBoxWrite(int index, u16 value) override; TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override; - void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc, - u64 ticks, float gamma) override; + void SwapImpl(AbstractTexture* texture, const EFBRectangle& rc, u64 ticks, float Gamma) override; void ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable, u32 color, u32 z) override; @@ -106,9 +106,7 @@ private: u32 fb_stride, u32 fb_height); // Draw the frame, as well as the OSD to the swap chain. - void DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, - const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width, - u32 fb_stride, u32 fb_height); + void DrawScreen(VKTexture* xfb_texture); // Draw the frame only to the screenshot buffer. bool DrawFrameDump(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index e2f44b73be..3edd507b23 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -246,6 +246,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config) config->backend_info.bSupportsST3CTextures = false; // Dependent on features. config->backend_info.bSupportsBPTCTextures = false; // Dependent on features. config->backend_info.bSupportsReversedDepthRange = false; // No support yet due to driver bugs. + config->backend_info.bSupportsCopyToVram = true; // Assumed support. } void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list) |
