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)