D3D12: Support native compressed textures

This commit is contained in:
Stenzek 2017-04-16 20:53:38 +10:00
parent 2d75c2ab10
commit 3f18c5e0f1
2 changed files with 63 additions and 4 deletions

View File

@ -262,6 +262,21 @@ std::vector<DXGI_SAMPLE_DESC> EnumAAModes(ID3D12Device* device)
return aa_modes; return aa_modes;
} }
static bool SupportsS3TCTextures(ID3D12Device* device)
{
auto CheckForFormat = [](ID3D12Device* device, DXGI_FORMAT format) {
D3D12_FEATURE_DATA_FORMAT_SUPPORT data = {format};
if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data))))
return false;
return (data.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D) != 0;
};
return CheckForFormat(device, DXGI_FORMAT_BC1_UNORM) &&
CheckForFormat(device, DXGI_FORMAT_BC2_UNORM) &&
CheckForFormat(device, DXGI_FORMAT_BC3_UNORM);
}
HRESULT Create(HWND wnd) HRESULT Create(HWND wnd)
{ {
hWnd = wnd; hWnd = wnd;
@ -478,6 +493,8 @@ HRESULT Create(HWND wnd)
SAFE_RELEASE(factory); SAFE_RELEASE(factory);
SAFE_RELEASE(adapter); SAFE_RELEASE(adapter);
g_Config.backend_info.bSupportsST3CTextures = SupportsS3TCTextures(device12);
return S_OK; return S_OK;
} }

View File

@ -33,6 +33,42 @@ static u32 s_efb_copy_last_cbuf_id = UINT_MAX;
static ID3D12Resource* s_texture_cache_entry_readback_buffer = nullptr; static ID3D12Resource* s_texture_cache_entry_readback_buffer = nullptr;
static size_t s_texture_cache_entry_readback_buffer_size = 0; static size_t s_texture_cache_entry_readback_buffer_size = 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() TextureCache::TCacheEntry::~TCacheEntry()
{ {
m_texture->Release(); m_texture->Release();
@ -51,6 +87,11 @@ bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int l
Common::AlignUp(level_width * sizeof(u32), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); Common::AlignUp(level_width * sizeof(u32), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
size_t required_readback_buffer_size = level_pitch * level_height; size_t required_readback_buffer_size = level_pitch * level_height;
// 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);
// Check if the current readback buffer is large enough // Check if the current readback buffer is large enough
if (required_readback_buffer_size > s_texture_cache_entry_readback_buffer_size) if (required_readback_buffer_size > s_texture_cache_entry_readback_buffer_size)
{ {
@ -178,19 +219,20 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase*
void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length, void TextureCache::TCacheEntry::Load(u32 level, u32 width, u32 height, u32 row_length,
const u8* buffer, size_t buffer_size) const u8* buffer, size_t buffer_size)
{ {
u32 src_pitch = 4 * row_length; u32 src_pitch = GetLevelPitch(config.format, row_length);
D3D::ReplaceRGBATexture2D(m_texture->GetTex12(), buffer, width, height, src_pitch, level, D3D::ReplaceRGBATexture2D(m_texture->GetTex12(), buffer, width, height, src_pitch, level,
m_texture->GetResourceUsageState()); m_texture->GetResourceUsageState());
} }
TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config) TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConfig& config)
{ {
DXGI_FORMAT dxgi_format = GetDXGIFormatForHostFormat(config.format);
if (config.rendertarget) if (config.rendertarget)
{ {
D3DTexture2D* texture = D3DTexture2D* texture =
D3DTexture2D::Create(config.width, config.height, D3DTexture2D::Create(config.width, config.height,
TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET,
DXGI_FORMAT_R8G8B8A8_UNORM, 1, config.layers); dxgi_format, 1, config.layers);
TCacheEntry* entry = new TCacheEntry(config, texture); TCacheEntry* entry = new TCacheEntry(config, texture);
@ -204,8 +246,8 @@ TextureCacheBase::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntry
{ {
ID3D12Resource* texture_resource = nullptr; ID3D12Resource* texture_resource = nullptr;
D3D12_RESOURCE_DESC texture_resource_desc = CD3DX12_RESOURCE_DESC::Tex2D( D3D12_RESOURCE_DESC texture_resource_desc =
DXGI_FORMAT_R8G8B8A8_UNORM, config.width, config.height, 1, config.levels); CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, config.width, config.height, 1, config.levels);
CheckHR(D3D::device12->CreateCommittedResource( CheckHR(D3D::device12->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,