From 12dd15c8ddb587e2f76351b59e0097940061485b Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 9 Dec 2023 19:00:11 -0600 Subject: [PATCH] VideoBackends / VideoCommon: add type enum to dictate whether a texture is a 2D texture, a texture array, or a cube map; support 2D texture type across backends Co-authored-by: TellowKrinkle --- Source/Core/VideoBackends/D3D/DXTexture.cpp | 42 ++++++--- .../Core/VideoBackends/D3D12/DX12Texture.cpp | 37 ++++++-- Source/Core/VideoBackends/Metal/MTLGfx.mm | 23 ++++- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 89 ++++++++++++++++--- Source/Core/VideoBackends/OGL/OGLTexture.h | 23 ++++- .../VideoBackends/Vulkan/StateTracker.cpp | 8 +- .../Core/VideoBackends/Vulkan/VKSwapChain.cpp | 5 +- .../Core/VideoBackends/Vulkan/VKTexture.cpp | 27 +++++- Source/Core/VideoCommon/AbstractTexture.cpp | 3 +- Source/Core/VideoCommon/FrameDumper.cpp | 9 +- .../Core/VideoCommon/FramebufferManager.cpp | 36 +++++--- Source/Core/VideoCommon/OnScreenDisplay.cpp | 3 +- Source/Core/VideoCommon/OnScreenUI.cpp | 6 +- Source/Core/VideoCommon/PostProcessing.cpp | 3 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 24 +++-- Source/Core/VideoCommon/TextureConfig.h | 14 ++- 16 files changed, 271 insertions(+), 81 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index 7a260eae4a..5d791b5246 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -45,9 +45,10 @@ std::unique_ptr DXTexture::Create(const TextureConfig& config, std::s if (config.IsComputeImage()) bindflags |= D3D11_BIND_UNORDERED_ACCESS; - CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels, - bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, - config.IsCubeMap() ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0); + CD3D11_TEXTURE2D_DESC desc( + tex_format, config.width, config.height, config.layers, config.levels, bindflags, + D3D11_USAGE_DEFAULT, 0, config.samples, 0, + config.type == AbstractTextureType::Texture_CubeMap ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0); ComPtr d3d_texture; HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf()); if (FAILED(hr)) @@ -72,7 +73,8 @@ std::unique_ptr DXTexture::CreateAdopted(ComPtr text // Convert to our texture config format. TextureConfig config(desc.Width, desc.Height, desc.MipLevels, desc.ArraySize, desc.SampleDesc.Count, - D3DCommon::GetAbstractFormatForDXGIFormat(desc.Format), 0); + D3DCommon::GetAbstractFormatForDXGIFormat(desc.Format), 0, + AbstractTextureType::Texture_2DArray); if (desc.BindFlags & D3D11_BIND_RENDER_TARGET) config.flags |= AbstractTextureFlag_RenderTarget; if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) @@ -89,13 +91,33 @@ std::unique_ptr DXTexture::CreateAdopted(ComPtr text bool DXTexture::CreateSRV() { + D3D_SRV_DIMENSION dimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + if (m_config.type == AbstractTextureType::Texture_2DArray) + { + if (m_config.IsMultisampled()) + dimension = D3D_SRV_DIMENSION_TEXTURE2DMSARRAY; + else + dimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY; + } + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (m_config.IsMultisampled()) + dimension = D3D_SRV_DIMENSION_TEXTURE2DMS; + else + dimension = D3D_SRV_DIMENSION_TEXTURE2D; + } + else if (m_config.type == AbstractTextureType::Texture_CubeMap) + { + dimension = D3D_SRV_DIMENSION_TEXTURECUBE; + } + else + { + PanicAlertFmt("Failed to create D3D SRV - unhandled type"); + return false; + } const CD3D11_SHADER_RESOURCE_VIEW_DESC desc( - m_texture.Get(), - m_config.IsCubeMap() ? D3D11_SRV_DIMENSION_TEXTURECUBE : - m_config.IsMultisampled() ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY : - D3D11_SRV_DIMENSION_TEXTURE2DARRAY, - D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0, - m_config.layers); + m_texture.Get(), dimension, D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, + m_config.levels, 0, m_config.layers); DEBUG_ASSERT(!m_srv); HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, m_srv.GetAddressOf()); if (FAILED(hr)) diff --git a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp index 400867d458..4a1faf6f97 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp @@ -140,7 +140,8 @@ std::unique_ptr DXTexture::CreateAdopted(ID3D12Resource* resource) } TextureConfig config(static_cast(desc.Width), desc.Height, desc.MipLevels, - desc.DepthOrArraySize, desc.SampleDesc.Count, format, 0); + desc.DepthOrArraySize, desc.SampleDesc.Count, format, 0, + AbstractTextureType::Texture_2DArray); if (desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) { @@ -165,14 +166,34 @@ bool DXTexture::CreateSRVDescriptor() return false; } - D3D12_SHADER_RESOURCE_VIEW_DESC desc = { - D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), - m_config.IsCubeMap() ? D3D12_SRV_DIMENSION_TEXTURECUBE : - m_config.IsMultisampled() ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : - D3D12_SRV_DIMENSION_TEXTURE2DARRAY, - D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING}; + D3D12_SRV_DIMENSION dimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + if (m_config.type == AbstractTextureType::Texture_2DArray) + { + if (m_config.IsMultisampled()) + dimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; + else + dimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + } + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (m_config.IsMultisampled()) + dimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + else + dimension = D3D12_SRV_DIMENSION_TEXTURE2D; + } + else if (m_config.type == AbstractTextureType::Texture_CubeMap) + { + dimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + } + else + { + PanicAlertFmt("Failed to allocate SRV - unhandled type"); + return false; + } + D3D12_SHADER_RESOURCE_VIEW_DESC desc = {D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), + dimension, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING}; - if (m_config.IsCubeMap()) + if (m_config.type == AbstractTextureType::Texture_CubeMap) { desc.TextureCube.MostDetailedMip = 0; desc.TextureCube.MipLevels = m_config.levels; diff --git a/Source/Core/VideoBackends/Metal/MTLGfx.mm b/Source/Core/VideoBackends/Metal/MTLGfx.mm index acc79683ef..d594117de5 100644 --- a/Source/Core/VideoBackends/Metal/MTLGfx.mm +++ b/Source/Core/VideoBackends/Metal/MTLGfx.mm @@ -36,14 +36,29 @@ bool Metal::Gfx::IsHeadless() const // MARK: Texture Creation +static MTLTextureType FromAbstract(AbstractTextureType type, bool multisample) +{ + switch (type) + { + case AbstractTextureType::Texture_2D: + return multisample ? MTLTextureType2DMultisample : MTLTextureType2D; + case AbstractTextureType::Texture_2DArray: + return multisample ? MTLTextureType2DMultisampleArray : MTLTextureType2DArray; + case AbstractTextureType::Texture_CubeMap: + return MTLTextureTypeCube; + } + + ASSERT(false); + return MTLTextureType2DArray; +} + std::unique_ptr Metal::Gfx::CreateTexture(const TextureConfig& config, std::string_view name) { @autoreleasepool { MRCOwned desc = MRCTransfer([MTLTextureDescriptor new]); - [desc setTextureType:config.samples > 1 ? MTLTextureType2DMultisampleArray : - MTLTextureType2DArray]; + [desc setTextureType:FromAbstract(config.type, config.samples > 1)]; [desc setPixelFormat:Util::FromAbstract(config.format)]; [desc setWidth:config.width]; [desc setHeight:config.height]; @@ -490,8 +505,8 @@ void Metal::Gfx::SetupSurface() [m_layer setDrawableSize:{static_cast(info.width), static_cast(info.height)}]; - TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format, - AbstractTextureFlag_RenderTarget); + TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format, AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); m_bb_texture = std::make_unique(nullptr, cfg); m_backbuffer = std::make_unique( m_bb_texture.get(), nullptr, std::vector{}, info.width, info.height, 1, 1); diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 70c38d14ff..58f1b10a04 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -140,29 +140,61 @@ OGLTexture::OGLTexture(const TextureConfig& tex_config, std::string_view name) glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, m_config.levels - 1); GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true); - if (g_ogl_config.bSupportsTextureStorage && m_config.IsCubeMap()) + if (g_ogl_config.bSupportsTextureStorage && m_config.type == AbstractTextureType::Texture_CubeMap) { glTexStorage2D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height); } else if (tex_config.IsMultisampled()) { ASSERT(g_ogl_config.bSupportsMSAA); - if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone) + if (m_config.type == AbstractTextureType::Texture_2DArray) { - glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone) + { + glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + m_config.height, m_config.layers, GL_FALSE); + } + else + { + ASSERT(!g_ogl_config.bIsES); + glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, m_config.height, m_config.layers, GL_FALSE); + } + } + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone) + { + glTexStorage2DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + m_config.height, GL_FALSE); + } + else + { + ASSERT(!g_ogl_config.bIsES); + glTexImage2DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, + m_config.height, GL_FALSE); + } } else { - ASSERT(!g_ogl_config.bIsES); - glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width, - m_config.height, m_config.layers, GL_FALSE); + ASSERT(false); } } else if (g_ogl_config.bSupportsTextureStorage) { - glTexStorage3D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height, - m_config.layers); + if (m_config.type == AbstractTextureType::Texture_2DArray) + { + glTexStorage3D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height, + m_config.layers); + } + else if (m_config.type == AbstractTextureType::Texture_2D) + { + glTexStorage2D(target, m_config.levels, gl_internal_format, m_config.width, m_config.height); + } + else + { + ASSERT(false); + } } if (m_config.IsRenderTarget()) @@ -271,7 +303,7 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, false); if (IsCompressedFormat(m_config.format)) { - if (m_config.IsCubeMap()) + if (m_config.type == AbstractTextureType::Texture_CubeMap) { if (g_ogl_config.bSupportsTextureStorage) { @@ -285,7 +317,20 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 width, height, 0, static_cast(buffer_size), buffer); } } - else + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (g_ogl_config.bSupportsTextureStorage) + { + glCompressedTexSubImage2D(target, level, 0, 0, width, height, gl_internal_format, + static_cast(buffer_size), buffer); + } + else + { + glCompressedTexImage2D(target, level, gl_internal_format, width, height, 0, + static_cast(buffer_size), buffer); + } + } + else if (m_config.type == AbstractTextureType::Texture_2DArray) { if (g_ogl_config.bSupportsTextureStorage) { @@ -298,12 +343,16 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 static_cast(buffer_size), buffer); } } + else + { + PanicAlertFmt("Failed to handle compressed texture load - unhandled type"); + } } else { GLenum gl_format = GetGLFormatForTextureFormat(m_config.format); GLenum gl_type = GetGLTypeForTextureFormat(m_config.format); - if (m_config.IsCubeMap()) + if (m_config.type == AbstractTextureType::Texture_CubeMap) { if (g_ogl_config.bSupportsTextureStorage) { @@ -316,7 +365,19 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 height, 0, gl_format, gl_type, buffer); } } - else + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (g_ogl_config.bSupportsTextureStorage) + { + glTexSubImage2D(target, level, 0, 0, width, height, gl_format, gl_type, buffer); + } + else + { + glTexImage2D(target, level, gl_internal_format, width, height, 0, gl_format, gl_type, + buffer); + } + } + else if (m_config.type == AbstractTextureType::Texture_2DArray) { if (g_ogl_config.bSupportsTextureStorage) { @@ -328,6 +389,10 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 buffer); } } + else + { + PanicAlertFmt("Failed to handle texture load - unhandled type"); + } } if (row_length != width) diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index 91879a6564..eea458c5a1 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -34,9 +34,26 @@ public: GLuint GetGLTextureId() const { return m_texId; } GLenum GetGLTarget() const { - return m_config.IsCubeMap() ? GL_TEXTURE_CUBE_MAP : - IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : - GL_TEXTURE_2D_ARRAY; + if (m_config.type == AbstractTextureType::Texture_2DArray) + { + if (m_config.IsMultisampled()) + return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + else + return GL_TEXTURE_2D_ARRAY; + } + else if (m_config.type == AbstractTextureType::Texture_2D) + { + if (m_config.IsMultisampled()) + return GL_TEXTURE_2D_MULTISAMPLE; + else + return GL_TEXTURE_2D; + } + else if (m_config.type == AbstractTextureType::Texture_CubeMap) + { + return GL_TEXTURE_CUBE_MAP; + } + + return GL_TEXTURE_2D_ARRAY; } static GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage); GLenum GetGLFormatForImageTexture() const; diff --git a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp index 4afd627614..332cd41cbf 100644 --- a/Source/Core/VideoBackends/Vulkan/StateTracker.cpp +++ b/Source/Core/VideoBackends/Vulkan/StateTracker.cpp @@ -60,15 +60,17 @@ void StateTracker::DestroyInstance() bool StateTracker::Initialize() { // Create a dummy texture which can be used in place of a real binding. - m_dummy_texture = - VKTexture::Create(TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, 0), ""); + m_dummy_texture = VKTexture::Create(TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray), + ""); if (!m_dummy_texture) return false; m_dummy_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // Create a dummy compute texture which can be used in place of a real binding m_dummy_compute_texture = VKTexture::Create( - TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage), + TextureConfig(1, 1, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage, + AbstractTextureType::Texture_2DArray), ""); if (!m_dummy_compute_texture) return false; diff --git a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp index 48102df64d..58e2e439e8 100644 --- a/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKSwapChain.cpp @@ -428,8 +428,9 @@ bool SwapChain::SetupSwapChainImages() images.data()); ASSERT(res == VK_SUCCESS); - const TextureConfig texture_config(TextureConfig( - m_width, m_height, 1, m_layers, 1, m_texture_format, AbstractTextureFlag_RenderTarget)); + const TextureConfig texture_config( + TextureConfig(m_width, m_height, 1, m_layers, 1, m_texture_format, + AbstractTextureFlag_RenderTarget, AbstractTextureType::Texture_2DArray)); const VkRenderPass load_render_pass = g_object_cache->GetRenderPass( m_surface_format.format, VK_FORMAT_UNDEFINED, 1, VK_ATTACHMENT_LOAD_OP_LOAD); const VkRenderPass clear_render_pass = g_object_cache->GetRenderPass( diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index e80ce4f2f7..6756305d1e 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -70,8 +70,9 @@ std::unique_ptr VKTexture::Create(const TextureConfig& tex_config, st VkImageCreateInfo image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr, - tex_config.IsCubeMap() ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : - static_cast(0), + tex_config.type == AbstractTextureType::Texture_CubeMap ? + VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : + static_cast(0), VK_IMAGE_TYPE_2D, GetVkFormatForHostTextureFormat(tex_config.format), {tex_config.width, tex_config.height, 1}, @@ -107,8 +108,26 @@ std::unique_ptr VKTexture::Create(const TextureConfig& tex_config, st std::unique_ptr texture = std::make_unique( tex_config, alloc, image, name, VK_IMAGE_LAYOUT_UNDEFINED, ComputeImageLayout::Undefined); - if (!texture->CreateView(tex_config.IsCubeMap() ? VK_IMAGE_VIEW_TYPE_CUBE : - VK_IMAGE_VIEW_TYPE_2D_ARRAY)) + + VkImageViewType image_view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + if (tex_config.type == AbstractTextureType::Texture_CubeMap) + { + image_view_type = VK_IMAGE_VIEW_TYPE_CUBE; + } + else if (tex_config.type == AbstractTextureType::Texture_2D) + { + image_view_type = VK_IMAGE_VIEW_TYPE_2D; + } + else if (tex_config.type == AbstractTextureType::Texture_2DArray) + { + image_view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } + else + { + PanicAlertFmt("Unhandled texture type."); + return nullptr; + } + if (!texture->CreateView(image_view_type)) return nullptr; return texture; diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp index 416af06123..08eec74fa3 100644 --- a/Source/Core/VideoCommon/AbstractTexture.cpp +++ b/Source/Core/VideoCommon/AbstractTexture.cpp @@ -37,7 +37,8 @@ bool AbstractTexture::Save(const std::string& filename, unsigned int level, int // Use a temporary staging texture for the download. Certainly not optimal, // but this is not a frequently-executed code path.. TextureConfig readback_texture_config(level_width, level_height, 1, 1, 1, - AbstractTextureFormat::RGBA8, 0); + AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); auto readback_texture = g_gfx->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config); if (!readback_texture) diff --git a/Source/Core/VideoCommon/FrameDumper.cpp b/Source/Core/VideoCommon/FrameDumper.cpp index 06bbe1b1c9..d45d9933be 100644 --- a/Source/Core/VideoCommon/FrameDumper.cpp +++ b/Source/Core/VideoCommon/FrameDumper.cpp @@ -82,7 +82,7 @@ bool FrameDumper::CheckFrameDumpRenderTexture(u32 target_width, u32 target_heigh m_frame_dump_render_texture.reset(); m_frame_dump_render_texture = g_gfx->CreateTexture( TextureConfig(target_width, target_height, 1, 1, 1, AbstractTextureFormat::RGBA8, - AbstractTextureFlag_RenderTarget), + AbstractTextureFlag_RenderTarget, AbstractTextureType::Texture_2DArray), "Frame dump render texture"); if (!m_frame_dump_render_texture) { @@ -102,9 +102,10 @@ bool FrameDumper::CheckFrameDumpReadbackTexture(u32 target_width, u32 target_hei return true; rbtex.reset(); - rbtex = g_gfx->CreateStagingTexture( - StagingTextureType::Readback, - TextureConfig(target_width, target_height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0)); + rbtex = g_gfx->CreateStagingTexture(StagingTextureType::Readback, + TextureConfig(target_width, target_height, 1, 1, 1, + AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray)); if (!rbtex) return false; diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp index 4bdc3616a9..9790551afb 100644 --- a/Source/Core/VideoCommon/FramebufferManager.cpp +++ b/Source/Core/VideoCommon/FramebufferManager.cpp @@ -152,13 +152,15 @@ static u32 CalculateEFBLayers() TextureConfig FramebufferManager::GetEFBColorTextureConfig(u32 width, u32 height) { return TextureConfig(width, height, 1, CalculateEFBLayers(), g_ActiveConfig.iMultisamples, - GetEFBColorFormat(), AbstractTextureFlag_RenderTarget); + GetEFBColorFormat(), AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); } TextureConfig FramebufferManager::GetEFBDepthTextureConfig(u32 width, u32 height) { return TextureConfig(width, height, 1, CalculateEFBLayers(), g_ActiveConfig.iMultisamples, - GetEFBDepthFormat(), AbstractTextureFlag_RenderTarget); + GetEFBDepthFormat(), AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); } FramebufferState FramebufferManager::GetEFBFramebufferState() const @@ -254,7 +256,8 @@ bool FramebufferManager::CreateEFBFramebuffer() flags |= AbstractTextureFlag_RenderTarget; m_efb_resolve_color_texture = g_gfx->CreateTexture( TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1, - efb_color_texture_config.layers, 1, efb_color_texture_config.format, flags), + efb_color_texture_config.layers, 1, efb_color_texture_config.format, flags, + AbstractTextureType::Texture_2DArray), "EFB color resolve texture"); if (!m_efb_resolve_color_texture) return false; @@ -274,7 +277,7 @@ bool FramebufferManager::CreateEFBFramebuffer() m_efb_depth_resolve_texture = g_gfx->CreateTexture( TextureConfig(efb_depth_texture_config.width, efb_depth_texture_config.height, 1, efb_depth_texture_config.layers, 1, GetEFBDepthCopyFormat(), - AbstractTextureFlag_RenderTarget), + AbstractTextureFlag_RenderTarget, AbstractTextureType::Texture_2DArray), "EFB depth resolve texture"); if (!m_efb_depth_resolve_texture) return false; @@ -695,7 +698,8 @@ bool FramebufferManager::CreateReadbackFramebuffer() { const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, - 1, 1, GetEFBColorFormat(), AbstractTextureFlag_RenderTarget); + 1, 1, GetEFBColorFormat(), AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); m_efb_color_cache.texture = g_gfx->CreateTexture(color_config, "EFB color cache"); if (!m_efb_color_cache.texture) return false; @@ -717,7 +721,8 @@ bool FramebufferManager::CreateReadbackFramebuffer() const TextureConfig depth_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), - AbstractTextureFlag_RenderTarget); + AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); m_efb_depth_cache.texture = g_gfx->CreateTexture(depth_config, "EFB depth cache"); if (!m_efb_depth_cache.texture) return false; @@ -729,12 +734,14 @@ bool FramebufferManager::CreateReadbackFramebuffer() } // Staging texture use the full EFB dimensions, as this is the buffer for the whole cache. - m_efb_color_cache.readback_texture = g_gfx->CreateStagingTexture( - StagingTextureType::Mutable, - TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), 0)); + m_efb_color_cache.readback_texture = + g_gfx->CreateStagingTexture(StagingTextureType::Mutable, + TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), + 0, AbstractTextureType::Texture_2DArray)); m_efb_depth_cache.readback_texture = g_gfx->CreateStagingTexture( StagingTextureType::Mutable, - TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), 0)); + TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), 0, + AbstractTextureType::Texture_2DArray)); if (!m_efb_color_cache.readback_texture || !m_efb_depth_cache.readback_texture) return false; @@ -1116,14 +1123,15 @@ void FramebufferManager::DoSaveState(PointerWrap& p) AbstractTexture* depth_texture = ResolveEFBDepthTexture(m_efb_depth_texture->GetRect(), true); // We don't want to save these as rendertarget textures, just the data itself when deserializing. - const TextureConfig color_texture_config(color_texture->GetWidth(), color_texture->GetHeight(), - color_texture->GetLevels(), color_texture->GetLayers(), - 1, GetEFBColorFormat(), 0); + const TextureConfig color_texture_config( + color_texture->GetWidth(), color_texture->GetHeight(), color_texture->GetLevels(), + color_texture->GetLayers(), 1, GetEFBColorFormat(), 0, AbstractTextureType::Texture_2DArray); g_texture_cache->SerializeTexture(color_texture, color_texture_config, p); const TextureConfig depth_texture_config(depth_texture->GetWidth(), depth_texture->GetHeight(), depth_texture->GetLevels(), depth_texture->GetLayers(), - 1, GetEFBDepthCopyFormat(), 0); + 1, GetEFBDepthCopyFormat(), 0, + AbstractTextureType::Texture_2DArray); g_texture_cache->SerializeTexture(depth_texture, depth_texture_config, p); } diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp index 0e07dbc397..bfa8bc5321 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp @@ -90,7 +90,8 @@ static float DrawMessage(int index, Message& msg, const ImVec2& position, int ti { const u32 width = msg.icon->width; const u32 height = msg.icon->height; - TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0); + TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); msg.texture = g_gfx->CreateTexture(tex_config); if (msg.texture) { diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp index 88141736e4..fdb5d49af7 100644 --- a/Source/Core/VideoCommon/OnScreenUI.cpp +++ b/Source/Core/VideoCommon/OnScreenUI.cpp @@ -77,7 +77,8 @@ bool OnScreenUI::Initialize(u32 width, u32 height, float scale) io.Fonts->GetTexDataAsRGBA32(&font_tex_pixels, &font_tex_width, &font_tex_height); TextureConfig font_tex_config(font_tex_width, font_tex_height, 1, 1, 1, - AbstractTextureFormat::RGBA8, 0); + AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); std::unique_ptr font_tex = g_gfx->CreateTexture(font_tex_config, "ImGui font texture"); if (!font_tex) @@ -362,7 +363,8 @@ void OnScreenUI::DrawChallenges() continue; const u32 width = icon->width; const u32 height = icon->height; - TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0); + TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); auto res = m_challenge_texture_map.insert_or_assign(name, g_gfx->CreateTexture(tex_config)); res.first->second->Load(0, width, height, width, icon->rgba_data.data(), sizeof(u32) * width * height); diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp index 615d853a45..1458e3c59f 100644 --- a/Source/Core/VideoCommon/PostProcessing.cpp +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -530,7 +530,8 @@ void PostProcessing::BlitFromTexture(const MathUtil::Rectangle& dst, { const TextureConfig intermediary_color_texture_config( target_width, target_height, 1, target_layers, src_tex->GetSamples(), - s_intermediary_buffer_format, AbstractTextureFlag_RenderTarget); + s_intermediary_buffer_format, AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); m_intermediary_color_texture = g_gfx->CreateTexture(intermediary_color_texture_config, "Intermediary post process texture"); diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 2c749c7703..9294748397 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -415,7 +415,8 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(RcTcacheEntry& entry, u32 new_wi } const TextureConfig newconfig(new_width, new_height, 1, entry->GetNumLayers(), 1, - AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget); + AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); std::optional new_texture = AllocateTexture(newconfig); if (!new_texture) { @@ -445,7 +446,8 @@ bool TextureCacheBase::CheckReadbackTexture(u32 width, u32 height, AbstractTextu return true; } - TextureConfig staging_config(std::max(width, 128u), std::max(height, 128u), 1, 1, 1, format, 0); + TextureConfig staging_config(std::max(width, 128u), std::max(height, 128u), 1, 1, 1, format, 0, + AbstractTextureType::Texture_2DArray); m_readback_texture.reset(); m_readback_texture = g_gfx->CreateStagingTexture(StagingTextureType::Readback, staging_config); return m_readback_texture != nullptr; @@ -1680,7 +1682,8 @@ RcTcacheEntry TextureCacheBase::CreateTextureEntry( const u32 texLevels = no_mips ? 1 : (u32)calculate_max_levels(); const auto& first_level = assets_data[0]->m_texture.m_slices[0].m_levels[0]; const TextureConfig config(first_level.width, first_level.height, texLevels, - static_cast(assets_data.size()), 1, first_level.format, 0); + static_cast(assets_data.size()), 1, first_level.format, 0, + AbstractTextureType::Texture_2DArray); entry = AllocateCacheEntry(config); if (!entry) [[unlikely]] return entry; @@ -1710,7 +1713,8 @@ RcTcacheEntry TextureCacheBase::CreateTextureEntry( const u32 width = texture_info.GetRawWidth(); const u32 height = texture_info.GetRawHeight(); - const TextureConfig config(width, height, texLevels, 1, 1, AbstractTextureFormat::RGBA8, 0); + const TextureConfig config(width, height, texLevels, 1, 1, AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); entry = AllocateCacheEntry(config); if (!entry) [[unlikely]] return entry; @@ -1896,7 +1900,8 @@ RcTcacheEntry TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height // Create a new VRAM texture, and fill it with the data from guest RAM. entry = AllocateCacheEntry(TextureConfig(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, - AbstractTextureFlag_RenderTarget)); + AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray)); // Compute total texture size. XFB textures aren't tiled, so this is simple. const u32 total_size = height * stride; @@ -2357,7 +2362,8 @@ void TextureCacheBase::CopyRenderTargetToTexture( { // create the texture const TextureConfig config(scaled_tex_w, scaled_tex_h, 1, g_framebuffer_manager->GetEFBLayers(), - 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget); + 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); entry = AllocateCacheEntry(config); if (entry) { @@ -2842,7 +2848,8 @@ void TextureCacheBase::ReleaseToPool(TCacheEntry* entry) bool TextureCacheBase::CreateUtilityTextures() { constexpr TextureConfig encoding_texture_config( - EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8, AbstractTextureFlag_RenderTarget); + EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8, AbstractTextureFlag_RenderTarget, + AbstractTextureType::Texture_2DArray); m_efb_encoding_texture = g_gfx->CreateTexture(encoding_texture_config, "EFB encoding texture"); if (!m_efb_encoding_texture) return false; @@ -2854,7 +2861,8 @@ bool TextureCacheBase::CreateUtilityTextures() if (g_ActiveConfig.backend_info.bSupportsGPUTextureDecoding) { constexpr TextureConfig decoding_texture_config( - 1024, 1024, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage); + 1024, 1024, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage, + AbstractTextureType::Texture_2DArray); m_decoding_texture = g_gfx->CreateTexture(decoding_texture_config, "GPU texture decoding texture"); if (!m_decoding_texture) diff --git a/Source/Core/VideoCommon/TextureConfig.h b/Source/Core/VideoCommon/TextureConfig.h index 75d7387f17..462b3dddff 100644 --- a/Source/Core/VideoCommon/TextureConfig.h +++ b/Source/Core/VideoCommon/TextureConfig.h @@ -39,16 +39,22 @@ enum AbstractTextureFlag : u32 { AbstractTextureFlag_RenderTarget = (1 << 0), // Texture is used as a framebuffer. AbstractTextureFlag_ComputeImage = (1 << 1), // Texture is used as a compute image. - AbstractTextureFlag_CubeMap = (1 << 2), // Texture is used as a cube map. +}; + +enum class AbstractTextureType +{ + Texture_2DArray, // Used as a 2D texture array + Texture_2D, // Used as a normal 2D texture + Texture_CubeMap, // Used as a cube map texture }; struct TextureConfig { constexpr TextureConfig() = default; constexpr TextureConfig(u32 width_, u32 height_, u32 levels_, u32 layers_, u32 samples_, - AbstractTextureFormat format_, u32 flags_) + AbstractTextureFormat format_, u32 flags_, AbstractTextureType type_) : width(width_), height(height_), levels(levels_), layers(layers_), samples(samples_), - format(format_), flags(flags_) + format(format_), flags(flags_), type(type_) { } @@ -62,7 +68,6 @@ struct TextureConfig bool IsMultisampled() const { return samples > 1; } bool IsRenderTarget() const { return (flags & AbstractTextureFlag_RenderTarget) != 0; } bool IsComputeImage() const { return (flags & AbstractTextureFlag_ComputeImage) != 0; } - bool IsCubeMap() const { return (flags & AbstractTextureFlag_CubeMap) != 0; } u32 width = 0; u32 height = 0; @@ -71,6 +76,7 @@ struct TextureConfig u32 samples = 1; AbstractTextureFormat format = AbstractTextureFormat::RGBA8; u32 flags = 0; + AbstractTextureType type = AbstractTextureType::Texture_2DArray; }; namespace std