From 93f57a4f3829bf1e1b2f394e22794cf06e73433d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 29 Sep 2026 10:24:26 -0600 Subject: [PATCH] GPU: Delete copy operations on classes that own resources These own GPU objects, memory or refcounts in their destructors (or assert there that they were torn down), so a copy would double-free. Nothing copies them today; this keeps it that way. The manager base classes cover every backend's subclass. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/GPU/OpenGL/GLMemory.h | 2 ++ Common/GPU/OpenGL/GLRenderManager.h | 9 +++++++++ Common/GPU/Vulkan/VulkanBarrier.h | 2 ++ Common/GPU/Vulkan/VulkanDescSet.h | 2 ++ Common/GPU/Vulkan/VulkanFramebuffer.h | 2 ++ Common/GPU/Vulkan/VulkanImage.h | 2 ++ Common/GPU/Vulkan/VulkanRenderManager.h | 5 +++++ Common/Render/DrawBuffer.h | 2 ++ Common/Render/TextureAtlas.h | 6 ++++++ GPU/Common/DrawEngineCommon.h | 2 ++ GPU/Common/FramebufferManagerCommon.h | 2 ++ GPU/Common/PresentationCommon.h | 2 ++ GPU/Common/ReplacedTexture.h | 2 ++ GPU/Common/ShaderCommon.h | 2 ++ GPU/Common/TextureCacheCommon.h | 5 +++++ GPU/Common/TextureReplacer.h | 2 ++ GPU/GLES/ShaderManagerGLES.h | 4 ++++ GPU/GPUCommon.h | 2 ++ GPU/Software/BinManager.h | 4 ++++ GPU/Software/TransformUnit.h | 2 ++ GPU/Vulkan/PipelineManagerVulkan.h | 3 +++ GPU/Vulkan/ShaderManagerVulkan.h | 4 ++++ GPU/Vulkan/TextureCacheVulkan.h | 2 ++ 23 files changed, 70 insertions(+) diff --git a/Common/GPU/OpenGL/GLMemory.h b/Common/GPU/OpenGL/GLMemory.h index 3d7780f621..e5ba129a29 100644 --- a/Common/GPU/OpenGL/GLMemory.h +++ b/Common/GPU/OpenGL/GLMemory.h @@ -30,6 +30,8 @@ static inline int operator &(const GLBufferStrategy &lhs, const GLBufferStrategy class GLRBuffer { public: + GLRBuffer(const GLRBuffer &) = delete; + GLRBuffer &operator=(const GLRBuffer &) = delete; GLRBuffer(GLuint target, size_t size) : target_(target), size_((int)size) {} ~GLRBuffer() { if (buffer_) { diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 687307c67d..edfe69b373 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -30,6 +30,8 @@ constexpr int MAX_GL_TEXTURE_SLOTS = 8; class GLRTexture { public: + GLRTexture(const GLRTexture &) = delete; + GLRTexture &operator=(const GLRTexture &) = delete; GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips); ~GLRTexture(); @@ -53,6 +55,8 @@ public: class GLRFramebuffer { public: + GLRFramebuffer(const GLRFramebuffer &) = delete; + GLRFramebuffer &operator=(const GLRFramebuffer &) = delete; GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil, const char *tag) : color_texture(caps, _width, _height, 1, 1), z_stencil_texture(caps, _width, _height, 1, 1), width(_width), height(_height), z_stencil_(z_stencil) { @@ -83,6 +87,8 @@ private: class GLRShader { public: + GLRShader(const GLRShader &) = delete; + GLRShader &operator=(const GLRShader &) = delete; explicit GLRShader(std::string_view _desc) : desc(_desc) {} ~GLRShader() { if (shader) { @@ -116,6 +122,9 @@ public: class GLRProgram { public: + GLRProgram() = default; + GLRProgram(const GLRProgram &) = delete; + GLRProgram &operator=(const GLRProgram &) = delete; ~GLRProgram() { if (deleteCallback_) { deleteCallback_(deleteParam_); diff --git a/Common/GPU/Vulkan/VulkanBarrier.h b/Common/GPU/Vulkan/VulkanBarrier.h index e41df8f9b1..734fc77f81 100644 --- a/Common/GPU/Vulkan/VulkanBarrier.h +++ b/Common/GPU/Vulkan/VulkanBarrier.h @@ -12,6 +12,8 @@ struct VKRImage; class VulkanBarrierBatch { public: + VulkanBarrierBatch(const VulkanBarrierBatch &) = delete; + VulkanBarrierBatch &operator=(const VulkanBarrierBatch &) = delete; VulkanBarrierBatch() : imageBarriers_(4) {} ~VulkanBarrierBatch(); diff --git a/Common/GPU/Vulkan/VulkanDescSet.h b/Common/GPU/Vulkan/VulkanDescSet.h index 5123ba3460..17833db7c6 100644 --- a/Common/GPU/Vulkan/VulkanDescSet.h +++ b/Common/GPU/Vulkan/VulkanDescSet.h @@ -18,6 +18,8 @@ enum class BindingType { // Only appropriate for use in a per-frame pool. class VulkanDescSetPool { public: + VulkanDescSetPool(const VulkanDescSetPool &) = delete; + VulkanDescSetPool &operator=(const VulkanDescSetPool &) = delete; VulkanDescSetPool(const char *tag, bool grow = true) : tag_(tag), grow_(grow) {} ~VulkanDescSetPool(); diff --git a/Common/GPU/Vulkan/VulkanFramebuffer.h b/Common/GPU/Vulkan/VulkanFramebuffer.h index 0b686b3929..291609c06c 100644 --- a/Common/GPU/Vulkan/VulkanFramebuffer.h +++ b/Common/GPU/Vulkan/VulkanFramebuffer.h @@ -60,6 +60,8 @@ struct VKRImage { class VKRFramebuffer { public: + VKRFramebuffer(const VKRFramebuffer &) = delete; + VKRFramebuffer &operator=(const VKRFramebuffer &) = delete; VKRFramebuffer(VulkanContext *vk, VulkanBarrierBatch *barriers, int _width, int _height, int _numLayers, int _multiSampleLevel, bool createDepthStencilBuffer, const char *tag); ~VKRFramebuffer(); diff --git a/Common/GPU/Vulkan/VulkanImage.h b/Common/GPU/Vulkan/VulkanImage.h index e087a8a1c1..d6a53ec11a 100644 --- a/Common/GPU/Vulkan/VulkanImage.h +++ b/Common/GPU/Vulkan/VulkanImage.h @@ -22,6 +22,8 @@ struct TextureCopyBatch { // ALWAYS use an allocator when calling CreateDirect. class VulkanTexture { public: + VulkanTexture(const VulkanTexture &) = delete; + VulkanTexture &operator=(const VulkanTexture &) = delete; VulkanTexture(VulkanContext *vulkan, const char *tag); ~VulkanTexture() { Destroy(); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 8f4b7b0d0f..42bb5f2dd7 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -115,6 +115,8 @@ public: // Wrapped pipeline. Does own desc! struct VKRGraphicsPipeline { + VKRGraphicsPipeline(const VKRGraphicsPipeline &) = delete; + VKRGraphicsPipeline &operator=(const VKRGraphicsPipeline &) = delete; VKRGraphicsPipeline(PipelineFlags flags, const char *tag) : flags_(flags), tag_(tag) {} ~VKRGraphicsPipeline(); @@ -195,6 +197,9 @@ static_assert(sizeof(PackedDescriptor::buffer) == 16, "PackedDescriptor should b // Note that we only support a single descriptor set due to compatibility with some ancient devices. // We should probably eventually give that up eventually. struct VKRPipelineLayout { + VKRPipelineLayout() = default; + VKRPipelineLayout(const VKRPipelineLayout &) = delete; + VKRPipelineLayout &operator=(const VKRPipelineLayout &) = delete; ~VKRPipelineLayout(); enum { MAX_DESC_SET_BINDINGS = 5 }; diff --git a/Common/Render/DrawBuffer.h b/Common/Render/DrawBuffer.h index 94e5e56095..f5c9b90e60 100644 --- a/Common/Render/DrawBuffer.h +++ b/Common/Render/DrawBuffer.h @@ -51,6 +51,8 @@ class TextDrawer; class DrawBuffer { public: + DrawBuffer(const DrawBuffer &) = delete; + DrawBuffer &operator=(const DrawBuffer &) = delete; DrawBuffer(); ~DrawBuffer(); diff --git a/Common/Render/TextureAtlas.h b/Common/Render/TextureAtlas.h index 493a73c3ba..15ae9e0fb3 100644 --- a/Common/Render/TextureAtlas.h +++ b/Common/Render/TextureAtlas.h @@ -96,6 +96,9 @@ struct AtlasFontHeader { }; struct AtlasFont { + AtlasFont() = default; + AtlasFont(const AtlasFont &) = delete; + AtlasFont &operator=(const AtlasFont &) = delete; ~AtlasFont(); float padding; @@ -126,6 +129,9 @@ struct AtlasHeader { }; struct Atlas { + Atlas() = default; + Atlas(const Atlas &) = delete; + Atlas &operator=(const Atlas &) = delete; ~Atlas(); bool LoadMeta(const uint8_t *data, size_t data_size); bool IsMetadataLoaded() const { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 0333809963..fee97a90b6 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -73,6 +73,8 @@ struct alignas(16) Plane8 { class DrawEngineCommon { public: + DrawEngineCommon(const DrawEngineCommon &) = delete; + DrawEngineCommon &operator=(const DrawEngineCommon &) = delete; DrawEngineCommon(); virtual ~DrawEngineCommon(); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 365d4d050e..bfe5db0d47 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -291,6 +291,8 @@ struct DisplayLayoutConfig; class FramebufferManagerCommon { public: + FramebufferManagerCommon(const FramebufferManagerCommon &) = delete; + FramebufferManagerCommon &operator=(const FramebufferManagerCommon &) = delete; FramebufferManagerCommon(Draw::DrawContext *draw); virtual ~FramebufferManagerCommon(); diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index abdab8f032..eb6caf1969 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -80,6 +80,8 @@ ENUM_CLASS_BITOPS(OutputFlags); class PresentationCommon { public: + PresentationCommon(const PresentationCommon &) = delete; + PresentationCommon &operator=(const PresentationCommon &) = delete; PresentationCommon(Draw::DrawContext *draw); ~PresentationCommon(); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 6ff33d7367..17817f77f8 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -140,6 +140,8 @@ struct ReplacedTextureLevel { class ReplacedTexture { public: + ReplacedTexture(const ReplacedTexture &) = delete; + ReplacedTexture &operator=(const ReplacedTexture &) = delete; ReplacedTexture(VFSBackend *vfs, const ReplacementDesc &desc); ~ReplacedTexture(); diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 6e31d9dfaa..56f449179a 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -123,6 +123,8 @@ enum : uint64_t { class ShaderManagerCommon { public: + ShaderManagerCommon(const ShaderManagerCommon &) = delete; + ShaderManagerCommon &operator=(const ShaderManagerCommon &) = delete; ShaderManagerCommon(Draw::DrawContext *draw) : draw_(draw) {} virtual ~ShaderManagerCommon() {} diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 22fa4e7517..30549035c1 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -160,6 +160,9 @@ ENUM_CLASS_BITOPS(TexStatus); // TODO: Shrink this struct. There is some fluff. struct TexCacheEntry { + TexCacheEntry() = default; + TexCacheEntry(const TexCacheEntry &) = delete; + TexCacheEntry &operator=(const TexCacheEntry &) = delete; ~TexCacheEntry() { #ifdef _DEBUG if (texturePtr || textureName || vkTex) @@ -338,6 +341,8 @@ struct TextureApplyResult { class TextureCacheCommon { public: + TextureCacheCommon(const TextureCacheCommon &) = delete; + TextureCacheCommon &operator=(const TextureCacheCommon &) = delete; TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D); virtual ~TextureCacheCommon(); diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 833d21cd96..210221562e 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -76,6 +76,8 @@ enum class ReplacerDecimateMode { class TextureReplacer { public: + TextureReplacer(const TextureReplacer &) = delete; + TextureReplacer &operator=(const TextureReplacer &) = delete; // The draw context is checked for supported texture formats. TextureReplacer(Draw::DrawContext *draw); ~TextureReplacer(); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index a0f519de3e..2f79093711 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -37,6 +37,8 @@ class IOFile; class LinkedShader { public: + LinkedShader(const LinkedShader &) = delete; + LinkedShader &operator=(const LinkedShader &) = delete; LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, FShaderID FSID, Shader *fs, bool useHWTransform, bool preloading = false); ~LinkedShader(); @@ -139,6 +141,8 @@ struct ShaderDescGLES { class Shader { public: + Shader(const Shader &) = delete; + Shader &operator=(const Shader &) = delete; Shader(GLRenderManager *render, const char *code, const std::string &desc, const ShaderDescGLES ¶ms); ~Shader(); GLRShader *shader; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index a295a970c3..5cca5d9433 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -56,6 +56,8 @@ inline bool IsTrianglePrim(GEPrimitiveType prim) { struct TransformStats; class GPUCommon { public: + GPUCommon(const GPUCommon &) = delete; + GPUCommon &operator=(const GPUCommon &) = delete; // The constructor might run on the loader thread. GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); virtual ~GPUCommon() = default; diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h index c2b2a7bfdd..8f453251a4 100644 --- a/GPU/Software/BinManager.h +++ b/GPU/Software/BinManager.h @@ -57,6 +57,8 @@ struct BinItem { template struct BinQueue { + BinQueue(const BinQueue &) = delete; + BinQueue &operator=(const BinQueue &) = delete; BinQueue() { Reset(); } @@ -185,6 +187,8 @@ struct BinDirtyRange { class StringWriter; class BinManager { public: + BinManager(const BinManager &) = delete; + BinManager &operator=(const BinManager &) = delete; BinManager(); ~BinManager(); diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 17fc2053f4..d0e2a5bb78 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -111,6 +111,8 @@ class StringWriter; class TransformUnit { public: + TransformUnit(const TransformUnit &) = delete; + TransformUnit &operator=(const TransformUnit &) = delete; TransformUnit(); ~TransformUnit(); diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index bd05b9b243..a722fd8b29 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -63,6 +63,9 @@ private: // Simply wraps a Vulkan pipeline, providing some metadata. struct VulkanPipeline { + VulkanPipeline() = default; + VulkanPipeline(const VulkanPipeline &) = delete; + VulkanPipeline &operator=(const VulkanPipeline &) = delete; ~VulkanPipeline() { desc->Release(); } diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 3ba870b94d..86848b60ad 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -40,6 +40,8 @@ class VulkanPushPool; class VulkanFragmentShader { public: + VulkanFragmentShader(const VulkanFragmentShader &) = delete; + VulkanFragmentShader &operator=(const VulkanFragmentShader &) = delete; VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, FragmentShaderFlags flags, const char *code, SPIRVCache *cache); ~VulkanFragmentShader(); @@ -63,6 +65,8 @@ protected: class VulkanVertexShader { public: + VulkanVertexShader(const VulkanVertexShader &) = delete; + VulkanVertexShader &operator=(const VulkanVertexShader &) = delete; VulkanVertexShader(VulkanContext *vulkan, VShaderID id, VertexShaderFlags flags, const char *code, bool useHWTransform, SPIRVCache *cache); ~VulkanVertexShader(); diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 72b15b585f..0a95a74d53 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -37,6 +37,8 @@ class StringWriter; class SamplerCache { public: + SamplerCache(const SamplerCache &) = delete; + SamplerCache &operator=(const SamplerCache &) = delete; SamplerCache(VulkanContext *vulkan) : vulkan_(vulkan), cache_(16) {} ~SamplerCache(); VkSampler GetOrCreateSampler(const SamplerCacheKey &key);