From 2faab0e08299495c42de6fe7e993e7bea23f20e8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 11 May 2020 13:36:23 -0700 Subject: [PATCH] GPU: Use postshader for direct VRAM draws again. Also centralize the pixel texture code while at it. --- GPU/Common/FramebufferCommon.cpp | 75 ++++++++++++++++++++++++--- GPU/Common/FramebufferCommon.h | 3 +- GPU/D3D11/FramebufferManagerD3D11.cpp | 49 +---------------- GPU/D3D11/FramebufferManagerD3D11.h | 1 - GPU/Directx9/FramebufferDX9.cpp | 49 +---------------- GPU/Directx9/FramebufferDX9.h | 1 - GPU/Directx9/StencilBufferDX9.cpp | 2 + GPU/GLES/FramebufferManagerGLES.cpp | 50 ------------------ GPU/GLES/FramebufferManagerGLES.h | 1 - GPU/GLES/StencilBufferGLES.cpp | 5 +- GPU/Vulkan/FramebufferVulkan.cpp | 52 ------------------- GPU/Vulkan/FramebufferVulkan.h | 3 -- GPU/Vulkan/StencilBufferVulkan.cpp | 3 ++ 13 files changed, 82 insertions(+), 212 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index eee1a0027a..db9c35f2b1 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -700,6 +700,71 @@ void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer } } +Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) { + // TODO: We can just change the texture format and flip some bits around instead of this. + // Could share code with the texture cache perhaps. + auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) { + for (int y = 0; y < height; y++) { + const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y; + const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y; + u32 *dst = (u32 *)(data + byteStride * y); + switch (srcPixelFormat) { + case GE_FORMAT_565: + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) + ConvertRGB565ToBGRA8888(dst, src16, width); + else + ConvertRGBA565ToRGBA8888(dst, src16, width); + break; + + case GE_FORMAT_5551: + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) + ConvertRGBA5551ToBGRA8888(dst, src16, width); + else + ConvertRGBA5551ToRGBA8888(dst, src16, width); + break; + + case GE_FORMAT_4444: + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) + ConvertRGBA4444ToBGRA8888(dst, src16, width); + else + ConvertRGBA4444ToRGBA8888(dst, src16, width); + break; + + case GE_FORMAT_8888: + if (preferredPixelsFormat_ == Draw::DataFormat::B8G8R8A8_UNORM) + ConvertRGBA8888ToBGRA8888(dst, src32, width); + else + memcpy(dst, src32, 4 * width); + break; + + case GE_FORMAT_INVALID: + _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); + break; + } + } + }; + + Draw::TextureDesc desc{ + Draw::TextureType::LINEAR2D, + preferredPixelsFormat_, + width, + height, + 1, + 1, + false, + "DrawPixels", + { (uint8_t *)srcPixels }, + generateTexture, + }; + // TODO: On Vulkan, use a custom allocator? Important to use an allocator: + // Hot Shot Golf (#12355) does tons of these in a frame in some situations! So actually, + // we do use an allocator. In fact, I've now banned allocator-less textures. + Draw::Texture *tex = draw_->CreateTexture(desc); + if (!tex) + ERROR_LOG(G3D, "Failed to create drawpixels texture"); + return tex; +} + void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) { textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); @@ -712,8 +777,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu draw_->BindTextures(0, 1, &pixelsTex); int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; - // TODO: Currently we can't access the texture from Draw. - //if (!applyPostShader) { + if (!applyPostShader) { // TODO: Does this need to bind the backbuffer? What is this doing? float x, y, w, h; CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, uvRotation); @@ -727,7 +791,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu flags = flags | DRAWTEX_TO_BACKBUFFER; SetViewport2D(0, 0, pixelWidth_, pixelHeight_); DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags); - /*} else { + } else { OutputFlags flags = g_Config.iBufFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST; if (needBackBufferYSwap_) { flags |= OutputFlags::BACKBUFFER_FLIPPED; @@ -741,10 +805,9 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu std::swap(v0, v1); } - // TODO - presentation_->SourceTexture(); + presentation_->SourceTexture(pixelsTex); presentation_->CopyToOutput(flags, uvRotation, u0, v0, u1, v1, uniforms); - }*/ + } pixelsTex->Release(); diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index aad0bf8e7e..fe6959bdc6 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -308,7 +308,7 @@ public: protected: virtual void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h); void SetViewport2D(int x, int y, int w, int h); - virtual Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) = 0; + Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1); virtual void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) = 0; virtual void Bind2DShader() = 0; @@ -397,6 +397,7 @@ protected: int bloomHack_ = 0; bool needGLESRebinds_ = false; + Draw::DataFormat preferredPixelsFormat_ = Draw::DataFormat::R8G8B8A8_UNORM; struct TempFBOInfo { Draw::Framebuffer *fbo; diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 5a1fda5536..055f3d535c 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -129,6 +129,7 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) ShaderTranslationInit(); presentation_->SetLanguage(HLSL_D3D11); + preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM; } FramebufferManagerD3D11::~FramebufferManagerD3D11() { @@ -178,54 +179,6 @@ void FramebufferManagerD3D11::SetDrawEngine(DrawEngineD3D11 *td) { drawEngine_ = td; } -Draw::Texture *FramebufferManagerD3D11::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) { - auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) { - for (int y = 0; y < height; y++) { - const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y; - const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y; - u32 *dst = (u32 *)(data + byteStride * y); - switch (srcPixelFormat) { - case GE_FORMAT_565: - ConvertRGB565ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_5551: - ConvertRGBA5551ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_4444: - ConvertRGBA4444ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_8888: - ConvertRGBA8888ToBGRA8888(dst, src32, width); - break; - - case GE_FORMAT_INVALID: - _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); - break; - } - } - }; - - Draw::TextureDesc desc{ - Draw::TextureType::LINEAR2D, - Draw::DataFormat::B8G8R8A8_UNORM, - width, - height, - 1, - 1, - false, - "DrawPixels", - { (uint8_t *)srcPixels }, - generateTexture, - }; - Draw::Texture *tex = draw_->CreateTexture(desc); - if (!tex) - ERROR_LOG(G3D, "Failed to create drawpixels texture"); - return tex; -} - void FramebufferManagerD3D11::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { struct Coord { Lin::Vec3 pos; float u, v; diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index dc50926b16..eaacc60703 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -68,7 +68,6 @@ protected: private: void Bind2DShader() override; - Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); void SimpleBlit( Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2, diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index fcc06476c2..46bb1d6a2b 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -117,6 +117,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { ShaderTranslationInit(); presentation_->SetLanguage(HLSL_DX9); + preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM; } FramebufferManagerDX9::~FramebufferManagerDX9() { @@ -159,54 +160,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { drawEngine_ = td; } - Draw::Texture *FramebufferManagerDX9::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) { - auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) { - for (int y = 0; y < height; y++) { - const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y; - const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y; - u32 *dst = (u32 *)(data + byteStride * y); - switch (srcPixelFormat) { - case GE_FORMAT_565: - ConvertRGB565ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_5551: - ConvertRGBA5551ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_4444: - ConvertRGBA4444ToBGRA8888(dst, src16, width); - break; - - case GE_FORMAT_8888: - ConvertRGBA8888ToBGRA8888(dst, src32, width); - break; - - case GE_FORMAT_INVALID: - _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); - break; - } - } - }; - - Draw::TextureDesc desc{ - Draw::TextureType::LINEAR2D, - Draw::DataFormat::B8G8R8A8_UNORM, - width, - height, - 1, - 1, - false, - "DrawPixels", - { (uint8_t *)srcPixels }, - generateTexture, - }; - Draw::Texture *tex = draw_->CreateTexture(desc); - if (!tex) - ERROR_LOG(G3D, "Failed to create drawpixels texture"); - return tex; - } - void FramebufferManagerDX9::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { // TODO: StretchRect instead when possible? float coord[20] = { diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index d270345820..592ed3f119 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -76,7 +76,6 @@ protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: - Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h) override; void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); bool GetRenderTargetFramebuffer(LPDIRECT3DSURFACE9 renderTarget, LPDIRECT3DSURFACE9 offscreen, int w, int h, GPUDebugBuffer &buffer); diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 1219c4e334..5302c9e4f6 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -202,6 +202,8 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer float u1 = 1.0f; float v1 = 1.0f; Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); + if (!tex) + return false; device_->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, D3DCOLOR_RGBA(0, 0, 0, 0), 0.0f, 0); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 793e54726e..efaa14426c 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -166,56 +166,6 @@ FramebufferManagerGLES::~FramebufferManagerGLES() { delete [] convBuf_; } -Draw::Texture *FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) { - // TODO: We can just change the texture format and flip some bits around instead of this. - // Could share code with the texture cache perhaps. - auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) { - for (int y = 0; y < height; y++) { - const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y; - const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y; - u32 *dst = (u32 *)(data + byteStride * y); - switch (srcPixelFormat) { - case GE_FORMAT_565: - ConvertRGBA565ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_5551: - ConvertRGBA5551ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_4444: - ConvertRGBA4444ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_8888: - memcpy(dst, src32, 4 * width); - break; - - case GE_FORMAT_INVALID: - _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); - break; - } - } - }; - - Draw::TextureDesc desc{ - Draw::TextureType::LINEAR2D, - Draw::DataFormat::R8G8B8A8_UNORM, - width, - height, - 1, - 1, - false, - "DrawPixels", - { (uint8_t *)srcPixels }, - generateTexture, - }; - Draw::Texture *tex = draw_->CreateTexture(desc); - if (!tex) - ERROR_LOG(G3D, "Failed to create drawpixels texture"); - return tex; -} - // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. // TODO: This could totally use fbo_blit in many cases. void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index bfb438cbc3..7068c01796 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -73,7 +73,6 @@ private: void CreateDeviceObjects(); void DestroyDeviceObjects(); - Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; void Bind2DShader() override; void CompileDraw2DProgram(); diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 84e603be2b..387001db26 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -177,8 +177,11 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe float u1 = 1.0f; float v1 = 1.0f; - Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height, u1, v1); textureCacheGL_->ForgetLastTexture(); + Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height, u1, v1); + if (!tex) + return false; + draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex); // We must bind the program after starting the render pass, and set the color mask after clearing. diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 8db0df9438..f8f6e1cf72 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -176,58 +176,6 @@ void FramebufferManagerVulkan::Init() { Resized(); } -Draw::Texture *FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) { - auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) { - for (int y = 0; y < height; y++) { - const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y; - const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y; - u32 *dst = (u32 *)(data + byteStride * y); - switch (srcPixelFormat) { - case GE_FORMAT_565: - ConvertRGBA565ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_5551: - ConvertRGBA5551ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_4444: - ConvertRGBA4444ToRGBA8888(dst, src16, width); - break; - - case GE_FORMAT_8888: - memcpy(dst, src32, 4 * width); - break; - - case GE_FORMAT_INVALID: - _dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels()."); - break; - } - } - }; - - // Hot Shot Golf (#12355) does tons of these in a frame in some situations! So actually, - // we do use an allocator. In fact, I've now banned allocator-less textures. - - Draw::TextureDesc desc{ - Draw::TextureType::LINEAR2D, - Draw::DataFormat::R8G8B8A8_UNORM, - width, - height, - 1, - 1, - false, - "DrawPixels", - { (uint8_t *)srcPixels }, - generateTexture, - }; - // TODO: Use allocator_ somehow? - Draw::Texture *tex = draw_->CreateTexture(desc); - if (!tex) - ERROR_LOG(G3D, "Failed to create drawpixels texture"); - return tex; -} - void FramebufferManagerVulkan::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { float texCoords[8] = { u0,v0, diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 45f8c305e2..0a357d970a 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -78,9 +78,6 @@ protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; private: - // The returned texture does not need to be free'd, might be returned from a pool (currently single entry) - Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) override; - void InitDeviceObjects(); void DestroyDeviceObjects(); diff --git a/GPU/Vulkan/StencilBufferVulkan.cpp b/GPU/Vulkan/StencilBufferVulkan.cpp index 76a79d692b..a99480d497 100644 --- a/GPU/Vulkan/StencilBufferVulkan.cpp +++ b/GPU/Vulkan/StencilBufferVulkan.cpp @@ -164,6 +164,9 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip float u1 = 1.0f; float v1 = 1.0f; Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); + if (!tex) + return false; + if (dstBuffer->fbo) { draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } else {