diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index d811458100c..70b71a03a23 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -330,28 +330,29 @@ namespace dxvk { Rc D3D9CommonTexture::CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const { DxvkImageCreateInfo imageInfo; - imageInfo.type = GetImageTypeFromResourceType(ResourceType); - imageInfo.format = m_mapping.ConversionFormatInfo.FormatColor != VK_FORMAT_UNDEFINED - ? m_mapping.ConversionFormatInfo.FormatColor - : m_mapping.FormatColor; - imageInfo.flags = 0; - imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; - imageInfo.extent.width = m_desc.Width; - imageInfo.extent.height = m_desc.Height; - imageInfo.extent.depth = m_desc.Depth; - imageInfo.numLayers = m_desc.ArraySize; - imageInfo.mipLevels = m_desc.MipLevels; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_TRANSFER_DST_BIT - | m_desc.ImageUsage; - imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT - | m_device->GetEnabledShaderStages(); - imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT - | VK_ACCESS_TRANSFER_WRITE_BIT - | VK_ACCESS_SHADER_READ_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.shared = m_desc.IsBackBuffer; + imageInfo.type = GetImageTypeFromResourceType(ResourceType); + imageInfo.format = m_mapping.ConversionFormatInfo.FormatColor != VK_FORMAT_UNDEFINED + ? m_mapping.ConversionFormatInfo.FormatColor + : m_mapping.FormatColor; + imageInfo.flags = 0; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent.width = m_desc.Width; + imageInfo.extent.height = m_desc.Height; + imageInfo.extent.depth = m_desc.Depth; + imageInfo.numLayers = m_desc.ArraySize; + imageInfo.mipLevels = m_desc.MipLevels; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | m_desc.ImageUsage; + imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | m_device->GetEnabledShaderStages(); + imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT + | VK_ACCESS_SHADER_READ_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL; + imageInfo.shared = m_desc.IsShared; + imageInfo.stableGpuAddress = m_desc.IsStableAddress; if (pSharedHandle) { imageInfo.sharing.type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index bbef9f13a2f..d01eca3d1bb 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -45,12 +45,13 @@ namespace dxvk { D3DMULTISAMPLE_TYPE MultiSample; DWORD MultisampleQuality; bool Discard; - bool IsBackBuffer; + bool IsShared; bool IsAttachmentOnly; bool IsLockable; // Additional parameters for ID3D9VkInteropDevice VkImageUsageFlags ImageUsage = 0; + bool IsStableAddress = false; }; struct D3D9ColorView { diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 3b59006df39..561895dc0c9 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -640,7 +640,7 @@ namespace dxvk { desc.Discard = FALSE; desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = FALSE; // Docs: // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked @@ -716,7 +716,7 @@ namespace dxvk { desc.Discard = FALSE; desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = FALSE; // Docs: // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked @@ -777,7 +777,7 @@ namespace dxvk { desc.Discard = FALSE; desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = FALSE; // Docs: // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked @@ -4197,7 +4197,7 @@ namespace dxvk { desc.Discard = FALSE; desc.MultiSample = MultiSample; desc.MultisampleQuality = MultisampleQuality; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = TRUE; desc.IsLockable = Lockable; @@ -4244,7 +4244,7 @@ namespace dxvk { desc.Discard = FALSE; desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = TRUE; // Docs: Off-screen plain surfaces are always lockable, regardless of their pool types. desc.IsLockable = TRUE; @@ -4314,7 +4314,7 @@ namespace dxvk { desc.Discard = Discard; desc.MultiSample = MultiSample; desc.MultisampleQuality = MultisampleQuality; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = TRUE; desc.IsLockable = IsLockableDepthStencilFormat(desc.Format); @@ -8638,7 +8638,7 @@ namespace dxvk { desc.Discard = (pPresentationParameters->Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL) != 0; desc.MultiSample = pPresentationParameters->MultiSampleType; desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality; - desc.IsBackBuffer = FALSE; + desc.IsShared = FALSE; desc.IsAttachmentOnly = TRUE; desc.IsLockable = IsLockableDepthStencilFormat(desc.Format); diff --git a/src/d3d9/d3d9_interfaces.h b/src/d3d9/d3d9_interfaces.h index c4956e597b3..84c7786f798 100644 --- a/src/d3d9/d3d9_interfaces.h +++ b/src/d3d9/d3d9_interfaces.h @@ -64,6 +64,10 @@ ID3D9VkInteropTexture : public IUnknown { * Retrieves both the image handle as well as the image's * properties. Any of the given pointers may be \c nullptr. * + * The VkImage returned by this function is only guaranteed + * to be safe for images created by ID3D9VkInteropDeviceCreateImage + * with the D3D9_VK_IMAGE_STABLE_ADDRESS flag. + * * If \c pInfo is not \c nullptr, the following rules apply: * - \c pInfo->sType \e must be \c VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO * - \c pInfo->pNext \e must be \c nullptr or point to a supported @@ -94,9 +98,29 @@ ID3D9VkInteropTexture : public IUnknown { VkImageCreateInfo* pInfo) = 0; }; +/** + * \brief D3D9 extended image flags + */ +enum D3D9VkExtImageFlagBits : uint32_t { + /// Image is used externally so it needs to be + /// in its default layout after each submission + D3D9_VK_IMAGE_STABLE_LAYOUT = 1 << 0, + + /// Requests the image to not be relocated in the future. This ensures + /// that the handle returned by GetVulkanImageInfo will remain stable. + /// NOTE: This will prevent memory defragmentation for this image. + D3D9_VK_IMAGE_STABLE_ADDRESS = 1 << 1, +}; + +/** + * \brief D3D9 extended image flags + * + * A bitfield of \c D3D9VkExtImageFlagBits + */ +using D3D9VkExtImageFlags = uint32_t; /** - * \brief D3D9 image description + * \brief D3D9 extended image description */ struct D3D9VkExtImageDesc { D3DRESOURCETYPE Type; // Can be SURFACE, TEXTURE, CUBETEXTURE, VOLUMETEXTURE @@ -113,6 +137,7 @@ struct D3D9VkExtImageDesc { bool IsAttachmentOnly; // If false, then VK_IMAGE_USAGE_SAMPLED_BIT will be added bool IsLockable; VkImageUsageFlags ImageUsage; // Additional image usage flags + D3D9VkExtImageFlags Flags; }; /** diff --git a/src/d3d9/d3d9_interop.cpp b/src/d3d9/d3d9_interop.cpp index d76ddd66329..377fce26003 100644 --- a/src/d3d9/d3d9_interop.cpp +++ b/src/d3d9/d3d9_interop.cpp @@ -313,10 +313,11 @@ namespace dxvk { desc.Discard = params->Discard; desc.MultiSample = params->MultiSample; desc.MultisampleQuality = params->MultiSampleQuality; - desc.IsBackBuffer = FALSE; + desc.IsShared = params->Flags & D3D9_VK_IMAGE_STABLE_LAYOUT; desc.IsAttachmentOnly = params->IsAttachmentOnly; desc.IsLockable = params->IsLockable; desc.ImageUsage = params->ImageUsage; + desc.IsStableAddress = params->Flags & D3D9_VK_IMAGE_STABLE_ADDRESS; D3DRESOURCETYPE textureType = params->Type == D3DRTYPE_SURFACE ? D3DRTYPE_TEXTURE : params->Type; diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 9e3a749f7b2..e2724ca7fb1 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -1016,7 +1016,7 @@ namespace dxvk { desc.Pool = D3DPOOL_DEFAULT; desc.Usage = D3DUSAGE_RENDERTARGET; desc.Discard = FALSE; - desc.IsBackBuffer = TRUE; + desc.IsShared = TRUE; // The texture will get sampled for presentation. desc.IsAttachmentOnly = FALSE; // we cannot respect D3DPRESENTFLAG_LOCKABLE_BACKBUFFER here because diff --git a/src/dxvk/dxvk_image.cpp b/src/dxvk/dxvk_image.cpp index b8628650dcd..bb68d82ae92 100644 --- a/src/dxvk/dxvk_image.cpp +++ b/src/dxvk/dxvk_image.cpp @@ -13,7 +13,8 @@ namespace dxvk { m_vkd (device->vkd()), m_properties (memFlags), m_shaderStages (util::shaderStages(createInfo.stages)), - m_info (createInfo) { + m_info (createInfo), + m_stableAddress (createInfo.stableGpuAddress) { m_allocator->registerResource(this); copyFormatList(createInfo.viewFormatCount, createInfo.viewFormats); diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index 63cba2819dd..4dd7018f1d7 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -63,6 +63,9 @@ namespace dxvk { // to be in its default layout after each submission VkBool32 shared = VK_FALSE; + // Requests the image to not be relocated in the future + VkBool32 stableGpuAddress = VK_FALSE; + // Image is likely to have a short lifetime VkBool32 transient = VK_FALSE; @@ -102,7 +105,7 @@ namespace dxvk { uint32_t viewFormatCount = 0u; // View formats to add to the compatibility list const VkFormat* viewFormats = nullptr; - // Requtes the image to not be relocated in the future + // Requests the image to not be relocated in the future VkBool32 stableGpuAddress = VK_FALSE; };