diff --git a/src/microsoft/vulkan/dzn_image.c b/src/microsoft/vulkan/dzn_image.c index b907f513d90..16d6f785841 100644 --- a/src/microsoft/vulkan/dzn_image.c +++ b/src/microsoft/vulkan/dzn_image.c @@ -587,6 +587,53 @@ dzn_image_layout_to_state(const struct dzn_image *image, } } +bool +dzn_image_formats_are_compatible(const struct dzn_device *device, + VkFormat orig_fmt, VkFormat new_fmt, + VkImageUsageFlags usage, + VkImageAspectFlagBits aspect) +{ + const struct dzn_physical_device *pdev = + container_of(device->vk.physical, struct dzn_physical_device, vk); + DXGI_FORMAT orig_dxgi = dzn_image_get_dxgi_format(orig_fmt, usage, aspect); + DXGI_FORMAT new_dxgi = dzn_image_get_dxgi_format(new_fmt, usage, aspect); + + if (orig_dxgi == new_dxgi) + return true; + + DXGI_FORMAT typeless_orig = dzn_get_typeless_dxgi_format(orig_dxgi); + DXGI_FORMAT typeless_new = dzn_get_typeless_dxgi_format(new_dxgi); + + if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) + return typeless_orig == typeless_new; + + if (pdev->options3.CastingFullyTypedFormatSupported) { + enum pipe_format orig_pfmt = vk_format_to_pipe_format(orig_fmt); + enum pipe_format new_pfmt = vk_format_to_pipe_format(new_fmt); + + /* Types don't belong to the same group, they're incompatible. */ + if (typeless_orig != typeless_new) + return false; + + /* FLOAT <-> non-FLOAT casting is disallowed. */ + if (util_format_is_float(orig_pfmt) != util_format_is_float(new_pfmt)) + return false; + + /* UNORM <-> SNORM casting is disallowed. */ + bool orig_is_norm = + util_format_is_unorm(orig_pfmt) || util_format_is_snorm(orig_pfmt); + bool new_is_norm = + util_format_is_unorm(new_pfmt) || util_format_is_snorm(new_pfmt); + if (orig_is_norm && new_is_norm && + util_format_is_unorm(orig_pfmt) != util_format_is_unorm(new_pfmt)) + return false; + + return true; + } + + return false; +} + VKAPI_ATTR VkResult VKAPI_CALL dzn_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h index 8d3b9b9ee8e..4c063ec001e 100644 --- a/src/microsoft/vulkan/dzn_private.h +++ b/src/microsoft/vulkan/dzn_private.h @@ -878,6 +878,12 @@ struct dzn_image { VkDeviceSize mem_offset; }; +bool +dzn_image_formats_are_compatible(const struct dzn_device *device, + VkFormat orig_fmt, VkFormat new_fmt, + VkImageUsageFlags usage, + VkImageAspectFlagBits aspect); + void dzn_image_align_extent(const struct dzn_image *image, VkExtent3D *extent); @@ -998,6 +1004,7 @@ struct dzn_sampler { (_image)->vk.mip_levels - (_range)->baseMipLevel : (_range)->levelCount) DXGI_FORMAT dzn_pipe_to_dxgi_format(enum pipe_format in); +DXGI_FORMAT dzn_get_typeless_dxgi_format(DXGI_FORMAT in); D3D12_FILTER dzn_translate_sampler_filter(const VkSamplerCreateInfo *create_info); D3D12_COMPARISON_FUNC dzn_translate_compare_op(VkCompareOp in); void dzn_translate_viewport(D3D12_VIEWPORT *out, const VkViewport *in); diff --git a/src/microsoft/vulkan/dzn_util.c b/src/microsoft/vulkan/dzn_util.c index ba75301c109..753e664234b 100644 --- a/src/microsoft/vulkan/dzn_util.c +++ b/src/microsoft/vulkan/dzn_util.c @@ -155,6 +155,59 @@ dzn_pipe_to_dxgi_format(enum pipe_format in) return formats[in]; } +DXGI_FORMAT +dzn_get_typeless_dxgi_format(DXGI_FORMAT in) +{ + if (in >= DXGI_FORMAT_R32G32B32A32_TYPELESS && in <= DXGI_FORMAT_R32G32B32A32_SINT) + return DXGI_FORMAT_R32G32B32A32_TYPELESS; + if (in >= DXGI_FORMAT_R32G32B32_TYPELESS && in <= DXGI_FORMAT_R32G32B32_SINT) + return DXGI_FORMAT_R32G32B32_TYPELESS; + if (in >= DXGI_FORMAT_R16G16B16A16_TYPELESS && in <= DXGI_FORMAT_R16G16B16A16_SINT) + return DXGI_FORMAT_R16G16B16A16_TYPELESS; + if (in <= DXGI_FORMAT_R32G32_TYPELESS && in >= DXGI_FORMAT_R32G32_SINT) + return DXGI_FORMAT_R32G32_TYPELESS; + if (in <= DXGI_FORMAT_R32G8X24_TYPELESS && in >= DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) + return DXGI_FORMAT_R32G8X24_TYPELESS; + if (in <= DXGI_FORMAT_R10G10B10A2_TYPELESS && in >= DXGI_FORMAT_R10G10B10A2_UINT) + return DXGI_FORMAT_R10G10B10A2_TYPELESS; + if (in <= DXGI_FORMAT_R8G8B8A8_TYPELESS && in >= DXGI_FORMAT_R8G8B8A8_SINT) + return DXGI_FORMAT_R8G8B8A8_TYPELESS; + if (in <= DXGI_FORMAT_R16G16_TYPELESS && in >= DXGI_FORMAT_R16G16_SINT) + return DXGI_FORMAT_R16G16_TYPELESS; + if (in <= DXGI_FORMAT_R32_TYPELESS && in >= DXGI_FORMAT_R32_SINT) + return DXGI_FORMAT_R32_TYPELESS; + if (in <= DXGI_FORMAT_R24G8_TYPELESS && in >= DXGI_FORMAT_X24_TYPELESS_G8_UINT) + return DXGI_FORMAT_R24G8_TYPELESS; + if (in <= DXGI_FORMAT_R8G8_TYPELESS && in >= DXGI_FORMAT_R8G8_SINT) + return DXGI_FORMAT_R8G8_TYPELESS; + if (in <= DXGI_FORMAT_R16_TYPELESS && in >= DXGI_FORMAT_R16_SINT) + return DXGI_FORMAT_R16_TYPELESS; + if (in <= DXGI_FORMAT_R8_TYPELESS && in >= DXGI_FORMAT_R8_SINT) + return DXGI_FORMAT_R8_TYPELESS; + if (in <= DXGI_FORMAT_BC1_TYPELESS && in >= DXGI_FORMAT_BC1_UNORM_SRGB) + return DXGI_FORMAT_BC1_TYPELESS; + if (in <= DXGI_FORMAT_BC2_TYPELESS && in >= DXGI_FORMAT_BC2_UNORM_SRGB) + return DXGI_FORMAT_BC2_TYPELESS; + if (in <= DXGI_FORMAT_BC3_TYPELESS && in >= DXGI_FORMAT_BC3_UNORM_SRGB) + return DXGI_FORMAT_BC3_TYPELESS; + if (in <= DXGI_FORMAT_BC4_TYPELESS && in >= DXGI_FORMAT_BC4_SNORM) + return DXGI_FORMAT_BC4_TYPELESS; + if (in <= DXGI_FORMAT_BC5_TYPELESS && in >= DXGI_FORMAT_BC5_SNORM) + return DXGI_FORMAT_BC5_TYPELESS; + if (in == DXGI_FORMAT_B8G8R8A8_UNORM || + (in <= DXGI_FORMAT_B8G8R8A8_TYPELESS && in >= DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)) + return DXGI_FORMAT_B8G8R8A8_TYPELESS; + if (in == DXGI_FORMAT_B8G8R8X8_UNORM || + (in <= DXGI_FORMAT_B8G8R8X8_TYPELESS && in >= DXGI_FORMAT_B8G8R8X8_UNORM_SRGB)) + return DXGI_FORMAT_B8G8R8X8_TYPELESS; + if (in <= DXGI_FORMAT_BC6H_TYPELESS && in >= DXGI_FORMAT_BC6H_SF16) + return DXGI_FORMAT_BC6H_TYPELESS; + if (in <= DXGI_FORMAT_BC7_TYPELESS && in >= DXGI_FORMAT_BC7_UNORM_SRGB) + return DXGI_FORMAT_BC7_TYPELESS; + + return in; +} + struct dzn_sampler_filter_info { VkFilter min, mag; VkSamplerMipmapMode mipmap;