diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 443367b1aa..378829f578 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -131,7 +131,6 @@ public: stencilDirty_ = true; } - void EndFrame() override; void Draw(int vertexCount, int offset) override; void DrawIndexed(int vertexCount, int offset) override; @@ -139,6 +138,9 @@ public: void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; void BeginFrame() override; + void EndFrame() override; + + int GetFrameCount() override { return frameCount_; } std::string GetInfoString(InfoField info) const override { switch (info) { @@ -221,6 +223,7 @@ private: int nextIndexBufferOffset_ = 0; InvalidationCallback invalidationCallback_; + int frameCount_ = 0; // Dynamic state float blendFactor_[4]{}; @@ -423,6 +426,7 @@ void D3D11DrawContext::HandleEvent(Event ev, int width, int height, void *param1 void D3D11DrawContext::EndFrame() { curPipeline_ = nullptr; + frameCount_++; } void D3D11DrawContext::SetViewport(const Viewport &viewport) { diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 5389eac6fe..a05057d8a1 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -580,6 +580,7 @@ public: } void EndFrame() override; + int GetFrameCount() override { return frameCount_; } void UpdateDynamicUniformBuffer(const void *ub, size_t size) override; @@ -640,6 +641,7 @@ private: D3DCAPS9 d3dCaps_; char shadeLangVersion_[64]{}; DeviceCaps caps_{}; + int frameCount_ = 0; // Bound state AutoRef curPipeline_; @@ -964,6 +966,7 @@ void D3D9Context::BindNativeTexture(int index, void *nativeTexture) { void D3D9Context::EndFrame() { curPipeline_ = nullptr; + frameCount_++; } static void SemanticToD3D9UsageAndIndex(int semantic, BYTE *usage, BYTE *index) { diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 3f29d54207..2b39a83f22 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -370,6 +370,10 @@ public: void BeginFrame() override; void EndFrame() override; + int GetFrameCount() override { + return frameCount_; + } + void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override; @@ -492,6 +496,7 @@ private: void ApplySamplers(); GLRenderManager renderManager_; + int frameCount_ = 0; DeviceCaps caps_{}; @@ -795,6 +800,7 @@ void OpenGLContext::EndFrame() { renderManager_.Finish(); Invalidate(InvalidationFlags::CACHED_RENDER_STATE); + frameCount_++; } void OpenGLContext::Invalidate(InvalidationFlags flags) { diff --git a/Common/GPU/Vulkan/VulkanDebug.cpp b/Common/GPU/Vulkan/VulkanDebug.cpp index e5a045e05b..b91e0bb9bb 100644 --- a/Common/GPU/Vulkan/VulkanDebug.cpp +++ b/Common/GPU/Vulkan/VulkanDebug.cpp @@ -53,8 +53,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( return false; case 1303270965: // Benign perf warning, image blit using GENERAL layout. - // UNASSIGNED - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) + // TODO: Oops, turns out we filtered out a bit too much here! + // We really need that performance flag check to sort out the stuff that matters. + // Will enable it soon, but it'll take some fixing. + // + //if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) return false; break; @@ -79,6 +82,14 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( // Extended validation (ARM best practices) // Non-fifo validation not recommended return false; + case -564812795: + case 369680064: + case 307231540: + case 618171435: // SHADER_ACCESS_READ + case 1774732925: // same but different + case -1539028524: // image layout in draw + // wip + return false; default: break; } diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index e535a10a99..f33e34ec06 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -484,6 +484,10 @@ public: void EndFrame() override; void WipeQueue() override; + int GetFrameCount() override { + return frameCount_; + } + void FlushState() override {} void ResetStats() override { @@ -528,6 +532,7 @@ private: VulkanTexture *GetNullTexture(); VulkanContext *vulkan_ = nullptr; + int frameCount_ = 0; VulkanRenderManager renderManager_; VulkanTexture *nullTexture_ = nullptr; @@ -1105,6 +1110,8 @@ void VKContext::EndFrame() { // Unbind stuff, to avoid accidentally relying on it across frames (and provide some protection against forgotten unbinds of deleted things). Invalidate(InvalidationFlags::CACHED_RENDER_STATE); + + frameCount_++; } void VKContext::Invalidate(InvalidationFlags flags) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 77b5582479..b90e638117 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -841,6 +841,10 @@ public: // Not very elegant, but more elegant than the old passId hack. virtual void SetInvalidationCallback(InvalidationCallback callback) = 0; + // Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.numFlips + virtual int GetFrameCount() = 0; + virtual int GetFramesInFlight() { return 3; } + protected: ShaderModule *vsPresets_[VS_MAX_PRESET]; ShaderModule *fsPresets_[FS_MAX_PRESET]; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 914d6780f8..1e1fa344a5 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1402,16 +1402,19 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G Draw::DataFormat texFormat = srcPixelFormat == GE_FORMAT_DEPTH16 ? depthFormat : preferredPixelsFormat_; + int frameNumber = draw_->GetFrameCount(); + // Look for a matching texture we can re-use. for (auto &iter : drawPixelsCache_) { - if (iter.frameNumber > gpuStats.numFlips - 3 || iter.tex->Width() != width || iter.tex->Height() != height || iter.tex->Format() != texFormat) { + if (iter.frameNumber >= frameNumber - 3 || iter.tex->Width() != width || iter.tex->Height() != height || iter.tex->Format() != texFormat) { continue; } // OK, current one seems good, let's use it (and mark it used). gpuStats.numDrawPixels++; draw_->UpdateTextureLevels(iter.tex, &srcPixels, generateTexture, 1); - iter.frameNumber = gpuStats.numFlips; + // NOTE: numFlips is no good - this is called every frame when paused sometimes! + iter.frameNumber = frameNumber; return iter.tex; } @@ -1442,7 +1445,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G INFO_LOG(G3D, "Creating drawPixelsCache texture: %dx%d", tex->Width(), tex->Height()); - DrawPixelsEntry entry{ tex, gpuStats.numFlips }; + DrawPixelsEntry entry{ tex, frameNumber }; drawPixelsCache_.push_back(entry); return tex; } @@ -1695,7 +1698,7 @@ void FramebufferManagerCommon::DecimateFBOs() { // And DrawPixels cached textures. for (auto it = drawPixelsCache_.begin(); it != drawPixelsCache_.end(); ) { - int age = gpuStats.numFlips - it->frameNumber; + int age = draw_->GetFrameCount() - it->frameNumber; if (age > 10) { INFO_LOG(G3D, "Releasing drawPixelsCache texture: %dx%d", it->tex->Width(), it->tex->Height()); it->tex->Release();