diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5a1256f2e5..5f65627574 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -442,7 +442,7 @@ void TextureCacheCommon::Decimate() { for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ) { // In low memory mode, we kill them all. if (lowMemoryMode_ || iter->second->lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { - ReleaseTexture(iter->second.get()); + ReleaseTexture(iter->second.get(), true); secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(iter->second.get()); secondCache_.erase(iter++); } else { @@ -482,7 +482,7 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c replaceImages = true; } else { InvalidateLastTexture(entry); - ReleaseTexture(entry); + ReleaseTexture(entry, true); entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; } } @@ -1411,13 +1411,11 @@ void TextureCacheCommon::ApplyTexture() { void TextureCacheCommon::Clear(bool delete_them) { ForgetLastTexture(); - if (delete_them) { - for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { - ReleaseTexture(iter->second.get()); - } - for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ++iter) { - ReleaseTexture(iter->second.get()); - } + for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { + ReleaseTexture(iter->second.get(), delete_them); + } + for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ++iter) { + ReleaseTexture(iter->second.get(), delete_them); } if (cache_.size() + secondCache_.size()) { INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache_.size() + secondCache_.size())); @@ -1431,7 +1429,7 @@ void TextureCacheCommon::Clear(bool delete_them) { } void TextureCacheCommon::DeleteTexture(TexCache::iterator it) { - ReleaseTexture(it->second.get()); + ReleaseTexture(it->second.get(), true); auto fbInfo = fbTexInfo_.find(it->first); if (fbInfo != fbTexInfo_.end()) { fbTexInfo_.erase(fbInfo); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 1443338f41..160301c3bf 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -209,7 +209,7 @@ public: protected: virtual void BindTexture(TexCacheEntry *entry) = 0; virtual void Unbind() = 0; - virtual void ReleaseTexture(TexCacheEntry *entry) = 0; + virtual void ReleaseTexture(TexCacheEntry *entry, bool delete_them) = 0; void DeleteTexture(TexCache::iterator it); void Decimate(); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index f0f605abe5..eabee0b7f5 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -145,6 +145,9 @@ void DrawEngineD3D11::DestroyDeviceObjects() { for (auto &blend : blendCache_) { blend.second->Release(); } + for (auto &blend1 : blendCache1_) { + blend1.second->Release(); + } for (auto &raster : rasterCache_) { raster.second->Release(); } diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 25015fb0a1..40aeeb74c7 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -1050,7 +1050,11 @@ bool FramebufferManagerD3D11::GetDepthStencilBuffer(VirtualFramebuffer *vfb, GPU Draw::Framebuffer *fboForRead = nullptr; fboForRead = vfb->fbo; - buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, !useBufferedRendering_); + if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, !useBufferedRendering_); + } else { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, !useBufferedRendering_); + } ID3D11Texture2D *packTex; D3D11_TEXTURE2D_DESC packDesc{}; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index f72b6d3d68..41565c409c 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -503,7 +503,6 @@ void GPU_D3D11::CheckGPUFeatures() { u32 features = 0; features |= GPU_SUPPORTS_BLEND_MINMAX; - features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; features |= GPU_PREFER_CPU_DOWNLOAD; features |= GPU_SUPPORTS_ACCURATE_DEPTH; // Breaks text in PaRappa for some reason. features |= GPU_SUPPORTS_ANISOTROPY; @@ -511,6 +510,10 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_LARGE_VIEWPORTS; features |= GPU_SUPPORTS_DUALSOURCE_BLEND; features |= GPU_SUPPORTS_ANY_COPY_IMAGE; + features |= GPU_SUPPORTS_TEXTURE_FLOAT; + features |= GPU_SUPPORTS_INSTANCE_RENDERING; + features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; + features |= GPU_SUPPORTS_FBO; uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::A4R4G4B4_UNORM_PACK16); uint32_t fmt1555 = draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16); @@ -523,15 +526,20 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_LOGIC_OP; } - if (!g_Config.bHighQualityDepth) { + if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - // Assume we always have a 24-bit depth buffer. - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + // Use fragment rounding on desktop and GLES3, most accurate. + features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { features |= GPU_ROUND_DEPTH_TO_16BIT; } + // The Phantasy Star hack :( + if (PSP_CoreParameter().compat.flags().DepthRangeHack && (features & GPU_SUPPORTS_ACCURATE_DEPTH) == 0) { + features |= GPU_USE_DEPTH_RANGE_HACK; + } + if (PSP_CoreParameter().compat.flags().ClearToRAM) { features |= GPU_USE_CLEAR_RAM_HACK; } diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 8ff98cc33f..5db3bc1f3b 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -120,7 +120,7 @@ void TextureCacheD3D11::SetFramebufferManager(FramebufferManagerD3D11 *fbManager framebufferManager_ = fbManager; } -void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry) { +void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { ID3D11Texture2D *texture = (ID3D11Texture2D *)entry->texturePtr; ID3D11ShaderResourceView *view = (ID3D11ShaderResourceView *)entry->textureView; if (texture) { @@ -496,7 +496,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. - ReleaseTexture(entry); + ReleaseTexture(entry, true); replaceImages = false; } // We're replacing, so we won't scale. @@ -671,7 +671,7 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & HRESULT hr = device_->CreateTexture2D(&desc, nullptr, &texture); if (FAILED(hr)) { INFO_LOG(G3D, "Failed to create D3D texture"); - ReleaseTexture(&entry); + ReleaseTexture(&entry, true); return; } ID3D11ShaderResourceView *view; diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index e9e4b0ed58..d4232e20c6 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -67,7 +67,7 @@ public: protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; - void ReleaseTexture(TexCacheEntry *entry) override; + void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); diff --git a/GPU/Directx9/PixelShaderGeneratorDX9.cpp b/GPU/Directx9/PixelShaderGeneratorDX9.cpp index acbcd81885..a90bfa3872 100644 --- a/GPU/Directx9/PixelShaderGeneratorDX9.cpp +++ b/GPU/Directx9/PixelShaderGeneratorDX9.cpp @@ -142,7 +142,7 @@ bool GenerateFragmentShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage if (enableFog) { WRITE(p, " float v_fogdepth: TEXCOORD1;\n"); } - if (lang == HLSL_D3D11 && replaceBlend == REPLACE_BLEND_COPY_FBO) { + if (lang == HLSL_D3D11 && ((replaceBlend == REPLACE_BLEND_COPY_FBO) || gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT))) { WRITE(p, " float4 pixelPos : SV_POSITION;\n"); } WRITE(p, "};\n"); @@ -152,11 +152,14 @@ bool GenerateFragmentShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage } else { WRITE(p, "struct PS_OUT {\n"); if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE) { - WRITE(p, " float4 target : SV_Target0;\n"); - WRITE(p, " float4 target1 : SV_Target1;\n"); + WRITE(p, " float4 target : SV_Target0;\n"); + WRITE(p, " float4 target1 : SV_Target1;\n"); } else { - WRITE(p, " float4 target : SV_Target;\n"); + WRITE(p, " float4 target : SV_Target;\n"); + } + if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { + WRITE(p, " float depth : SV_DEPTH;\n"); } WRITE(p, "};\n"); WRITE(p, "PS_OUT main( PS_IN In ) {\n"); @@ -492,6 +495,24 @@ bool GenerateFragmentShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage break; } + if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { + const double scale = DepthSliceFactor() * 65535.0; + + WRITE(p, " float z = In.pixelPos.z;\n"); + if (gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) { + // We center the depth with an offset, but only its fraction matters. + // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. + if (((int)(DepthSliceFactor() - 1.0f) & 1) == 1) { + WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); + } else { + WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); + } + } else { + WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); + } + WRITE(p, " outfragment.depth = z;\n"); + } + if (lang == HLSL_D3D11) { if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE) { WRITE(p, " outfragment.target = float4(v.rgb, %s);\n", replacedAlpha.c_str()); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 0f44224727..a02bb1789e 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -84,7 +84,7 @@ void TextureCacheDX9::SetFramebufferManager(FramebufferManagerDX9 *fbManager) { framebufferManager_ = fbManager; } -void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry) { +void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { DEBUG_LOG(G3D, "Deleting texture %p", entry->texturePtr); LPDIRECT3DTEXTURE9 &texture = DxTex(entry); if (texture) { @@ -520,7 +520,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. - ReleaseTexture(entry); + ReleaseTexture(entry, true); replaceImages = false; } // We're replacing, so we won't scale. @@ -675,7 +675,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re hr = pD3Ddevice->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL); if (FAILED(hr)) { INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th); - ReleaseTexture(&entry); + ReleaseTexture(&entry, true); return; } } diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 714b467315..c448a97606 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -61,7 +61,7 @@ public: protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; - void ReleaseTexture(TexCacheEntry *entry) override; + void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: void UpdateSamplingParams(TexCacheEntry &entry, bool force); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 0d9ec77cbd..b5c2c64e16 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -69,9 +69,10 @@ void TextureCacheGLES::SetFramebufferManager(FramebufferManagerGLES *fbManager) framebufferManager_ = fbManager; } -void TextureCacheGLES::ReleaseTexture(TexCacheEntry *entry) { +void TextureCacheGLES::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { DEBUG_LOG(G3D, "Deleting texture %i", entry->textureName); - glDeleteTextures(1, &entry->textureName); + if (delete_them) + glDeleteTextures(1, &entry->textureName); entry->textureName = 0; } diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 6b41125420..ff9932936d 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -80,7 +80,7 @@ public: protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; - void ReleaseTexture(TexCacheEntry *entry) override; + void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: void UpdateSamplingParams(TexCacheEntry &entry, bool force); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 36d3041195..d4a5d8b7de 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -179,7 +179,7 @@ void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan) { samplerCache_.DeviceRestore(vulkan); } -void TextureCacheVulkan::ReleaseTexture(TexCacheEntry *entry) { +void TextureCacheVulkan::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { DEBUG_LOG(G3D, "Deleting texture %p", entry->vkTex); delete entry->vkTex; entry->vkTex = nullptr; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index d720b20be3..46bde17c52 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -103,7 +103,7 @@ public: protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; - void ReleaseTexture(TexCacheEntry *entry) override; + void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key);