diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 5b4328cb7f..06ee82b450 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -239,6 +239,19 @@ D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter) return feat_level; } +static bool SupportsS3TCTextures(ID3D11Device* device) +{ + UINT bc1_support, bc2_support, bc3_support; + if (FAILED(device->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &bc1_support)) || + FAILED(device->CheckFormatSupport(DXGI_FORMAT_BC2_UNORM, &bc2_support)) || + FAILED(device->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &bc3_support))) + { + return false; + } + + return ((bc1_support & bc2_support & bc3_support) & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; +} + HRESULT Create(HWND wnd) { hWnd = wnd; @@ -427,6 +440,7 @@ HRESULT Create(HWND wnd) UINT format_support; device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support); bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; + g_Config.backend_info.bSupportsST3CTextures = SupportsS3TCTextures(device); stateman = new StateManager; return S_OK; diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index de22a2c04f..92941477e8 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -7,6 +7,7 @@ #include #include +#include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" @@ -29,6 +30,42 @@ static std::unique_ptr g_encoder; const size_t MAX_COPY_BUFFERS = 32; ID3D11Buffer* efbcopycbuf[MAX_COPY_BUFFERS] = {0}; +static u32 GetLevelPitch(HostTextureFormat format, u32 row_length) +{ + switch (format) + { + case HostTextureFormat::DXT1: + return row_length / 4 * 8; + + case HostTextureFormat::DXT3: + case HostTextureFormat::DXT5: + return row_length / 4 * 16; + + case HostTextureFormat::RGBA8: + default: + return row_length * 4; + } +} + +static DXGI_FORMAT GetDXGIFormatForHostFormat(HostTextureFormat format) +{ + switch (format) + { + case HostTextureFormat::DXT1: + return DXGI_FORMAT_BC1_UNORM; + + case HostTextureFormat::DXT3: + return DXGI_FORMAT_BC2_UNORM; + + case HostTextureFormat::DXT5: + return DXGI_FORMAT_BC3_UNORM; + + case HostTextureFormat::RGBA8: + default: + return DXGI_FORMAT_R8G8B8A8_UNORM; + } +} + TextureCache::TCacheEntry::~TCacheEntry() { texture->Release(); @@ -41,6 +78,11 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) { + // We can't dump compressed textures currently (it would mean drawing them to a RGBA8 + // framebuffer, and saving that). TextureCache does not call Save for custom textures + // anyway, so this is fine for now. + _assert_(config.format == HostTextureFormat::RGBA8); + // Create a staging/readback texture with the dimensions of the specified mip level. u32 mip_width = std::max(config.width >> level, 1u); u32 mip_height = std::max(config.height >> level, 1u); @@ -132,25 +174,26 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size) { - u32 src_pitch = row_length * 4; + u32 src_pitch = GetLevelPitch(config.format, row_length); D3D::context->UpdateSubresource(texture->GetTex(), level, nullptr, buffer, src_pitch, 0); } TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config) { + DXGI_FORMAT dxgi_format = GetDXGIFormatForHostFormat(config.format); if (config.rendertarget) { return new TCacheEntry( - config, D3DTexture2D::Create( - config.width, config.height, (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | - (int)D3D11_BIND_SHADER_RESOURCE), - D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, config.layers)); + config, D3DTexture2D::Create(config.width, config.height, + (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | + (int)D3D11_BIND_SHADER_RESOURCE), + D3D11_USAGE_DEFAULT, dxgi_format, 1, config.layers)); } else { const D3D11_TEXTURE2D_DESC texdesc = - CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, config.width, config.height, 1, - config.levels, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0); + CD3D11_TEXTURE2D_DESC(dxgi_format, config.width, config.height, 1, config.levels, + D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0); ID3D11Texture2D* pTexture; const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);