Merge pull request #2602 from mimimi085181/partial-texture-updates2
Support partial texture updates via efb copies
This commit is contained in:
commit
8493feb89f
|
@ -77,6 +77,13 @@ bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int l
|
|||
return saved_png;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::DoPartialTextureUpdate(TCacheEntryBase* entry_, u32 x, u32 y)
|
||||
{
|
||||
TCacheEntry* entry = (TCacheEntry*)entry_;
|
||||
|
||||
D3D::context->CopySubresourceRegion(texture->GetTex(), 0, x , y , 0, entry->texture->GetTex(), 0, NULL);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,8 @@ private:
|
|||
TCacheEntry(const TCacheEntryConfig& config, D3DTexture2D *_tex) : TCacheEntryBase(config), texture(_tex) {}
|
||||
~TCacheEntry();
|
||||
|
||||
void DoPartialTextureUpdate(TCacheEntryBase* entry, u32 x, u32 y) override;
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int levels) override;
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ void InitBackendInfo()
|
|||
g_Config.backend_info.bSupportsPostProcessing = false;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = true;
|
||||
g_Config.backend_info.bSupportsClipControl = false;
|
||||
g_Config.backend_info.bSupportsCopySubImage = true;
|
||||
|
||||
IDXGIFactory* factory;
|
||||
IDXGIAdapter* ad;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2015 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/OGL/GLExtensions/gl_common.h"
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
|
||||
|
||||
extern PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
|
||||
|
|
@ -788,6 +788,9 @@ PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
|
|||
// ARB_clip_control
|
||||
PFNGLCLIPCONTROLPROC glClipControl;
|
||||
|
||||
// ARB_copy_image
|
||||
PFNGLCOPYIMAGESUBDATAPROC glCopyImageSubData;
|
||||
|
||||
// Creates a GLFunc object that requires a feature
|
||||
#define GLFUNC_REQUIRES(x, y) { (void**)&x, #x, y }
|
||||
// Creates a GLFunc object with a different function suffix
|
||||
|
@ -1278,6 +1281,18 @@ const GLFunc gl_function_array[] =
|
|||
// ARB_clip_control
|
||||
GLFUNC_REQUIRES(glClipControl, "GL_ARB_clip_control"),
|
||||
|
||||
// ARB_copy_image
|
||||
GLFUNC_REQUIRES(glCopyImageSubData, "GL_ARB_copy_image"),
|
||||
|
||||
// NV_copy_image
|
||||
GLFUNC_SUFFIX(glCopyImageSubData, NV, "GL_NV_copy_image !GL_ARB_copy_image"),
|
||||
|
||||
// OES_copy_image
|
||||
GLFUNC_SUFFIX(glCopyImageSubData, OES, "GL_OES_copy_image"),
|
||||
|
||||
// EXT_copy_image
|
||||
GLFUNC_SUFFIX(glCopyImageSubData, EXT, "GL_EXT_copy_image !GL_OES_copy_image"),
|
||||
|
||||
// gl_1_1
|
||||
// OpenGL 1.1 is at the end due to a bug in Android's EGL stack.
|
||||
// eglGetProcAddress can only return a finite amount of function pointers
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "VideoBackends/OGL/GLExtensions/ARB_blend_func_extended.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_buffer_storage.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_clip_control.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_copy_image.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_debug_output.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_draw_elements_base_vertex.h"
|
||||
#include "VideoBackends/OGL/GLExtensions/ARB_ES2_compatibility.h"
|
||||
|
|
|
@ -469,6 +469,10 @@ Renderer::Renderer()
|
|||
g_Config.backend_info.bSupportsGeometryShaders = GLExtensions::Version() >= 320;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = GLExtensions::Supports("GL_ARB_texture_buffer_object");
|
||||
g_Config.backend_info.bSupportsClipControl = GLExtensions::Supports("GL_ARB_clip_control");
|
||||
g_Config.backend_info.bSupportsCopySubImage = GLExtensions::Supports("GL_ARB_copy_image") ||
|
||||
GLExtensions::Supports("GL_NV_copy_image") ||
|
||||
GLExtensions::Supports("GL_EXT_copy_image") ||
|
||||
GLExtensions::Supports("GL_OES_copy_image");
|
||||
|
||||
// Desktop OpenGL supports the binding layout if it supports 420pack
|
||||
// OpenGL ES 3.1 supports it implicitly without an extension
|
||||
|
@ -598,7 +602,8 @@ Renderer::Renderer()
|
|||
g_ogl_config.bSupportsMSAA ? "" : "MSAA ",
|
||||
g_ogl_config.bSupportSampleShading ? "" : "SSAA ",
|
||||
g_ActiveConfig.backend_info.bSupportsGSInstancing ? "" : "GSInstancing ",
|
||||
g_ActiveConfig.backend_info.bSupportsClipControl ? "" : "ClipControl "
|
||||
g_ActiveConfig.backend_info.bSupportsClipControl ? "" : "ClipControl ",
|
||||
g_ActiveConfig.backend_info.bSupportsCopySubImage ? "" : "CopyImageSubData "
|
||||
);
|
||||
|
||||
s_last_multisample_mode = g_ActiveConfig.iMultisampleMode;
|
||||
|
|
|
@ -137,6 +137,14 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf
|
|||
return entry;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::DoPartialTextureUpdate(TCacheEntryBase* entry_, u32 x, u32 y)
|
||||
{
|
||||
|
||||
TCacheEntry* entry = (TCacheEntry*)entry_;
|
||||
|
||||
glCopyImageSubData(entry->texture, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, texture, GL_TEXTURE_2D_ARRAY, 0, x, y, 0, entry->native_width, entry->native_height, 1);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,8 @@ private:
|
|||
TCacheEntry(const TCacheEntryConfig& config);
|
||||
~TCacheEntry();
|
||||
|
||||
void DoPartialTextureUpdate(TCacheEntryBase* entry, u32 x, u32 y) override;
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level) override;
|
||||
|
||||
|
|
|
@ -211,6 +211,48 @@ bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 r
|
|||
return true;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntryBase::DoPartialTextureUpdates()
|
||||
{
|
||||
const bool isPaletteTexture = (format== GX_TF_C4 || format == GX_TF_C8 || format == GX_TF_C14X2 || format >= 0x10000);
|
||||
|
||||
// Efb copies and paletted textures are excluded from these updates, until there's an example where a game would
|
||||
// benefit from this. Both would require more work to be done.
|
||||
// TODO: Implement upscaling support for normal textures, and then remove the efb to ram and the scaled efb restrictions
|
||||
if (!g_ActiveConfig.backend_info.bSupportsCopySubImage || !g_ActiveConfig.bSkipEFBCopyToRam || IsEfbCopy()
|
||||
|| isPaletteTexture || (g_ActiveConfig.bCopyEFBScaled && g_ActiveConfig.iEFBScale != SCALE_1X))
|
||||
return;
|
||||
|
||||
u32 block_width = TexDecoder_GetBlockWidthInTexels(format);
|
||||
u32 block_height = TexDecoder_GetBlockHeightInTexels(format);
|
||||
u32 block_size = block_width * block_height * TexDecoder_GetTexelSizeInNibbles(format) / 2;
|
||||
|
||||
u32 numBlocksX = (native_width + block_width - 1) / block_width;
|
||||
|
||||
TexCache::iterator iter = textures_by_address.lower_bound(addr);
|
||||
TexCache::iterator iterend = textures_by_address.upper_bound(addr + size_in_bytes);
|
||||
|
||||
while (iter != iterend)
|
||||
{
|
||||
TCacheEntryBase* entry = iter->second;
|
||||
if (entry->IsEfbCopy() && addr <= entry->addr && entry->addr + entry->size_in_bytes <= addr + size_in_bytes
|
||||
&& entry->frameCount == FRAMECOUNT_INVALID && entry->copyMipMapStrideChannels * 32 == numBlocksX * block_size)
|
||||
{
|
||||
u32 block_offset = (entry->addr - addr) / block_size;
|
||||
u32 block_x = block_offset % numBlocksX;
|
||||
u32 block_y = block_offset / numBlocksX;
|
||||
|
||||
u32 x = block_x * block_width;
|
||||
u32 y = block_y * block_height;
|
||||
|
||||
DoPartialTextureUpdate(entry, x, y);
|
||||
|
||||
// Mark the texture update as used, so it isn't applied more than once
|
||||
entry->frameCount = frameCount;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level)
|
||||
{
|
||||
std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) +
|
||||
|
@ -398,6 +440,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
|
|||
if (entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels &&
|
||||
entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
{
|
||||
entry->DoPartialTextureUpdates();
|
||||
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
}
|
||||
|
@ -450,6 +494,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
|
|||
if (entry->format == full_format && entry->native_levels >= tex_levels &&
|
||||
entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
{
|
||||
entry->DoPartialTextureUpdates();
|
||||
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
++iter;
|
||||
|
@ -590,6 +636,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
|
|||
INCSTAT(stats.numTexturesUploaded);
|
||||
SETSTAT(stats.numTexturesAlive, textures_by_address.size());
|
||||
|
||||
entry->DoPartialTextureUpdates();
|
||||
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
|
||||
|
@ -904,6 +952,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
|||
entry->frameCount = FRAMECOUNT_INVALID;
|
||||
entry->is_efb_copy = true;
|
||||
entry->is_custom_tex = false;
|
||||
entry->copyMipMapStrideChannels = bpmem.copyMipMapStrideChannels;
|
||||
|
||||
entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
u32 format;
|
||||
bool is_efb_copy;
|
||||
bool is_custom_tex;
|
||||
u32 copyMipMapStrideChannels;
|
||||
|
||||
unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view
|
||||
unsigned int native_levels;
|
||||
|
@ -88,6 +89,8 @@ public:
|
|||
virtual void Bind(unsigned int stage) = 0;
|
||||
virtual bool Save(const std::string& filename, unsigned int level) = 0;
|
||||
|
||||
virtual void DoPartialTextureUpdate(TCacheEntryBase* entry, u32 x, u32 y) = 0;
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level) = 0;
|
||||
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
|
@ -97,6 +100,8 @@ public:
|
|||
|
||||
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
||||
|
||||
void DoPartialTextureUpdates();
|
||||
|
||||
bool IsEfbCopy() const { return is_efb_copy; }
|
||||
};
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ struct VideoConfig final
|
|||
bool bSupportsPostProcessing;
|
||||
bool bSupportsPaletteConversion;
|
||||
bool bSupportsClipControl; // Needed by VertexShaderGen, so must stay in VideoCommon
|
||||
bool bSupportsCopySubImage; // Needed for partial texture updates
|
||||
} backend_info;
|
||||
|
||||
// Utility
|
||||
|
|
Loading…
Reference in New Issue