From b91ad1d2d73a12a66b7c0b2f69b40835ee10147f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 10:55:26 +0200 Subject: [PATCH 1/6] Remove optimization in BlitUsingRaster that shouldn't have been there (redundant, lacked feature check) --- GPU/Common/FramebufferManagerCommon.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 0a5675c298..d0959d51fc 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -694,11 +694,11 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage; + // Copy image required for now, might get rid of this later. bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && - (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx); - // Copy image required for now. - if (!draw_->GetDeviceCaps().framebufferCopySupported) - doReinterpret = false; + (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) && + draw_->GetDeviceCaps().framebufferCopySupported; + if (!doReinterpret) { // Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil. if (oldFormat == GE_FORMAT_565) { @@ -2667,12 +2667,6 @@ void FramebufferManagerCommon::BlitUsingRaster( draw_->GetFramebufferDimensions(src, &srcW, &srcH); draw_->GetFramebufferDimensions(dest, &destW, &destH); - if (srcW == destW && srcH == destH && destX2 - destX1 == srcX2 - srcX1 && destY2 - destY1 == srcY2 - srcY1) { - // Optimize to a copy - draw_->CopyFramebufferImage(src, 0, (int)srcX1, (int)srcY1, 0, dest, 0, (int)destX1, (int)destY1, 0, (int)(srcX2 - srcX1), (int)(srcY2 - srcY1), 1, Draw::FB_COLOR_BIT, "BlitUsingRaster"); - return; - } - float dX = 1.0f / (float)destW; float dY = 1.0f / (float)destH; float sX = 1.0f / (float)srcW; From 6f1f482432bb4e641652ed132e43f3a0610ad0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 11:09:34 +0200 Subject: [PATCH 2/6] Make GLQueueRunner/RenderManager aware of device caps, use it to check for NPOT and some other stuff --- Common/GPU/D3D11/thin3d_d3d11.cpp | 1 + Common/GPU/OpenGL/GLQueueRunner.cpp | 10 ++++------ Common/GPU/OpenGL/GLQueueRunner.h | 16 ++++++++-------- Common/GPU/OpenGL/GLRenderManager.cpp | 11 ++--------- Common/GPU/OpenGL/GLRenderManager.h | 19 +++++++++++-------- Common/GPU/OpenGL/thin3d_gl.cpp | 4 ++++ Common/GPU/Vulkan/VulkanRenderManager.h | 2 -- Common/GPU/thin3d.h | 1 + GPU/Common/TextureCacheCommon.cpp | 1 + GPU/GLES/GPU_GLES.cpp | 10 ++++++---- GPU/Vulkan/GPU_Vulkan.cpp | 2 +- 11 files changed, 39 insertions(+), 38 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index f2427de09b..9b34826230 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -267,6 +267,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.framebufferSeparateDepthCopySupported = false; // Though could be emulated with a draw. caps_.texture3DSupported = true; caps_.fragmentShaderInt32Supported = true; + caps_.anisoSupported = true; D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options)); diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 1fa4cc79a3..08468636a8 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -43,7 +43,7 @@ GLuint g_defaultFBO = 0; void GLQueueRunner::CreateDeviceObjects() { CHECK_GL_ERROR_IF_DEBUG(); - if (gl_extensions.EXT_texture_filter_anisotropic) { + if (caps_.anisoSupported) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_); } else { maxAnisotropyLevel_ = 0.0f; @@ -208,7 +208,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski #if !defined(USING_GLES2) if (step.create_program.support_dual_source) { - _dbg_assert_msg_(gl_extensions.ARB_blend_func_extended, "ARB_blend_func_extended required for dual src"); + _dbg_assert_msg_(caps_.dualSourceBlend, "ARB/EXT_blend_func_extended required for dual src blend"); // Dual source alpha glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0"); glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1"); @@ -1341,16 +1341,14 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { _dbg_assert_(srcTex); _dbg_assert_(dstTex); + _assert_msg_(caps_.framebufferCopySupported, "Image copy extension expected"); + #if defined(USING_GLES2) -#if !PPSSPP_PLATFORM(IOS) - _assert_msg_(gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image, "Image copy extension expected"); glCopyImageSubDataOES( srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ, srcRect.w, srcRect.h, depth); -#endif #else - _assert_msg_(gl_extensions.ARB_copy_image || gl_extensions.NV_copy_image, "Image copy extension expected"); if (gl_extensions.ARB_copy_image) { glCopyImageSubData( srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index c6173195dd..13c5cfd701 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -7,8 +7,10 @@ #include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GPU/DataFormat.h" #include "Common/GPU/Shader.h" +#include "Common/GPU/thin3d.h" #include "Common/Data/Collections/TinySet.h" + struct GLRViewport { float x, y, w, h, minZ, maxZ; }; @@ -350,6 +352,10 @@ public: errorCallbackUserData_ = userdata; } + void SetDeviceCaps(const Draw::DeviceCaps &caps) { + caps_ = caps; + } + void RunInitSteps(const std::vector &steps, bool skipGLCalls); void RunSteps(const std::vector &steps, bool skipGLCalls); @@ -388,14 +394,6 @@ private: void PerformReadback(const GLRStep &pass); void PerformReadbackImage(const GLRStep &pass); - void LogRenderPass(const GLRStep &pass); - void LogCopy(const GLRStep &pass); - void LogBlit(const GLRStep &pass); - void LogReadback(const GLRStep &pass); - void LogReadbackImage(const GLRStep &pass); - - void ResizeReadbackBuffer(size_t requiredSize); - void fbo_ext_create(const GLRInitStep &step); void fbo_bind_fb_target(bool read, GLuint name); GLenum fbo_get_fb_target(bool read, GLuint **cached); @@ -405,6 +403,8 @@ private: GLuint globalVAO_ = 0; + Draw::DeviceCaps caps_{}; // For sanity checks. + int curFBWidth_ = 0; int curFBHeight_ = 0; int targetWidth_ = 0; diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index fa61548a25..172511333f 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -26,9 +26,8 @@ static bool OnRenderThread() { } #endif -GLRTexture::GLRTexture(int width, int height, int depth, int numMips) { - // Should move this check to thin3d, but really only OpenGL cares, so... - if (gl_extensions.IsCoreContext || gl_extensions.GLES3 || gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot) { +GLRTexture::GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips) { + if (caps.textureNPOTFullySupported) { canWrap = true; } else { canWrap = isPowerOf2(width) && isPowerOf2(height); @@ -116,12 +115,6 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) { framebuffers.clear(); } -GLRenderManager::GLRenderManager() { - for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { - - } -} - GLRenderManager::~GLRenderManager() { for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) { _assert_(frameData_[i].deleter.IsEmpty()); diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 31d16a2cae..9e4fafb50f 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -25,7 +25,7 @@ constexpr int MAX_GL_TEXTURE_SLOTS = 8; class GLRTexture { public: - GLRTexture(int width, int height, int depth, int numMips); + GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips); ~GLRTexture(); GLuint texture = 0; @@ -49,15 +49,13 @@ public: class GLRFramebuffer { public: - GLRFramebuffer(int _width, int _height, bool z_stencil) - : color_texture(_width, _height, 1, 1), z_stencil_texture(_width, _height, 1, 1), + GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil) + : color_texture(caps, _width, _height, 1, 1), z_stencil_texture(caps, _width, _height, 1, 1), width(_width), height(_height), z_stencil_(z_stencil) { } ~GLRFramebuffer(); - int numShadows = 1; // TODO: Support this. - GLuint handle = 0; GLRTexture color_texture; // Either z_stencil_texture, z_stencil_buffer, or (z_buffer and stencil_buffer) are set. @@ -360,12 +358,16 @@ public: // directly in the destructor. class GLRenderManager { public: - GLRenderManager(); + GLRenderManager() {} ~GLRenderManager(); void SetErrorCallback(ErrorCallbackFn callback, void *userdata) { queueRunner_.SetErrorCallback(callback, userdata); } + void SetDeviceCaps(const Draw::DeviceCaps &caps) { + queueRunner_.SetDeviceCaps(caps); + caps_ = caps; + } void ThreadStart(Draw::DrawContext *draw); void ThreadEnd(); @@ -388,7 +390,7 @@ public: // and then we'll also need formats and stuff. GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) { GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE }; - step.create_texture.texture = new GLRTexture(width, height, depth, numMips); + step.create_texture.texture = new GLRTexture(caps_, width, height, depth, numMips); step.create_texture.texture->target = target; initSteps_.push_back(step); return step.create_texture.texture; @@ -416,7 +418,7 @@ public: GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil) { GLRInitStep step{ GLRInitStepType::CREATE_FRAMEBUFFER }; - step.create_framebuffer.framebuffer = new GLRFramebuffer(width, height, z_stencil); + step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, width, height, z_stencil); initSteps_.push_back(step); return step.create_framebuffer.framebuffer; } @@ -1047,4 +1049,5 @@ private: #ifdef _DEBUG GLRProgram *curProgram_ = nullptr; #endif + Draw::DeviceCaps caps_{}; }; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index e9da2b2aa4..995c3f5295 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -541,6 +541,8 @@ OpenGLContext::OpenGLContext() { caps_.texture3DSupported = true; } + caps_.dualSourceBlend = gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended; + caps_.anisoSupported = gl_extensions.EXT_texture_filter_anisotropic; caps_.framebufferCopySupported = gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image || gl_extensions.ARB_copy_image; caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object || gl_extensions.GLES3; caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported; @@ -701,6 +703,8 @@ OpenGLContext::OpenGLContext() { shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM"; } } + + renderManager_.SetDeviceCaps(caps_); } OpenGLContext::~OpenGLContext() { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 3c9b350eef..7e805b26c7 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -45,8 +45,6 @@ public: VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VkRenderPass renderPass, int _width, int _height, const char *tag); ~VKRFramebuffer(); - int numShadows = 1; // TODO: Support this. - VkFramebuffer framebuf = VK_NULL_HANDLE; VKRImage color{}; VKRImage depth{}; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index bc409f5b4c..6099c198a3 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -540,6 +540,7 @@ struct DeviceCaps { bool framebufferFetchSupported; bool texture3DSupported; bool fragmentShaderInt32Supported; + bool textureNPOTFullySupported; std::string deviceName; // The device name to use when creating the thin3d context, to get the same one. }; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 215589b934..e6aeebf7f0 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1125,6 +1125,7 @@ void TextureCacheCommon::NotifyConfigChanged() { if (!gstate_c.Supports(GPU_SUPPORTS_TEXTURE_NPOT)) { // Reduce the scale factor to a power of two (e.g. 2 or 4) if textures must be a power of two. + // TODO: In addition we should probably remove these options from the UI in this case. while ((scaleFactor & (scaleFactor - 1)) != 0) { --scaleFactor; } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index a2420fe015..a18a9cb556 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -149,12 +149,14 @@ GPU_GLES::~GPU_GLES() { } // Take the raw GL extension and versioning data and turn into feature flags. +// TODO: This should use DrawContext::GetDeviceCaps() more and more, and eventually +// this can be shared between all the backends. void GPU_GLES::CheckGPUFeatures() { u32 features = 0; features |= GPU_SUPPORTS_16BIT_FORMATS; - if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) { + if (draw_->GetDeviceCaps().dualSourceBlend) { if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { features |= GPU_SUPPORTS_DUALSOURCE_BLEND; } @@ -170,19 +172,19 @@ void GPU_GLES::CheckGPUFeatures() { if ((gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA) || (gl_extensions.gpuVendor == GPU_VENDOR_AMD)) features |= GPU_PREFER_REVERSE_COLOR_ORDER; - if (gl_extensions.OES_texture_npot) + if (draw_->GetDeviceCaps().textureNPOTFullySupported) features |= GPU_SUPPORTS_TEXTURE_NPOT; if (gl_extensions.EXT_blend_minmax) features |= GPU_SUPPORTS_BLEND_MINMAX; - if (!gl_extensions.IsGLES) + if (draw_->GetDeviceCaps().logicOpSupported) features |= GPU_SUPPORTS_LOGIC_OP; if (gl_extensions.GLES3 || !gl_extensions.IsGLES) features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; - if (gl_extensions.EXT_texture_filter_anisotropic) + if (draw_->GetDeviceCaps().anisoSupported) features |= GPU_SUPPORTS_ANISOTROPY; bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index e84381a4fd..a421e209c3 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -258,7 +258,7 @@ void GPU_Vulkan::CheckGPUFeatures() { if (enabledFeatures.logicOp) { features |= GPU_SUPPORTS_LOGIC_OP; } - if (enabledFeatures.samplerAnisotropy) { + if (draw_->GetDeviceCaps().anisoSupported) { features |= GPU_SUPPORTS_ANISOTROPY; } From 4ff8f851102554d1d0ff95172f5ad75b08ab85b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 11:48:59 +0200 Subject: [PATCH 3/6] Forgot these... --- Common/GPU/D3D11/thin3d_d3d11.cpp | 1 + Common/GPU/D3D9/thin3d_d3d9.cpp | 1 + Common/GPU/OpenGL/thin3d_gl.cpp | 1 + Common/GPU/Vulkan/thin3d_vulkan.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 9b34826230..2448d8996e 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -268,6 +268,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.texture3DSupported = true; caps_.fragmentShaderInt32Supported = true; caps_.anisoSupported = true; + caps_.textureNPOTFullySupported = true; D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options)); diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 8c3607b670..10fa3beb44 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -668,6 +668,7 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID caps_.framebufferDepthCopySupported = false; caps_.framebufferSeparateDepthCopySupported = false; caps_.texture3DSupported = true; + caps_.textureNPOTFullySupported = true; if (d3d) { D3DDISPLAYMODE displayMode; diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 995c3f5295..128bc4fcce 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -555,6 +555,7 @@ OpenGLContext::OpenGLContext() { caps_.clipDistanceSupported = gl_extensions.VersionGEThan(3, 0); caps_.cullDistanceSupported = gl_extensions.ARB_cull_distance; } + caps_.textureNPOTFullySupported = gl_extensions.IsCoreContext || gl_extensions.GLES3 || gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot; // Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader): // This will induce a performance penalty on many architectures though so a blanket enable of this diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 33380676d0..c1d05acb38 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -792,6 +792,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan. caps_.texture3DSupported = true; caps_.fragmentShaderInt32Supported = true; + caps_.textureNPOTFullySupported = true; auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties; switch (deviceProps.vendorID) { From 1dabb54df5973f3c097f9fd25c8fd231bf5488b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 11:50:23 +0200 Subject: [PATCH 4/6] Improve the NPOT check --- Common/GPU/OpenGL/thin3d_gl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 128bc4fcce..7a17b3a036 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -555,7 +555,10 @@ OpenGLContext::OpenGLContext() { caps_.clipDistanceSupported = gl_extensions.VersionGEThan(3, 0); caps_.cullDistanceSupported = gl_extensions.ARB_cull_distance; } - caps_.textureNPOTFullySupported = gl_extensions.IsCoreContext || gl_extensions.GLES3 || gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot; + caps_.textureNPOTFullySupported = + (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(2, 0, 0)) || + gl_extensions.IsCoreContext || gl_extensions.GLES3 || + gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot; // Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader): // This will induce a performance penalty on many architectures though so a blanket enable of this From d61909ca9183ec0ad8a7ca5bee523fa4c8dab629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 12:02:06 +0200 Subject: [PATCH 5/6] More framebuffer blit fixes. --- GPU/Common/FramebufferManagerCommon.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index d0959d51fc..505006eff9 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2678,11 +2678,16 @@ void FramebufferManagerCommon::BlitUsingRaster( { -1.0f + 2.0f * dX * destX2, -(1.0f - 2.0f * dY * destY2), sX * srcX2, sY * srcY2 }, }; - // Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily). - draw_->BindTexture(0, nullptr); - draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitUsingRaster"); + if (dest != currentRenderVfb_->fbo) { + // Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily). + draw_->BindTexture(0, nullptr); + draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitUsingRaster"); + } draw_->BindFramebufferAsTexture(src, 0, Draw::FB_COLOR_BIT, 0); + Draw::Viewport vp{ 0.0f, 0.0f, (float)dest->Width(), (float)dest->Height(), 0.0f, 1.0f }; + draw_->SetViewports(1, &vp); + draw_->SetScissorRect(0, 0, (int)dest->Width(), (int)dest->Height()); DrawStrip2D(nullptr, vtx, 4, linearFilter); gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); From 5bf7b5630587b2a79488f4e78920097f1eb8d116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Aug 2022 12:04:41 +0200 Subject: [PATCH 6/6] Oops, this iOS check was still required. --- Common/GPU/OpenGL/GLQueueRunner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 08468636a8..7a9e29653e 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1344,10 +1344,12 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) { _assert_msg_(caps_.framebufferCopySupported, "Image copy extension expected"); #if defined(USING_GLES2) +#if !PPSSPP_PLATFORM(IOS) glCopyImageSubDataOES( srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ, dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ, srcRect.w, srcRect.h, depth); +#endif #else if (gl_extensions.ARB_copy_image) { glCopyImageSubData(