From 11aa2a703ae4f23edb92bd4306cbbae0aa03dbc6 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 21 Jun 2021 22:53:13 +0200 Subject: [PATCH] [d3d11] Introduce D3D11_COMMON_TEXTURE_MAP_MODE_STAGING This map mode can be used when no Vulkan image is needed to back a staging resource, which can save a significant amount of memory. --- src/d3d11/d3d11_texture.cpp | 37 ++++++++++++++++++++++--------------- src/d3d11/d3d11_texture.h | 19 ++++++++++++++++--- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index e2d2c807..4d31db93 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -10,7 +10,7 @@ namespace dxvk { D3D11_RESOURCE_DIMENSION Dimension, DXGI_USAGE DxgiUsage, VkImage vkImage) - : m_device(pDevice), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) { + : m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) { DXGI_VK_FORMAT_MODE formatMode = GetFormatMode(); DXGI_VK_FORMAT_INFO formatInfo = m_device->LookupFormat(m_desc.Format, formatMode); DXGI_VK_FORMAT_FAMILY formatFamily = m_device->LookupFamily(m_desc.Format, formatMode); @@ -153,6 +153,22 @@ namespace dxvk { imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; } + // If necessary, create the mapped linear buffer + if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { + for (uint32_t i = 0; i < m_desc.ArraySize; i++) { + for (uint32_t j = 0; j < m_desc.MipLevels; j++) { + if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT) + m_buffers.push_back(CreateMappedBuffer(j)); + + m_mapTypes.push_back(D3D11_MAP(~0u)); + } + } + } + + // Skip image creation if possible + if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) + return; + // We must keep LINEAR images in GENERAL layout, but we // can choose a better layout for the image based on how // it is going to be used by the game. @@ -194,16 +210,6 @@ namespace dxvk { m_image = m_device->GetDXVKDevice()->createImage(imageInfo, memoryProperties); else m_image = m_device->GetDXVKDevice()->createImageFromVkImage(imageInfo, vkImage); - - // If necessary, create the mapped linear buffer - for (uint32_t i = 0; i < m_desc.ArraySize; i++) { - for (uint32_t j = 0; j < m_desc.MipLevels; j++) { - if (m_mapMode == D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER) - m_buffers.push_back(CreateMappedBuffer(j)); - if (m_mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) - m_mapTypes.push_back(D3D11_MAP(~0u)); - } - } } @@ -238,7 +244,8 @@ namespace dxvk { layout.DepthPitch = vkLayout.depthPitch; } break; - case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER: { + case D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER: + case D3D11_COMMON_TEXTURE_MAP_MODE_STAGING: { auto formatInfo = imageFormatInfo(m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format); auto aspects = Aspect; @@ -247,7 +254,7 @@ namespace dxvk { if (aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) aspects = VK_IMAGE_ASPECT_DEPTH_BIT; - VkExtent3D mipExtent = m_image->mipLevelExtent(subresource.mipLevel); + VkExtent3D mipExtent = MipLevelExtent(subresource.mipLevel); while (aspects) { auto aspect = vk::getNextAspect(aspects); @@ -277,8 +284,8 @@ namespace dxvk { } // D3D wants us to return the total subresource size in some instances - if (m_image->info().type < VK_IMAGE_TYPE_2D) layout.RowPitch = layout.Size; - if (m_image->info().type < VK_IMAGE_TYPE_3D) layout.DepthPitch = layout.Size; + if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE2D) layout.RowPitch = layout.Size; + if (m_dimension < D3D11_RESOURCE_DIMENSION_TEXTURE3D) layout.DepthPitch = layout.Size; return layout; } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 3b0ace60..29e27767 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -20,9 +20,10 @@ namespace dxvk { * behave when mapping an image. */ enum D3D11_COMMON_TEXTURE_MAP_MODE { - D3D11_COMMON_TEXTURE_MAP_MODE_NONE, ///< Not mapped - D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, ///< Mapped through buffer - D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, ///< Directly mapped to host mem + D3D11_COMMON_TEXTURE_MAP_MODE_NONE, ///< Not mapped + D3D11_COMMON_TEXTURE_MAP_MODE_BUFFER, ///< Mapped through buffer + D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT, ///< Directly mapped to host mem + D3D11_COMMON_TEXTURE_MAP_MODE_STAGING, ///< Buffer only, no image }; @@ -90,6 +91,17 @@ namespace dxvk { return &m_desc; } + /** + * \brief Computes extent of a given mip level + * + * This also works for staging resources that have no image. + * \param [in] Level Mip level to compute the size of + */ + VkExtent3D MipLevelExtent(uint32_t Level) const { + return util::computeMipLevelExtent( + VkExtent3D { m_desc.Width, m_desc.Height, m_desc.Depth }, Level); + } + /** * \brief Special DXGI usage flags * @@ -247,6 +259,7 @@ namespace dxvk { private: D3D11Device* const m_device; + D3D11_RESOURCE_DIMENSION m_dimension; D3D11_COMMON_TEXTURE_DESC m_desc; D3D11_COMMON_TEXTURE_MAP_MODE m_mapMode; DXGI_USAGE m_dxgiUsage;