Implement VkSamplerYcbcrConversion object Implement the vk::SamplerYcbcrConversion object and pass it to the vk::Sampler and vk::ImageView constructors if present as an VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO extension struct value. Bug: b/132437008 Tests: dEQP-VK.*ycbcr* Change-Id: I16b03dc37920dd1eee7de80a370f8f7386dc4cea Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31614 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp index 512743c..1560d0b 100644 --- a/src/Vulkan/VkImageView.cpp +++ b/src/Vulkan/VkImageView.cpp
@@ -19,10 +19,7 @@ { VkComponentMapping ResolveComponentMapping(VkComponentMapping m, vk::Format format) { - if (m.r == VK_COMPONENT_SWIZZLE_IDENTITY) m.r = VK_COMPONENT_SWIZZLE_R; - if (m.g == VK_COMPONENT_SWIZZLE_IDENTITY) m.g = VK_COMPONENT_SWIZZLE_G; - if (m.b == VK_COMPONENT_SWIZZLE_IDENTITY) m.b = VK_COMPONENT_SWIZZLE_B; - if (m.a == VK_COMPONENT_SWIZZLE_IDENTITY) m.a = VK_COMPONENT_SWIZZLE_A; + m = vk::ResolveIdentityMapping(m); // Replace non-present components with zero/one swizzles so that the sampler // will give us correct interactions between channel replacement and texel replacement, @@ -58,10 +55,11 @@ std::atomic<uint32_t> ImageView::nextID(1); -ImageView::ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem) : +ImageView::ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem, const vk::SamplerYcbcrConversion *ycbcrConversion) : image(Cast(pCreateInfo->image)), viewType(pCreateInfo->viewType), format(pCreateInfo->format), components(ResolveComponentMapping(pCreateInfo->components, format)), - subresourceRange(ResolveRemainingLevelsLayers(pCreateInfo->subresourceRange, image)) + subresourceRange(ResolveRemainingLevelsLayers(pCreateInfo->subresourceRange, image)), + ycbcrConversion(ycbcrConversion) { }
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp index 718ebd2..f857f4d 100644 --- a/src/Vulkan/VkImageView.hpp +++ b/src/Vulkan/VkImageView.hpp
@@ -24,6 +24,7 @@ namespace vk { +class SamplerYcbcrConversion; class ImageView : public Object<ImageView, VkImageView> { @@ -33,7 +34,7 @@ // SAMPLING: Image used for texture sampling enum Usage { RAW, SAMPLING }; - ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem); + ImageView(const VkImageViewCreateInfo* pCreateInfo, void* mem, const vk::SamplerYcbcrConversion *ycbcrConversion); void destroy(const VkAllocationCallbacks* pAllocator); static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo); @@ -72,6 +73,7 @@ size_t getImageSizeInBytes() const { return image->getMemoryRequirements().size; } const uint32_t id = nextID++; + private: static std::atomic<uint32_t> nextID; friend class BufferView; // ImageView/BufferView share the ID space above. @@ -84,8 +86,21 @@ const Format format; const VkComponentMapping components = {}; const VkImageSubresourceRange subresourceRange = {}; + + const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr; }; +// TODO(b/132437008): Also used by SamplerYcbcrConversion. Move somewhere centrally? +inline VkComponentMapping ResolveIdentityMapping(VkComponentMapping m) +{ + return { + (m.r == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_R : m.r, + (m.g == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_G : m.g, + (m.b == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_B : m.b, + (m.a == VK_COMPONENT_SWIZZLE_IDENTITY) ? VK_COMPONENT_SWIZZLE_A : m.a, + }; +} + static inline ImageView* Cast(VkImageView object) { return reinterpret_cast<ImageView*>(object.get());
diff --git a/src/Vulkan/VkSampler.hpp b/src/Vulkan/VkSampler.hpp index 97a7190..4313e3c 100644 --- a/src/Vulkan/VkSampler.hpp +++ b/src/Vulkan/VkSampler.hpp
@@ -16,6 +16,7 @@ #define VK_SAMPLER_HPP_ #include "VkDevice.hpp" +#include "VkImageView.hpp" // For ResolveIdentityMapping() #include "Device/Config.hpp" #include "System/Math.hpp" @@ -27,7 +28,7 @@ class Sampler : public Object<Sampler, VkSampler> { public: - Sampler(const VkSamplerCreateInfo* pCreateInfo, void* mem) : + Sampler(const VkSamplerCreateInfo* pCreateInfo, void* mem, const vk::SamplerYcbcrConversion *ycbcrConversion) : magFilter(pCreateInfo->magFilter), minFilter(pCreateInfo->minFilter), mipmapMode(pCreateInfo->mipmapMode), @@ -42,7 +43,8 @@ minLod(ClampLod(pCreateInfo->minLod)), maxLod(ClampLod(pCreateInfo->maxLod)), borderColor(pCreateInfo->borderColor), - unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates) + unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates), + ycbcrConversion(ycbcrConversion) { } @@ -74,15 +76,54 @@ const VkBorderColor borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; const VkBool32 unnormalizedCoordinates = VK_FALSE; + const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr; + private: static std::atomic<uint32_t> nextID; }; +class SamplerYcbcrConversion : public Object<SamplerYcbcrConversion, VkSamplerYcbcrConversion> +{ +public: + SamplerYcbcrConversion(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, void* mem) : + format(pCreateInfo->format), + ycbcrModel(pCreateInfo->ycbcrModel), + ycbcrRange(pCreateInfo->ycbcrRange), + components(ResolveIdentityMapping(pCreateInfo->components)), + xChromaOffset(pCreateInfo->xChromaOffset), + yChromaOffset(pCreateInfo->yChromaOffset), + chromaFilter(pCreateInfo->chromaFilter), + forceExplicitReconstruction(pCreateInfo->forceExplicitReconstruction) + { + } + + ~SamplerYcbcrConversion() = default; + + static size_t ComputeRequiredAllocationSize(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo) + { + return 0; + } + + const VkFormat format = VK_FORMAT_UNDEFINED; + const VkSamplerYcbcrModelConversion ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; + const VkSamplerYcbcrRange ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; + const VkComponentMapping components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; + const VkChromaLocation xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + const VkChromaLocation yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + const VkFilter chromaFilter = VK_FILTER_NEAREST; + const VkBool32 forceExplicitReconstruction = VK_FALSE; +}; + static inline Sampler* Cast(VkSampler object) { return reinterpret_cast<Sampler*>(object.get()); } +static inline SamplerYcbcrConversion* Cast(VkSamplerYcbcrConversion object) +{ + return reinterpret_cast<SamplerYcbcrConversion*>(object.get()); +} + } // namespace vk #endif // VK_SAMPLER_HPP_ \ No newline at end of file
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index c639a81..081414e 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -443,7 +443,7 @@ break; default: // "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]" - UNIMPLEMENTED("extensionCreateInfo->sType"); // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here. + UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType)); // TODO(b/119321052): UNIMPLEMENTED() should be used only for features that must still be implemented. Use a more informational macro here. break; } @@ -1045,6 +1045,7 @@ } const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext); + const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr; while(extensionCreateInfo) { @@ -1058,8 +1059,10 @@ break; case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: { - const VkSamplerYcbcrConversionInfo* ycbcrConversionInfo = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(extensionCreateInfo); - if(ycbcrConversionInfo->conversion != VK_NULL_HANDLE) + const VkSamplerYcbcrConversionInfo* samplerYcbcrConversionInfo = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(extensionCreateInfo); + ycbcrConversion = vk::Cast(samplerYcbcrConversionInfo->conversion); + + if(ycbcrConversion != VK_NULL_HANDLE) { ASSERT((pCreateInfo->components.r == VK_COMPONENT_SWIZZLE_IDENTITY) && (pCreateInfo->components.g == VK_COMPONENT_SWIZZLE_IDENTITY) && @@ -1069,14 +1072,14 @@ } break; default: - UNIMPLEMENTED("extensionCreateInfo->sType"); + UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType)); break; } extensionCreateInfo = extensionCreateInfo->pNext; } - return vk::ImageView::Create(pAllocator, pCreateInfo, pView); + return vk::ImageView::Create(pAllocator, pCreateInfo, pView, ycbcrConversion); } VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) @@ -1245,12 +1248,33 @@ TRACE("(VkDevice device = %p, const VkSamplerCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkSampler* pSampler = %p)", device, pCreateInfo, pAllocator, pSampler); - if(pCreateInfo->pNext || pCreateInfo->flags) + if(pCreateInfo->flags) { UNIMPLEMENTED("pCreateInfo->pNext || pCreateInfo->flags"); } - return vk::Sampler::Create(pAllocator, pCreateInfo, pSampler); + const VkBaseInStructure* extensionCreateInfo = reinterpret_cast<const VkBaseInStructure*>(pCreateInfo->pNext); + const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr; + + while(extensionCreateInfo) + { + switch(extensionCreateInfo->sType) + { + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: + { + const VkSamplerYcbcrConversionInfo* samplerYcbcrConversionInfo = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(extensionCreateInfo); + ycbcrConversion = vk::Cast(samplerYcbcrConversionInfo->conversion); + } + break; + default: + UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType)); + break; + } + + extensionCreateInfo = extensionCreateInfo->pNext; + } + + return vk::Sampler::Create(pAllocator, pCreateInfo, pSampler, ycbcrConversion); } VKAPI_ATTR void VKAPI_CALL vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) @@ -1276,7 +1300,7 @@ ASSERT(!vk::Cast(device)->hasExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)); break; default: - UNIMPLEMENTED("extensionCreateInfo->sType"); + UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType)); break; } @@ -1466,7 +1490,7 @@ } break; default: - UNIMPLEMENTED("extensionCreateInfo->sType"); + UNIMPLEMENTED("extensionCreateInfo->sType %d", int(extensionCreateInfo->sType)); break; } @@ -2432,15 +2456,23 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) { - TRACE("()"); - UNIMPLEMENTED("vkCreateSamplerYcbcrConversion"); - return VK_SUCCESS; + TRACE("(VkDevice device = %p, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkSamplerYcbcrConversion* pYcbcrConversion = %p)", + device, pCreateInfo, pAllocator, pYcbcrConversion); + + if(pCreateInfo->pNext) + { + UNIMPLEMENTED("pCreateInfo->pNext"); + } + + return vk::SamplerYcbcrConversion::Create(pAllocator, pCreateInfo, pYcbcrConversion); } VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) { - TRACE("()"); - UNIMPLEMENTED("vkDestroySamplerYcbcrConversion"); + TRACE("(VkDevice device = %p, VkSamplerYcbcrConversion ycbcrConversion = %p, const VkAllocationCallbacks* pAllocator = %p)", + device, ycbcrConversion.get(), pAllocator); + + vk::destroy(ycbcrConversion, pAllocator); } VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate)