summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2017-06-18 12:57:05 -0700
committerGitHub <noreply@github.com>2017-06-18 12:57:05 -0700
commite63c33783049753784a24675bfa0792e54684fbd (patch)
tree3d984535025f4cb97489c9665220ac4237e7761c /Source/Core/VideoCommon
parent09457d3a4245ec9d4f2fdac3d1d0873a3354b858 (diff)
parente4896d39bd927b0b8e109e0334fa15cdb8e004f3 (diff)
Merge pull request #5305 from iwubcode/abstract_texture
Abstract Texture
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.cpp44
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.h33
-rw-r--r--Source/Core/VideoCommon/CMakeLists.txt2
-rw-r--r--Source/Core/VideoCommon/HiresTextures.cpp4
-rw-r--r--Source/Core/VideoCommon/HiresTextures.h6
-rw-r--r--Source/Core/VideoCommon/HiresTextures_DDSLoader.cpp10
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp214
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.h133
-rw-r--r--Source/Core/VideoCommon/TextureConfig.cpp18
-rw-r--r--Source/Core/VideoCommon/TextureConfig.h43
-rw-r--r--Source/Core/VideoCommon/VideoCommon.h9
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj4
-rw-r--r--Source/Core/VideoCommon/VideoCommon.vcxproj.filters12
13 files changed, 309 insertions, 223 deletions
diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp
new file mode 100644
index 0000000000..1b6fac8bff
--- /dev/null
+++ b/Source/Core/VideoCommon/AbstractTexture.cpp
@@ -0,0 +1,44 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <algorithm>
+
+#include "VideoCommon/AbstractTexture.h"
+
+AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c)
+{
+}
+
+AbstractTexture::~AbstractTexture() = default;
+
+bool AbstractTexture::Save(const std::string& filename, unsigned int level)
+{
+ return false;
+}
+
+bool AbstractTexture::IsCompressedHostTextureFormat(AbstractTextureFormat format)
+{
+ // This will need to be changed if we add any other uncompressed formats.
+ return format != AbstractTextureFormat::RGBA8;
+}
+
+size_t AbstractTexture::CalculateHostTextureLevelPitch(AbstractTextureFormat format, u32 row_length)
+{
+ switch (format)
+ {
+ case AbstractTextureFormat::DXT1:
+ return static_cast<size_t>(std::max(1u, row_length / 4)) * 8;
+ case AbstractTextureFormat::DXT3:
+ case AbstractTextureFormat::DXT5:
+ return static_cast<size_t>(std::max(1u, row_length / 4)) * 16;
+ case AbstractTextureFormat::RGBA8:
+ default:
+ return static_cast<size_t>(row_length) * 4;
+ }
+}
+
+const TextureConfig AbstractTexture::GetConfig() const
+{
+ return m_config;
+}
diff --git a/Source/Core/VideoCommon/AbstractTexture.h b/Source/Core/VideoCommon/AbstractTexture.h
new file mode 100644
index 0000000000..2b06d9c401
--- /dev/null
+++ b/Source/Core/VideoCommon/AbstractTexture.h
@@ -0,0 +1,33 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "Common/CommonTypes.h"
+#include "Common/MathUtil.h"
+#include "VideoCommon/TextureConfig.h"
+#include "VideoCommon/VideoCommon.h"
+
+class AbstractTexture
+{
+public:
+ explicit AbstractTexture(const TextureConfig& c);
+ virtual ~AbstractTexture();
+ virtual void Bind(unsigned int stage) = 0;
+ virtual bool Save(const std::string& filename, unsigned int level);
+
+ virtual void CopyRectangleFromTexture(const AbstractTexture* source,
+ const MathUtil::Rectangle<int>& srcrect,
+ const MathUtil::Rectangle<int>& dstrect) = 0;
+ virtual void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
+ size_t buffer_size) = 0;
+
+ static bool IsCompressedHostTextureFormat(AbstractTextureFormat format);
+ static size_t CalculateHostTextureLevelPitch(AbstractTextureFormat format, u32 row_length);
+
+ const TextureConfig GetConfig() const;
+
+protected:
+ const TextureConfig m_config;
+};
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt
index a50cd2774a..9eeb9f93bb 100644
--- a/Source/Core/VideoCommon/CMakeLists.txt
+++ b/Source/Core/VideoCommon/CMakeLists.txt
@@ -1,4 +1,5 @@
set(SRCS
+ AbstractTexture.cpp
AsyncRequests.cpp
BoundingBox.cpp
BPFunctions.cpp
@@ -30,6 +31,7 @@ set(SRCS
RenderState.cpp
Statistics.cpp
TextureCacheBase.cpp
+ TextureConfig.cpp
TextureConversionShader.cpp
TextureDecoder_Common.cpp
VertexLoader.cpp
diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp
index 95a70efc59..7b4a1d387c 100644
--- a/Source/Core/VideoCommon/HiresTextures.cpp
+++ b/Source/Core/VideoCommon/HiresTextures.cpp
@@ -533,7 +533,7 @@ bool HiresTexture::LoadTexture(Level& level, const std::vector<u8>& buffer)
// Images loaded by SOIL are converted to RGBA.
level.width = static_cast<u32>(width);
level.height = static_cast<u32>(height);
- level.format = HostTextureFormat::RGBA8;
+ level.format = AbstractTextureFormat::RGBA8;
level.data = ImageDataPointer(data, SOIL_free_image_data);
level.row_length = level.width;
level.data_size = static_cast<size_t>(level.row_length) * 4 * level.height;
@@ -555,7 +555,7 @@ HiresTexture::~HiresTexture()
{
}
-HostTextureFormat HiresTexture::GetFormat() const
+AbstractTextureFormat HiresTexture::GetFormat() const
{
return m_levels.at(0).format;
}
diff --git a/Source/Core/VideoCommon/HiresTextures.h b/Source/Core/VideoCommon/HiresTextures.h
index 30bb96d40c..3e7625c993 100644
--- a/Source/Core/VideoCommon/HiresTextures.h
+++ b/Source/Core/VideoCommon/HiresTextures.h
@@ -9,7 +9,7 @@
#include <vector>
#include "Common/CommonTypes.h"
-#include "VideoCommon/VideoCommon.h"
+#include "VideoCommon/TextureConfig.h"
class HiresTexture
{
@@ -32,13 +32,13 @@ public:
~HiresTexture();
- HostTextureFormat GetFormat() const;
+ AbstractTextureFormat GetFormat() const;
struct Level
{
Level();
ImageDataPointer data;
- HostTextureFormat format = HostTextureFormat::RGBA8;
+ AbstractTextureFormat format = AbstractTextureFormat::RGBA8;
u32 width = 0;
u32 height = 0;
u32 row_length = 0;
diff --git a/Source/Core/VideoCommon/HiresTextures_DDSLoader.cpp b/Source/Core/VideoCommon/HiresTextures_DDSLoader.cpp
index 27af3b6828..5b9bbeced9 100644
--- a/Source/Core/VideoCommon/HiresTextures_DDSLoader.cpp
+++ b/Source/Core/VideoCommon/HiresTextures_DDSLoader.cpp
@@ -142,7 +142,7 @@ struct DDSLoadInfo
u32 width = 0;
u32 height = 0;
u32 mip_count = 0;
- HostTextureFormat format = HostTextureFormat::RGBA8;
+ AbstractTextureFormat format = AbstractTextureFormat::RGBA8;
size_t first_mip_offset = 0;
size_t first_mip_size = 0;
u32 first_mip_row_length = 0;
@@ -300,21 +300,21 @@ bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
// In the future, this could be extended, but these isn't much benefit in doing so currently.
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71)
{
- info->format = HostTextureFormat::DXT1;
+ info->format = AbstractTextureFormat::DXT1;
info->block_size = 4;
info->bytes_per_block = 8;
needs_s3tc = true;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74)
{
- info->format = HostTextureFormat::DXT3;
+ info->format = AbstractTextureFormat::DXT3;
info->block_size = 4;
info->bytes_per_block = 16;
needs_s3tc = true;
}
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77)
{
- info->format = HostTextureFormat::DXT5;
+ info->format = AbstractTextureFormat::DXT5;
info->block_size = 4;
info->bytes_per_block = 16;
needs_s3tc = true;
@@ -353,7 +353,7 @@ bool ParseDDSHeader(File::IOFile& file, DDSLoadInfo* info)
}
// All these formats are RGBA, just with byte swapping.
- info->format = HostTextureFormat::RGBA8;
+ info->format = AbstractTextureFormat::RGBA8;
info->block_size = 1;
info->bytes_per_block = header.ddspf.dwRGBBitCount / 8;
}
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index 72978f6752..c61fa1fe5e 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -39,35 +39,18 @@ static const u64 TEXHASH_INVALID = 0;
// Sonic the Fighters (inside Sonic Gems Collection) loops a 64 frames animation
static const int TEXTURE_KILL_THRESHOLD = 64;
static const int TEXTURE_POOL_KILL_THRESHOLD = 3;
-static const int FRAMECOUNT_INVALID = 0;
std::unique_ptr<TextureCacheBase> g_texture_cache;
-TextureCacheBase::TCacheEntryBase::~TCacheEntryBase()
+TextureCacheBase::TCacheEntry::TCacheEntry(std::unique_ptr<AbstractTexture> tex)
+ : texture(std::move(tex))
{
}
-bool TextureCacheBase::IsCompressedHostTextureFormat(HostTextureFormat format)
+TextureCacheBase::TCacheEntry::~TCacheEntry()
{
- // This will need to be changed if we add any other uncompressed formats.
- return format != HostTextureFormat::RGBA8;
-}
-
-size_t TextureCacheBase::CalculateHostTextureLevelPitch(HostTextureFormat format, u32 row_length)
-{
- switch (format)
- {
- case HostTextureFormat::DXT1:
- return static_cast<size_t>(std::max(1u, row_length / 4)) * 8;
-
- case HostTextureFormat::DXT3:
- case HostTextureFormat::DXT5:
- return static_cast<size_t>(std::max(1u, row_length / 4)) * 16;
-
- case HostTextureFormat::RGBA8:
- default:
- return static_cast<size_t>(row_length) * 4;
- }
+ for (auto& reference : references)
+ reference->references.erase(this);
}
void TextureCacheBase::CheckTempSize(size_t required_size)
@@ -106,10 +89,6 @@ void TextureCacheBase::Invalidate()
textures_by_address.clear();
textures_by_hash.clear();
- for (auto& rt : texture_pool)
- {
- delete rt.second;
- }
texture_pool.clear();
}
@@ -197,13 +176,12 @@ void TextureCacheBase::Cleanup(int _frameCount)
TexPool::iterator tcend2 = texture_pool.end();
while (iter2 != tcend2)
{
- if (iter2->second->frameCount == FRAMECOUNT_INVALID)
+ if (iter2->second.frameCount == FRAMECOUNT_INVALID)
{
- iter2->second->frameCount = _frameCount;
+ iter2->second.frameCount = _frameCount;
}
- if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + iter2->second->frameCount)
+ if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + iter2->second.frameCount)
{
- delete iter2->second;
iter2 = texture_pool.erase(iter2);
}
else
@@ -213,7 +191,7 @@ void TextureCacheBase::Cleanup(int _frameCount)
}
}
-bool TextureCacheBase::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const
+bool TextureCacheBase::TCacheEntry::OverlapsMemoryRange(u32 range_address, u32 range_size) const
{
if (addr + size_in_bytes <= range_address)
return false;
@@ -236,14 +214,14 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config)
backup_config.gpu_texture_decoding = config.bEnableGPUTextureDecoding;
}
-TextureCacheBase::TCacheEntryBase* TextureCacheBase::ApplyPaletteToEntry(TCacheEntryBase* entry,
- u8* palette, u32 tlutfmt)
+TextureCacheBase::TCacheEntry* TextureCacheBase::ApplyPaletteToEntry(TCacheEntry* entry,
+ u8* palette, u32 tlutfmt)
{
- TCacheEntryConfig new_config = entry->config;
+ TextureConfig new_config = entry->texture->GetConfig();
new_config.levels = 1;
new_config.rendertarget = true;
- TCacheEntryBase* decoded_entry = AllocateTexture(new_config);
+ TCacheEntry* decoded_entry = AllocateCacheEntry(new_config);
if (!decoded_entry)
return nullptr;
@@ -259,10 +237,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::ApplyPaletteToEntry(TCacheE
return decoded_entry;
}
-void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBase** entry,
- u32 new_width, u32 new_height)
+void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntry* entry, u32 new_width,
+ u32 new_height)
{
- if ((*entry)->config.width == new_width && (*entry)->config.height == new_height)
+ if (entry->GetWidth() == new_width && entry->GetHeight() == new_height)
{
return;
}
@@ -274,41 +252,24 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas
return;
}
- TextureCacheBase::TCacheEntryConfig newconfig;
+ TextureConfig newconfig;
newconfig.width = new_width;
newconfig.height = new_height;
- newconfig.layers = (*entry)->config.layers;
+ newconfig.layers = entry->GetNumLayers();
newconfig.rendertarget = true;
- TCacheEntryBase* newentry = AllocateTexture(newconfig);
- if (newentry)
+ std::unique_ptr<AbstractTexture> new_texture = AllocateTexture(newconfig);
+ if (new_texture)
{
- newentry->SetGeneralParameters((*entry)->addr, (*entry)->size_in_bytes, (*entry)->format);
- newentry->SetDimensions((*entry)->native_width, (*entry)->native_height, 1);
- newentry->SetHashes((*entry)->base_hash, (*entry)->hash);
- newentry->frameCount = frameCount;
- newentry->is_efb_copy = (*entry)->is_efb_copy;
- MathUtil::Rectangle<int> srcrect, dstrect;
- srcrect.left = 0;
- srcrect.top = 0;
- srcrect.right = (*entry)->config.width;
- srcrect.bottom = (*entry)->config.height;
- dstrect.left = 0;
- dstrect.top = 0;
- dstrect.right = new_width;
- dstrect.bottom = new_height;
- newentry->CopyRectangleFromTexture(*entry, srcrect, dstrect);
-
- // Keep track of the pointer for textures_by_hash
- if ((*entry)->textures_by_hash_iter != textures_by_hash.end())
- {
- newentry->textures_by_hash_iter = textures_by_hash.emplace((*entry)->hash, newentry);
- }
-
- InvalidateTexture(GetTexCacheIter(*entry));
-
- *entry = newentry;
- textures_by_address.emplace((*entry)->addr, *entry);
+ new_texture->CopyRectangleFromTexture(entry->texture.get(),
+ entry->texture->GetConfig().GetRect(),
+ new_texture->GetConfig().GetRect());
+ entry->texture.swap(new_texture);
+
+ auto config = new_texture->GetConfig();
+ // At this point new_texture has the old texture in it,
+ // we can potentially reuse this, so let's move it back to the pool
+ texture_pool.emplace(config, TexPoolEntry(std::move(new_texture)));
}
else
{
@@ -316,9 +277,8 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas
}
}
-TextureCacheBase::TCacheEntryBase*
-TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8* palette,
- u32 tlutfmt)
+TextureCacheBase::TCacheEntry*
+TextureCacheBase::DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* palette, u32 tlutfmt)
{
// If the flag may_have_overlapping_textures is cleared, there are no overlapping EFB copies,
// which aren't applied already. It is set for new textures, and for the affected range
@@ -346,7 +306,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8*
auto iter = FindOverlappingTextures(entry_to_update->addr, entry_to_update->size_in_bytes);
while (iter.first != iter.second)
{
- TCacheEntryBase* entry = iter.first->second;
+ TCacheEntry* entry = iter.first->second;
if (entry != entry_to_update && entry->IsEfbCopy() &&
entry->references.count(entry_to_update) == 0 &&
entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes) &&
@@ -356,7 +316,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8*
{
if (isPaletteTexture)
{
- TCacheEntryBase* decoded_entry = ApplyPaletteToEntry(entry, palette, tlutfmt);
+ TCacheEntry* decoded_entry = ApplyPaletteToEntry(entry, palette, tlutfmt);
if (decoded_entry)
{
// Link the efb copy with the partially updated texture, so we won't apply this partial
@@ -404,15 +364,14 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8*
std::min(entry->native_height - src_y, entry_to_update->native_height - dst_y);
// If one of the textures is scaled, scale both with the current efb scaling factor
- if (entry_to_update->native_width != entry_to_update->config.width ||
- entry_to_update->native_height != entry_to_update->config.height ||
- entry->native_width != entry->config.width ||
- entry->native_height != entry->config.height)
+ if (entry_to_update->native_width != entry_to_update->GetWidth() ||
+ entry_to_update->native_height != entry_to_update->GetHeight() ||
+ entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight())
{
- ScaleTextureCacheEntryTo(&entry_to_update,
+ ScaleTextureCacheEntryTo(entry_to_update,
g_renderer->EFBToScaledX(entry_to_update->native_width),
g_renderer->EFBToScaledY(entry_to_update->native_height));
- ScaleTextureCacheEntryTo(&entry, g_renderer->EFBToScaledX(entry->native_width),
+ ScaleTextureCacheEntryTo(entry, g_renderer->EFBToScaledX(entry->native_width),
g_renderer->EFBToScaledY(entry->native_height));
src_x = g_renderer->EFBToScaledX(src_x);
@@ -432,7 +391,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8*
dstrect.top = dst_y;
dstrect.right = (dst_x + copy_width);
dstrect.bottom = (dst_y + copy_height);
- entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect);
+ entry_to_update->texture->CopyRectangleFromTexture(entry->texture.get(), srcrect, dstrect);
if (isPaletteTexture)
{
@@ -460,7 +419,7 @@ TextureCacheBase::DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8*
return entry_to_update;
}
-void TextureCacheBase::DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level)
+void TextureCacheBase::DumpTexture(TCacheEntry* entry, std::string basename, unsigned int level)
{
std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().GetGameID();
@@ -475,7 +434,7 @@ void TextureCacheBase::DumpTexture(TCacheEntryBase* entry, std::string basename,
std::string filename = szDir + "/" + basename + ".png";
if (!File::Exists(filename))
- entry->Save(filename, level);
+ entry->texture->Save(filename, level);
}
static u32 CalculateLevelSize(u32 level_0_size, u32 level)
@@ -484,8 +443,7 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level)
}
// Used by TextureCacheBase::Load
-TextureCacheBase::TCacheEntryBase* TextureCacheBase::ReturnEntry(unsigned int stage,
- TCacheEntryBase* entry)
+TextureCacheBase::TCacheEntry* TextureCacheBase::ReturnEntry(unsigned int stage, TCacheEntry* entry)
{
entry->frameCount = FRAMECOUNT_INVALID;
bound_textures[stage] = entry;
@@ -500,7 +458,7 @@ void TextureCacheBase::BindTextures()
for (size_t i = 0; i < bound_textures.size(); ++i)
{
if (bound_textures[i])
- bound_textures[i]->Bind(static_cast<u32>(i));
+ bound_textures[i]->texture->Bind(static_cast<u32>(i));
}
}
@@ -509,7 +467,7 @@ void TextureCacheBase::UnbindTextures()
bound_textures.fill(nullptr);
}
-TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
+TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
{
const FourTexUnits& tex = bpmem.tex[stage >> 2];
const u32 id = stage & 3;
@@ -651,7 +609,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
while (iter != iter_range.second)
{
- TCacheEntryBase* entry = iter->second;
+ TCacheEntry* entry = iter->second;
// Do not load strided EFB copies, they are not meant to be used directly
if (entry->IsEfbCopy() && entry->native_width == nativeW && entry->native_height == nativeH &&
entry->memory_stride == entry->BytesPerRow())
@@ -714,7 +672,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
if (unconverted_copy != textures_by_address.end())
{
- TCacheEntryBase* decoded_entry =
+ TCacheEntry* decoded_entry =
ApplyPaletteToEntry(unconverted_copy->second, &texMem[tlutaddr], tlutfmt);
if (decoded_entry)
@@ -737,7 +695,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
TexHashCache::iterator hash_iter = hash_range.first;
while (hash_iter != hash_range.second)
{
- TCacheEntryBase* entry = hash_iter->second;
+ TCacheEntry* entry = hash_iter->second;
// All parameters, except the address, need to match here
if (entry->format == full_format && entry->native_levels >= tex_levels &&
entry->native_width == nativeW && entry->native_height == nativeH)
@@ -791,13 +749,13 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
!(from_tmem && texformat == GX_TF_RGBA8);
// create the entry/texture
- TCacheEntryConfig config;
+ TextureConfig config;
config.width = width;
config.height = height;
config.levels = texLevels;
- config.format = hires_tex ? hires_tex->GetFormat() : HostTextureFormat::RGBA8;
+ config.format = hires_tex ? hires_tex->GetFormat() : AbstractTextureFormat::RGBA8;
- TCacheEntryBase* entry = AllocateTexture(config);
+ TCacheEntry* entry = AllocateCacheEntry(config);
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
if (!entry)
@@ -807,8 +765,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
if (hires_tex)
{
const auto& level = hires_tex->m_levels[0];
- entry->Load(0, level.width, level.height, level.row_length, level.data.get(), level.data_size);
+ entry->texture->Load(0, level.width, level.height, level.row_length, level.data.get(),
+ level.data_size);
}
+
if (!hires_tex && decode_on_gpu)
{
u32 row_stride = bytes_per_block * (expandedWidth / bsw);
@@ -832,7 +792,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
TexDecoder_DecodeRGBA8FromTmem(temp, src_data, src_data_gb, expandedWidth, expandedHeight);
}
- entry->Load(0, width, height, expandedWidth, temp, decoded_texture_size);
+ entry->texture->Load(0, width, height, expandedWidth, temp, decoded_texture_size);
}
iter = textures_by_address.emplace(address, entry);
@@ -862,8 +822,8 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
for (u32 level_index = 1; level_index != texLevels; ++level_index)
{
const auto& level = hires_tex->m_levels[level_index];
- entry->Load(level_index, level.width, level.height, level.row_length, level.data.get(),
- level.data_size);
+ entry->texture->Load(level_index, level.width, level.height, level.row_length,
+ level.data.get(), level.data_size);
}
}
else
@@ -905,7 +865,8 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
size_t decoded_mip_size = expanded_mip_width * sizeof(u32) * expanded_mip_height;
TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat,
tlut, (TlutFormat)tlutfmt);
- entry->Load(level, mip_width, mip_height, expanded_mip_width, temp, decoded_mip_size);
+ entry->texture->Load(level, mip_width, mip_height, expanded_mip_width, temp,
+ decoded_mip_size);
}
mip_src_data += mip_size;
@@ -1357,7 +1318,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
auto iter = FindOverlappingTextures(dstAddr, covered_range);
while (iter.first != iter.second)
{
- TCacheEntryBase* entry = iter.first->second;
+ TCacheEntry* entry = iter.first->second;
if (entry->OverlapsMemoryRange(dstAddr, covered_range))
{
if (invalidate_textures)
@@ -1373,13 +1334,13 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
if (copy_to_vram)
{
// create the texture
- TCacheEntryConfig config;
+ TextureConfig config;
config.rendertarget = true;
config.width = scaled_tex_w;
config.height = scaled_tex_h;
config.layers = FramebufferManagerBase::GetEFBLayers();
- TCacheEntryBase* entry = AllocateTexture(config);
+ TCacheEntry* entry = AllocateCacheEntry(config);
if (entry)
{
@@ -1390,7 +1351,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
entry->SetEfbCopy(dstStride);
entry->is_custom_tex = false;
- entry->FromRenderTarget(is_depth_copy, srcRect, scaleByHalf, cbufid, colmat);
+ CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, cbufid, colmat);
u64 hash = entry->CalculateHash();
entry->SetHashes(hash, hash);
@@ -1398,9 +1359,10 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
if (g_ActiveConfig.bDumpEFBTarget)
{
static int count = 0;
- entry->Save(StringFromFormat("%sefb_frame_%i.png",
- File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), count++),
- 0);
+ entry->texture->Save(StringFromFormat("%sefb_frame_%i.png",
+ File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
+ count++),
+ 0);
}
textures_by_address.emplace(dstAddr, entry);
@@ -1408,14 +1370,26 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
}
}
-TextureCacheBase::TCacheEntryBase*
-TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
+TextureCacheBase::TCacheEntry* TextureCacheBase::AllocateCacheEntry(const TextureConfig& config)
+{
+ std::unique_ptr<AbstractTexture> texture = AllocateTexture(config);
+
+ if (!texture)
+ {
+ return nullptr;
+ }
+ TCacheEntry* cacheEntry = new TCacheEntry(std::move(texture));
+ cacheEntry->textures_by_hash_iter = textures_by_hash.end();
+ return cacheEntry;
+}
+
+std::unique_ptr<AbstractTexture> TextureCacheBase::AllocateTexture(const TextureConfig& config)
{
TexPool::iterator iter = FindMatchingTextureFromPool(config);
- TextureCacheBase::TCacheEntryBase* entry;
+ std::unique_ptr<AbstractTexture> entry;
if (iter != texture_pool.end())
{
- entry = iter->second;
+ entry = std::move(iter->second.texture);
texture_pool.erase(iter);
}
else
@@ -1427,13 +1401,11 @@ TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
INCSTAT(stats.numTexturesCreated);
}
- entry->textures_by_hash_iter = textures_by_hash.end();
- entry->may_have_overlapping_textures = true;
return entry;
}
TextureCacheBase::TexPool::iterator
-TextureCacheBase::FindMatchingTextureFromPool(const TCacheEntryConfig& config)
+TextureCacheBase::FindMatchingTextureFromPool(const TextureConfig& config)
{
// Find a texture from the pool that does not have a frameCount of FRAMECOUNT_INVALID.
// This prevents a texture from being used twice in a single frame with different data,
@@ -1442,13 +1414,13 @@ TextureCacheBase::FindMatchingTextureFromPool(const TCacheEntryConfig& config)
// As non-render-target textures are usually static, this should not matter much.
auto range = texture_pool.equal_range(config);
auto matching_iter = std::find_if(range.first, range.second, [](const auto& iter) {
- return iter.first.rendertarget || iter.second->frameCount != FRAMECOUNT_INVALID;
+ return iter.first.rendertarget || iter.second.frameCount != FRAMECOUNT_INVALID;
});
return matching_iter != range.second ? matching_iter : texture_pool.end();
}
TextureCacheBase::TexAddrCache::iterator
-TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry)
+TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntry* entry)
{
auto iter_range = textures_by_address.equal_range(entry->addr);
TexAddrCache::iterator iter = iter_range.first;
@@ -1486,7 +1458,7 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter)
if (iter == textures_by_address.end())
return textures_by_address.end();
- TCacheEntryBase* entry = iter->second;
+ TCacheEntry* entry = iter->second;
if (entry->textures_by_hash_iter != textures_by_hash.end())
{
@@ -1494,15 +1466,13 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter)
entry->textures_by_hash_iter = textures_by_hash.end();
}
- entry->DestroyAllReferences();
-
- entry->frameCount = FRAMECOUNT_INVALID;
- texture_pool.emplace(entry->config, entry);
+ auto config = entry->texture->GetConfig();
+ texture_pool.emplace(config, TexPoolEntry(std::move(entry->texture)));
return textures_by_address.erase(iter);
}
-u32 TextureCacheBase::TCacheEntryBase::BytesPerRow() const
+u32 TextureCacheBase::TCacheEntry::BytesPerRow() const
{
const u32 blockW = TexDecoder_GetBlockWidthInTexels(format);
@@ -1517,7 +1487,7 @@ u32 TextureCacheBase::TCacheEntryBase::BytesPerRow() const
return numBlocksX * bytes_per_block;
}
-u32 TextureCacheBase::TCacheEntryBase::NumBlocksY() const
+u32 TextureCacheBase::TCacheEntry::NumBlocksY() const
{
u32 blockH = TexDecoder_GetBlockHeightInTexels(format);
// Round up source height to multiple of block size
@@ -1526,7 +1496,7 @@ u32 TextureCacheBase::TCacheEntryBase::NumBlocksY() const
return actualHeight / blockH;
}
-void TextureCacheBase::TCacheEntryBase::SetEfbCopy(u32 stride)
+void TextureCacheBase::TCacheEntry::SetEfbCopy(u32 stride)
{
is_efb_copy = true;
memory_stride = stride;
@@ -1536,7 +1506,7 @@ void TextureCacheBase::TCacheEntryBase::SetEfbCopy(u32 stride)
size_in_bytes = memory_stride * NumBlocksY();
}
-u64 TextureCacheBase::TCacheEntryBase::CalculateHash() const
+u64 TextureCacheBase::TCacheEntry::CalculateHash() const
{
u8* ptr = Memory::GetPointer(addr);
if (memory_stride == BytesPerRow())
diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h
index 7f2491a5c7..23f25f48fc 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.h
+++ b/Source/Core/VideoCommon/TextureCacheBase.h
@@ -12,7 +12,9 @@
#include <unordered_set>
#include "Common/CommonTypes.h"
+#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/BPMemory.h"
+#include "VideoCommon/TextureConfig.h"
#include "VideoCommon/TextureDecoder.h"
#include "VideoCommon/VideoCommon.h"
@@ -20,40 +22,14 @@ struct VideoConfig;
class TextureCacheBase
{
-public:
- struct TCacheEntryConfig
- {
- constexpr TCacheEntryConfig() = default;
-
- bool operator==(const TCacheEntryConfig& o) const
- {
- return std::tie(width, height, levels, layers, format, rendertarget) ==
- std::tie(o.width, o.height, o.levels, o.layers, o.format, o.rendertarget);
- }
-
- struct Hasher : std::hash<u64>
- {
- size_t operator()(const TCacheEntryConfig& c) const
- {
- u64 id = (u64)c.rendertarget << 63 | (u64)c.format << 50 | (u64)c.layers << 48 |
- (u64)c.levels << 32 | (u64)c.height << 16 | (u64)c.width;
- return std::hash<u64>::operator()(id);
- }
- };
-
- u32 width = 0;
- u32 height = 0;
- u32 levels = 1;
- u32 layers = 1;
- HostTextureFormat format = HostTextureFormat::RGBA8;
- bool rendertarget = false;
- };
+private:
+ static const int FRAMECOUNT_INVALID = 0;
- struct TCacheEntryBase
+public:
+ struct TCacheEntry
{
- const TCacheEntryConfig config;
-
// common members
+ std::unique_ptr<AbstractTexture> texture;
u32 addr;
u32 size_in_bytes;
u64 base_hash;
@@ -62,23 +38,27 @@ public:
u32 memory_stride;
bool is_efb_copy;
bool is_custom_tex;
- bool may_have_overlapping_textures;
+ bool may_have_overlapping_textures = true;
unsigned int native_width,
native_height; // Texture dimensions from the GameCube's point of view
unsigned int native_levels;
// used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames
- int frameCount;
+ int frameCount = FRAMECOUNT_INVALID;
// Keep an iterator to the entry in textures_by_hash, so it does not need to be searched when
// removing the cache entry
- std::multimap<u64, TCacheEntryBase*>::iterator textures_by_hash_iter;
+ std::multimap<u64, TCacheEntry*>::iterator textures_by_hash_iter;
// This is used to keep track of both:
// * efb copies used by this partially updated texture
// * partially updated textures which refer to this efb copy
- std::unordered_set<TCacheEntryBase*> references;
+ std::unordered_set<TCacheEntry*> references;
+
+ explicit TCacheEntry(std::unique_ptr<AbstractTexture> tex);
+
+ ~TCacheEntry();
void SetGeneralParameters(u32 _addr, u32 _size, u32 _format)
{
@@ -103,38 +83,15 @@ public:
}
// This texture entry is used by the other entry as a sub-texture
- void CreateReference(TCacheEntryBase* other_entry)
+ void CreateReference(TCacheEntry* other_entry)
{
// References are two-way, so they can easily be destroyed later
this->references.emplace(other_entry);
other_entry->references.emplace(this);
}
- void DestroyAllReferences()
- {
- for (auto& reference : references)
- reference->references.erase(this);
-
- references.clear();
- }
-
void SetEfbCopy(u32 stride);
- TCacheEntryBase(const TCacheEntryConfig& c) : config(c) {}
- virtual ~TCacheEntryBase();
-
- virtual void Bind(unsigned int stage) = 0;
- virtual bool Save(const std::string& filename, unsigned int level) = 0;
-
- virtual void CopyRectangleFromTexture(const TCacheEntryBase* source,
- const MathUtil::Rectangle<int>& srcrect,
- const MathUtil::Rectangle<int>& dstrect) = 0;
-
- virtual void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
- size_t buffer_size) = 0;
- virtual void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect, bool scaleByHalf,
- unsigned int cbufid, const float* colmat) = 0;
-
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
bool IsEfbCopy() const { return is_efb_copy; }
@@ -142,14 +99,16 @@ public:
u32 BytesPerRow() const;
u64 CalculateHash() const;
+
+ u32 GetWidth() const { return texture->GetConfig().width; }
+ u32 GetHeight() const { return texture->GetConfig().height; }
+ u32 GetNumLevels() const { return texture->GetConfig().levels; }
+ u32 GetNumLayers() const { return texture->GetConfig().layers; }
+ AbstractTextureFormat GetFormat() const { return texture->GetConfig().format; }
};
virtual ~TextureCacheBase(); // needs virtual for DX11 dtor
- // TODO: Move these to AbstractTexture once it is finished.
- static bool IsCompressedHostTextureFormat(HostTextureFormat format);
- static size_t CalculateHostTextureLevelPitch(HostTextureFormat format, u32 row_length);
-
void OnConfigChanged(VideoConfig& config);
// Removes textures which aren't used for more than TEXTURE_KILL_THRESHOLD frames,
@@ -158,8 +117,6 @@ public:
void Invalidate();
- virtual TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) = 0;
-
virtual void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) = 0;
@@ -167,14 +124,14 @@ public:
virtual bool CompileShaders() = 0;
virtual void DeleteShaders() = 0;
- TCacheEntryBase* Load(const u32 stage);
+ TCacheEntry* Load(const u32 stage);
void UnbindTextures();
virtual void BindTextures();
void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, u32 dstStride,
bool is_depth_copy, const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf);
- virtual void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette,
+ virtual void ConvertTexture(TCacheEntry* entry, TCacheEntry* unconverted, void* palette,
TlutFormat format) = 0;
// Returns true if the texture data and palette formats are supported by the GPU decoder.
@@ -187,7 +144,7 @@ public:
// width, height are the size of the image in pixels.
// aligned_width, aligned_height are the size of the image in pixels, aligned to the block size.
// row_stride is the number of bytes for a row of blocks, not pixels.
- virtual void DecodeTextureOnGPU(TCacheEntryBase* entry, u32 dst_level, const u8* data,
+ virtual void DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data,
size_t data_size, TextureFormat format, u32 width, u32 height,
u32 aligned_width, u32 aligned_height, u32 row_stride,
const u8* palette, TlutFormat palette_format)
@@ -200,38 +157,50 @@ protected:
alignas(16) u8* temp = nullptr;
size_t temp_size = 0;
- std::array<TCacheEntryBase*, 8> bound_textures{};
+ std::array<TCacheEntry*, 8> bound_textures{};
private:
- typedef std::multimap<u32, TCacheEntryBase*> TexAddrCache;
- typedef std::multimap<u64, TCacheEntryBase*> TexHashCache;
- typedef std::unordered_multimap<TCacheEntryConfig, TCacheEntryBase*, TCacheEntryConfig::Hasher>
- TexPool;
+ // Minimal version of TCacheEntry just for TexPool
+ struct TexPoolEntry
+ {
+ std::unique_ptr<AbstractTexture> texture;
+ int frameCount = FRAMECOUNT_INVALID;
+ TexPoolEntry(std::unique_ptr<AbstractTexture> tex) : texture(std::move(tex)) {}
+ };
+ typedef std::multimap<u32, TCacheEntry*> TexAddrCache;
+ typedef std::multimap<u64, TCacheEntry*> TexHashCache;
+ typedef std::unordered_multimap<TextureConfig, TexPoolEntry, TextureConfig::Hasher> TexPool;
void SetBackupConfig(const VideoConfig& config);
- TCacheEntryBase* ApplyPaletteToEntry(TCacheEntryBase* entry, u8* palette, u32 tlutfmt);
+ TCacheEntry* ApplyPaletteToEntry(TCacheEntry* entry, u8* palette, u32 tlutfmt);
- void ScaleTextureCacheEntryTo(TCacheEntryBase** entry, u32 new_width, u32 new_height);
- TCacheEntryBase* DoPartialTextureUpdates(TCacheEntryBase* entry_to_update, u8* palette,
- u32 tlutfmt);
+ void ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height);
+ TCacheEntry* DoPartialTextureUpdates(TCacheEntry* entry_to_update, u8* palette, u32 tlutfmt);
- void DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level);
+ void DumpTexture(TCacheEntry* entry, std::string basename, unsigned int level);
void CheckTempSize(size_t required_size);
- TCacheEntryBase* AllocateTexture(const TCacheEntryConfig& config);
- TexPool::iterator FindMatchingTextureFromPool(const TCacheEntryConfig& config);
- TexAddrCache::iterator GetTexCacheIter(TCacheEntryBase* entry);
+ TCacheEntry* AllocateCacheEntry(const TextureConfig& config);
+ std::unique_ptr<AbstractTexture> AllocateTexture(const TextureConfig& config);
+ TexPool::iterator FindMatchingTextureFromPool(const TextureConfig& config);
+ TexAddrCache::iterator GetTexCacheIter(TCacheEntry* entry);
// Return all possible overlapping textures. As addr+size of the textures is not
// indexed, this may return false positives.
std::pair<TexAddrCache::iterator, TexAddrCache::iterator>
FindOverlappingTextures(u32 addr, u32 size_in_bytes);
+ virtual std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) = 0;
+
+ virtual void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
+ const EFBRectangle& src_rect, bool scale_by_half,
+ unsigned int cbuf_id, const float* colmat) = 0;
+
// Removes and unlinks texture from texture cache and returns it to the pool
TexAddrCache::iterator InvalidateTexture(TexAddrCache::iterator t_iter);
- TCacheEntryBase* ReturnEntry(unsigned int stage, TCacheEntryBase* entry);
+ TCacheEntry* ReturnEntry(unsigned int stage, TCacheEntry* entry);
TexAddrCache textures_by_address;
TexHashCache textures_by_hash;
diff --git a/Source/Core/VideoCommon/TextureConfig.cpp b/Source/Core/VideoCommon/TextureConfig.cpp
new file mode 100644
index 0000000000..7a6930c798
--- /dev/null
+++ b/Source/Core/VideoCommon/TextureConfig.cpp
@@ -0,0 +1,18 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "VideoCommon/TextureConfig.h"
+
+#include <tuple>
+
+bool TextureConfig::operator==(const TextureConfig& o) const
+{
+ return std::tie(width, height, levels, layers, format, rendertarget) ==
+ std::tie(o.width, o.height, o.levels, o.layers, o.format, o.rendertarget);
+}
+
+MathUtil::Rectangle<int> TextureConfig::GetRect() const
+{
+ return {0, 0, static_cast<int>(width), static_cast<int>(height)};
+}
diff --git a/Source/Core/VideoCommon/TextureConfig.h b/Source/Core/VideoCommon/TextureConfig.h
new file mode 100644
index 0000000000..27a0c935a1
--- /dev/null
+++ b/Source/Core/VideoCommon/TextureConfig.h
@@ -0,0 +1,43 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstddef>
+#include <functional>
+
+#include "Common/CommonTypes.h"
+#include "Common/MathUtil.h"
+
+enum class AbstractTextureFormat : u32
+{
+ RGBA8,
+ DXT1,
+ DXT3,
+ DXT5
+};
+
+struct TextureConfig
+{
+ constexpr TextureConfig() = default;
+ bool operator==(const TextureConfig& o) const;
+ MathUtil::Rectangle<int> GetRect() const;
+
+ u32 width = 0;
+ u32 height = 0;
+ u32 levels = 1;
+ u32 layers = 1;
+ AbstractTextureFormat format = AbstractTextureFormat::RGBA8;
+ bool rendertarget = false;
+
+ struct Hasher : std::hash<u64>
+ {
+ size_t operator()(const TextureConfig& c) const
+ {
+ u64 id = (u64)c.rendertarget << 63 | (u64)c.format << 50 | (u64)c.layers << 48 |
+ (u64)c.levels << 32 | (u64)c.height << 16 | (u64)c.width;
+ return std::hash<u64>::operator()(id);
+ }
+ };
+};
diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h
index cff2883318..e25b2b66a5 100644
--- a/Source/Core/VideoCommon/VideoCommon.h
+++ b/Source/Core/VideoCommon/VideoCommon.h
@@ -77,15 +77,6 @@ enum class APIType
Nothing
};
-// Texture formats that videocommon can upload/use.
-enum class HostTextureFormat : u32
-{
- RGBA8,
- DXT1,
- DXT3,
- DXT5
-};
-
inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
{
u32 color = src;
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj
index 88d3e4b759..97adb25ac6 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj
@@ -36,6 +36,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
+ <ClCompile Include="AbstractTexture.cpp" />
<ClCompile Include="AsyncRequests.cpp" />
<ClCompile Include="AVIDump.cpp" />
<ClCompile Include="BoundingBox.cpp" />
@@ -68,6 +69,7 @@
<ClCompile Include="GeometryShaderGen.cpp" />
<ClCompile Include="GeometryShaderManager.cpp" />
<ClCompile Include="TextureCacheBase.cpp" />
+ <ClCompile Include="TextureConfig.cpp" />
<ClCompile Include="TextureConversionShader.cpp" />
<ClCompile Include="VertexLoader.cpp" />
<ClCompile Include="VertexLoaderBase.cpp" />
@@ -89,6 +91,7 @@
<ClCompile Include="XFStructs.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="AbstractTexture.h" />
<ClInclude Include="AsyncRequests.h" />
<ClInclude Include="AVIDump.h" />
<ClInclude Include="BoundingBox.h" />
@@ -124,6 +127,7 @@
<ClInclude Include="GeometryShaderGen.h" />
<ClInclude Include="GeometryShaderManager.h" />
<ClInclude Include="TextureCacheBase.h" />
+ <ClInclude Include="TextureConfig.h" />
<ClInclude Include="TextureConversionShader.h" />
<ClInclude Include="TextureDecoder.h" />
<ClInclude Include="VertexLoader.h" />
diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
index eb45d40ffc..be09444957 100644
--- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
+++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters
@@ -167,6 +167,12 @@
<ClCompile Include="HiresTextures_DDSLoader.cpp">
<Filter>Util</Filter>
</ClCompile>
+ <ClCompile Include="TextureConfig.cpp">
+ <Filter>Base</Filter>
+ </ClCompile>
+ <ClCompile Include="AbstractTexture.cpp">
+ <Filter>Base</Filter>
+ </C1Compile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CommandProcessor.h" />
@@ -317,6 +323,12 @@
<ClInclude Include="SamplerCommon.h">
<Filter>Util</Filter>
</ClInclude>
+ <ClInclude Include="TextureConfig.h">
+ <Filter>Base</Filter>
+ </ClInclude>
+ <ClInclude Include="AbstractTexture.h">
+ <Filter>Base</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />