From e892b7f1ac426fdc8a3ac1fa28026b86cc06279b Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 21 Jul 2023 19:09:40 -0500 Subject: [PATCH] VideoBackends: add support for cube maps for OGL, Vulkan, and D3D --- Source/Core/VideoBackends/D3D/DXTexture.cpp | 4 +- .../Core/VideoBackends/D3D12/DX12Context.cpp | 3 +- .../Core/VideoBackends/D3D12/DX12Texture.cpp | 29 +++++++--- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 57 +++++++++++++++---- Source/Core/VideoBackends/OGL/OGLTexture.h | 4 +- .../Core/VideoBackends/Vulkan/VKTexture.cpp | 6 +- Source/Core/VideoCommon/TextureConfig.h | 2 + 7 files changed, 81 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index c20a8d9204..7a260eae4a 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -46,7 +46,8 @@ std::unique_ptr DXTexture::Create(const TextureConfig& config, std::s 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, 0); + bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, + config.IsCubeMap() ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0); ComPtr d3d_texture; HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf()); if (FAILED(hr)) @@ -90,6 +91,7 @@ bool DXTexture::CreateSRV() { 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, diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.cpp b/Source/Core/VideoBackends/D3D12/DX12Context.cpp index bf156b2fdb..dd8630ac3b 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Context.cpp @@ -88,7 +88,8 @@ std::vector DXContext::GetAAModes(u32 adapter_index) bool DXContext::SupportsTextureFormat(DXGI_FORMAT format) { - constexpr u32 required = D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE; + constexpr u32 required = D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_TEXTURECUBE | + D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE; D3D12_FEATURE_DATA_FORMAT_SUPPORT support = {format}; return SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, diff --git a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp index f20c37354b..a51fe7ff38 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp @@ -165,19 +165,30 @@ bool DXTexture::CreateSRVDescriptor() return false; } - D3D12_SHADER_RESOURCE_VIEW_DESC desc = {D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), - m_config.IsMultisampled() ? - D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : - D3D12_SRV_DIMENSION_TEXTURE2DARRAY, - D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING}; - if (m_config.IsMultisampled()) + 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}; + + if (m_config.IsCubeMap()) { - desc.Texture2DMSArray.ArraySize = m_config.layers; + desc.TextureCube.MostDetailedMip = 0; + desc.TextureCube.MipLevels = m_config.levels; + desc.TextureCube.ResourceMinLODClamp = 0.0f; } else { - desc.Texture2DArray.MipLevels = m_config.levels; - desc.Texture2DArray.ArraySize = m_config.layers; + if (m_config.IsMultisampled()) + { + desc.Texture2DMSArray.ArraySize = m_config.layers; + } + else + { + desc.Texture2DArray.MipLevels = m_config.levels; + desc.Texture2DArray.ArraySize = m_config.layers; + } } g_dx_context->GetDevice()->CreateShaderResourceView(m_resource.Get(), &desc, m_srv_descriptor.cpu_handle); diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index f8894a365b..70c38d14ff 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -140,7 +140,11 @@ 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 (tex_config.IsMultisampled()) + if (g_ogl_config.bSupportsTextureStorage && m_config.IsCubeMap()) + { + 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) @@ -267,29 +271,62 @@ 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 (g_ogl_config.bSupportsTextureStorage) + if (m_config.IsCubeMap()) { - glCompressedTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_internal_format, - static_cast(buffer_size), buffer); + if (g_ogl_config.bSupportsTextureStorage) + { + glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, level, 0, 0, width, + height, gl_internal_format, static_cast(buffer_size), + buffer); + } + else + { + glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, level, gl_internal_format, + width, height, 0, static_cast(buffer_size), buffer); + } } else { - glCompressedTexImage3D(target, level, gl_internal_format, width, height, 1, 0, - static_cast(buffer_size), buffer); + if (g_ogl_config.bSupportsTextureStorage) + { + glCompressedTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_internal_format, + static_cast(buffer_size), buffer); + } + else + { + glCompressedTexImage3D(target, level, gl_internal_format, width, height, 1, 0, + static_cast(buffer_size), buffer); + } } } else { GLenum gl_format = GetGLFormatForTextureFormat(m_config.format); GLenum gl_type = GetGLTypeForTextureFormat(m_config.format); - if (g_ogl_config.bSupportsTextureStorage) + if (m_config.IsCubeMap()) { - glTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_format, gl_type, buffer); + if (g_ogl_config.bSupportsTextureStorage) + { + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, level, 0, 0, width, height, + gl_format, gl_type, buffer); + } + else + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, level, gl_internal_format, width, + height, 0, gl_format, gl_type, buffer); + } } else { - glTexImage3D(target, level, gl_internal_format, width, height, 1, 0, gl_format, gl_type, - buffer); + if (g_ogl_config.bSupportsTextureStorage) + { + glTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_format, gl_type, buffer); + } + else + { + glTexImage3D(target, level, gl_internal_format, width, height, 1, 0, gl_format, gl_type, + buffer); + } } } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index 53d9d7f589..91879a6564 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -34,7 +34,9 @@ public: GLuint GetGLTextureId() const { return m_texId; } GLenum GetGLTarget() const { - return IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_ARRAY; + return m_config.IsCubeMap() ? GL_TEXTURE_CUBE_MAP : + IsMultisampled() ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : + GL_TEXTURE_2D_ARRAY; } static GLenum GetGLInternalFormatForTextureFormat(AbstractTextureFormat format, bool storage); GLenum GetGLFormatForImageTexture() const; diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index f8923b4edc..e80ce4f2f7 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -70,7 +70,8 @@ std::unique_ptr VKTexture::Create(const TextureConfig& tex_config, st VkImageCreateInfo image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr, - 0, + tex_config.IsCubeMap() ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : + static_cast(0), VK_IMAGE_TYPE_2D, GetVkFormatForHostTextureFormat(tex_config.format), {tex_config.width, tex_config.height, 1}, @@ -106,7 +107,8 @@ 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(VK_IMAGE_VIEW_TYPE_2D_ARRAY)) + if (!texture->CreateView(tex_config.IsCubeMap() ? VK_IMAGE_VIEW_TYPE_CUBE : + VK_IMAGE_VIEW_TYPE_2D_ARRAY)) return nullptr; return texture; diff --git a/Source/Core/VideoCommon/TextureConfig.h b/Source/Core/VideoCommon/TextureConfig.h index c076ff85c0..75d7387f17 100644 --- a/Source/Core/VideoCommon/TextureConfig.h +++ b/Source/Core/VideoCommon/TextureConfig.h @@ -39,6 +39,7 @@ 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. }; struct TextureConfig @@ -61,6 +62,7 @@ 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;