Add support for YCbCr conversion samplers in vulkan. Refs #1194

This commit is contained in:
baldurk
2018-12-14 14:08:33 +00:00
parent 5ddefed02b
commit 2cf5129e71
14 changed files with 275 additions and 29 deletions
@@ -711,17 +711,57 @@ QVariantList VulkanPipelineStateViewer::makeSampler(const QString &bindset, cons
.arg((descriptor.minLOD == -FLT_MAX ? lit("0") : QString::number(descriptor.minLOD)))
.arg((descriptor.maxLOD == FLT_MAX ? lit("FLT_MAX") : QString::number(descriptor.maxLOD)));
// omit lod clamp if this is an immutable sampler and the attached resource is entirely within the
// range
if(descriptor.immutableSampler)
{
TextureDescription *tex = m_Ctx.GetTexture(descriptor.resourceResourceId);
if(tex && descriptor.minLOD <= 0.0f && descriptor.maxLOD >= (float)(tex->mips - 1))
{
lod = QString();
}
}
if(descriptor.mipBias != 0.0f)
lod += lit(" Bias %1").arg(descriptor.mipBias);
return {QString(),
bindset,
slotname,
descriptor.immutableSampler ? tr("Immutable Sampler") : tr("Sampler"),
descriptor.samplerResourceId,
addressing,
filter + lit(", ") + lod,
QString()};
if(!lod.isEmpty())
lod = lit(", ") + lod;
QString obj = ToQStr(descriptor.samplerResourceId);
if(descriptor.ycbcrSampler != ResourceId())
{
obj += lit(" ") + ToQStr(descriptor.ycbcrSampler);
if(descriptor.ycbcrSwizzle[0] != TextureSwizzle::Red ||
descriptor.ycbcrSwizzle[1] != TextureSwizzle::Green ||
descriptor.ycbcrSwizzle[2] != TextureSwizzle::Blue ||
descriptor.ycbcrSwizzle[3] != TextureSwizzle::Alpha)
{
obj += tr(" swizzle[%1%2%3%4]")
.arg(ToQStr(descriptor.swizzle[0]))
.arg(ToQStr(descriptor.swizzle[1]))
.arg(ToQStr(descriptor.swizzle[2]))
.arg(ToQStr(descriptor.swizzle[3]));
}
filter +=
QFormatStr(", %1 %2").arg(ToQStr(descriptor.ycbcrModel)).arg(ToQStr(descriptor.ycbcrRange));
addressing += tr(", Chroma %1 [%2,%3]")
.arg(ToQStr(descriptor.chromaFilter))
.arg(ToQStr(descriptor.xChromaOffset))
.arg(ToQStr(descriptor.yChromaOffset));
if(descriptor.forceExplicitReconstruction)
addressing += tr(" Explicit");
}
return {QString(), bindset,
slotname, descriptor.immutableSampler ? tr("Immutable Sampler") : tr("Sampler"),
obj, addressing,
filter + lod, QString()};
}
void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
+36
View File
@@ -439,6 +439,42 @@ std::string DoStringise(const AddressMode &el)
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const YcbcrConversion &el)
{
BEGIN_ENUM_STRINGISE(YcbcrConversion);
{
STRINGISE_ENUM_CLASS(Raw);
STRINGISE_ENUM_CLASS_NAMED(RangeOnly, "Range Only");
STRINGISE_ENUM_CLASS_NAMED(BT709, "BT.709");
STRINGISE_ENUM_CLASS_NAMED(BT601, "BT.601");
STRINGISE_ENUM_CLASS_NAMED(BT2020, "BT.2020");
}
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const YcbcrRange &el)
{
BEGIN_ENUM_STRINGISE(YcbcrRange);
{
STRINGISE_ENUM_CLASS_NAMED(ITUFull, "Full");
STRINGISE_ENUM_CLASS_NAMED(ITUNarrow, "Narrow");
}
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const ChromaSampleLocation &el)
{
BEGIN_ENUM_STRINGISE(ChromaSampleLocation);
{
STRINGISE_ENUM_CLASS_NAMED(CositedEven, "Even");
STRINGISE_ENUM_CLASS_NAMED(Midpoint, "Mid");
}
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const ResourceType &el)
{
+27
View File
@@ -315,6 +315,33 @@ enum class AddressMode : uint32_t
DECLARE_REFLECTION_ENUM(AddressMode);
enum YcbcrConversion
{
Raw,
RangeOnly,
BT709,
BT601,
BT2020,
};
DECLARE_REFLECTION_ENUM(YcbcrConversion);
enum YcbcrRange
{
ITUFull,
ITUNarrow,
};
DECLARE_REFLECTION_ENUM(YcbcrRange);
enum ChromaSampleLocation
{
CositedEven,
Midpoint,
};
DECLARE_REFLECTION_ENUM(ChromaSampleLocation);
DOCUMENT(R"(The type of a resource referred to by binding or API usage.
In some cases there is a little overlap or fudging when mapping API concepts - this is primarily
+22
View File
@@ -166,6 +166,28 @@ struct BindingElement
DOCUMENT("For samplers - ``True`` if unnormalized co-ordinates are used in this sampler.");
bool unnormalized = false;
DOCUMENT(R"(For samplers - the :class:`ResourceId` of the ycbcr conversion object associated with
this sampler.
)");
ResourceId ycbcrSampler;
DOCUMENT("For ycbcr samplers - the :class:`YcbcrConversion` used for conversion.");
YcbcrConversion ycbcrModel;
DOCUMENT("For ycbcr samplers - the :class:`YcbcrRange` used for conversion.");
YcbcrRange ycbcrRange;
DOCUMENT(R"(For ycbcr samplers - Four :class:`TextureSwizzle` elements indicating the swizzle
applied before conversion.
)");
TextureSwizzle ycbcrSwizzle[4];
DOCUMENT("For ycbcr samplers - the :class:`ChromaSampleLocation` X-axis chroma offset.");
ChromaSampleLocation xChromaOffset;
DOCUMENT("For ycbcr samplers - the :class:`ChromaSampleLocation` Y-axis chroma offset.");
ChromaSampleLocation yChromaOffset;
DOCUMENT("For ycbcr samplers - the :class:`FilterMode` describing the chroma filtering mode.");
FilterMode chromaFilter;
DOCUMENT("For ycbcr samplers - ``True`` if explicit reconstruction is force enabled.");
bool forceExplicitReconstruction;
DOCUMENT(R"(For samplers - check if the border color is used in this Vulkan sampler.
:return: ``True`` if the border color is used, ``False`` otherwise.
+1 -1
View File
@@ -522,7 +522,7 @@ CompareFunction MakeCompareFunc(VkCompareOp func)
return CompareFunction::AlwaysTrue;
}
static FilterMode MakeFilterMode(VkFilter f)
FilterMode MakeFilterMode(VkFilter f)
{
switch(f)
{
+1
View File
@@ -91,6 +91,7 @@ VkPrimitiveTopology MakeVkPrimitiveTopology(Topology Topo);
AddressMode MakeAddressMode(VkSamplerAddressMode addr);
void MakeBorderColor(VkBorderColor border, FloatVector *BorderColor);
CompareFunction MakeCompareFunc(VkCompareOp func);
FilterMode MakeFilterMode(VkFilter f);
TextureFilter MakeFilter(VkFilter minFilter, VkFilter magFilter, VkSamplerMipmapMode mipmapMode,
bool anisoEnable, bool compareEnable, VkSamplerReductionModeEXT reduction);
LogicOperation MakeLogicOp(VkLogicOp op);
+4
View File
@@ -2635,6 +2635,10 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
return Serialise_vkCmdInsertDebugUtilsLabelEXT(ser, VK_NULL_HANDLE, NULL);
break;
case VulkanChunk::vkCreateSamplerYcbcrConversion:
return Serialise_vkCreateSamplerYcbcrConversion(ser, VK_NULL_HANDLE, NULL, NULL, NULL);
break;
case VulkanChunk::vkCmdSetDeviceMask:
return Serialise_vkCmdSetDeviceMask(ser, VK_NULL_HANDLE, 0);
break;
+56 -5
View File
@@ -738,12 +738,14 @@ void VulkanCreationInfo::Sampler::Init(VulkanResourceManager *resourceMan, Vulka
{
reductionMode = reduction->reductionMode;
}
}
void VulkanCreationInfo::YCbCrSampler::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo)
{
const VkSamplerYcbcrConversionInfo *ycbcrInfo =
(const VkSamplerYcbcrConversionInfo *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO);
if(ycbcrInfo)
{
ycbcr = GetResID(ycbcrInfo->conversion);
}
}
static TextureSwizzle Convert(VkComponentSwizzle s, int i)
@@ -763,6 +765,55 @@ static TextureSwizzle Convert(VkComponentSwizzle s, int i)
return TextureSwizzle(uint32_t(TextureSwizzle::Red) + i);
}
void VulkanCreationInfo::YCbCrSampler::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo)
{
switch(pCreateInfo->ycbcrModel)
{
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: ycbcrModel = YcbcrConversion::Raw; break;
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
ycbcrModel = YcbcrConversion::RangeOnly;
break;
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: ycbcrModel = YcbcrConversion::BT709; break;
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: ycbcrModel = YcbcrConversion::BT601; break;
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: ycbcrModel = YcbcrConversion::BT2020; break;
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM:
case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE: break;
}
switch(pCreateInfo->ycbcrRange)
{
case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: ycbcrRange = YcbcrRange::ITUFull; break;
case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: ycbcrRange = YcbcrRange::ITUNarrow; break;
case VK_SAMPLER_YCBCR_RANGE_MAX_ENUM:
case VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE: break;
}
switch(pCreateInfo->xChromaOffset)
{
case VK_CHROMA_LOCATION_COSITED_EVEN: xChromaOffset = ChromaSampleLocation::CositedEven; break;
case VK_CHROMA_LOCATION_MIDPOINT: xChromaOffset = ChromaSampleLocation::Midpoint; break;
case VK_CHROMA_LOCATION_MAX_ENUM:
case VK_CHROMA_LOCATION_RANGE_SIZE: break;
}
switch(pCreateInfo->yChromaOffset)
{
case VK_CHROMA_LOCATION_COSITED_EVEN: yChromaOffset = ChromaSampleLocation::CositedEven; break;
case VK_CHROMA_LOCATION_MIDPOINT: yChromaOffset = ChromaSampleLocation::Midpoint; break;
case VK_CHROMA_LOCATION_MAX_ENUM:
case VK_CHROMA_LOCATION_RANGE_SIZE: break;
}
swizzle[0] = Convert(pCreateInfo->components.r, 0);
swizzle[1] = Convert(pCreateInfo->components.g, 1);
swizzle[2] = Convert(pCreateInfo->components.b, 2);
swizzle[3] = Convert(pCreateInfo->components.a, 3);
chromaFilter = MakeFilterMode(pCreateInfo->chromaFilter);
forceExplicitReconstruction = pCreateInfo->forceExplicitReconstruction != 0;
}
void VulkanCreationInfo::ImageView::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkImageViewCreateInfo *pCreateInfo)
{
+10
View File
@@ -386,6 +386,8 @@ struct VulkanCreationInfo
VkBorderColor borderColor;
bool unnormalizedCoordinates;
VkSamplerReductionModeEXT reductionMode;
ResourceId ycbcr;
};
map<ResourceId, Sampler> m_Sampler;
@@ -393,6 +395,14 @@ struct VulkanCreationInfo
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo);
YcbcrConversion ycbcrModel;
YcbcrRange ycbcrRange;
TextureSwizzle swizzle[4];
ChromaSampleLocation xChromaOffset;
ChromaSampleLocation yChromaOffset;
FilterMode chromaFilter;
bool forceExplicitReconstruction;
};
map<ResourceId, YCbCrSampler> m_YCbCrSampler;
+14
View File
@@ -1414,6 +1414,20 @@ void VulkanReplay::SavePipelineState()
el.maxLOD = sampl.maxLod;
MakeBorderColor(sampl.borderColor, (FloatVector *)el.borderColor);
el.unnormalized = sampl.unnormalizedCoordinates;
if(sampl.ycbcr != ResourceId())
{
const VulkanCreationInfo::YCbCrSampler &ycbcr = c.m_YCbCrSampler[sampl.ycbcr];
el.ycbcrSampler = rm->GetOriginalID(sampl.ycbcr);
el.ycbcrModel = ycbcr.ycbcrModel;
el.ycbcrRange = ycbcr.ycbcrRange;
memcpy(el.ycbcrSwizzle, ycbcr.swizzle, sizeof(TextureSwizzle) * 4);
el.xChromaOffset = ycbcr.xChromaOffset;
el.yChromaOffset = ycbcr.yChromaOffset;
el.chromaFilter = ycbcr.chromaFilter;
el.forceExplicitReconstruction = ycbcr.forceExplicitReconstruction;
}
}
}
@@ -551,17 +551,6 @@ void WrappedVulkan::vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice
{
ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), pFeatures);
// if the user is requesting ycbcr features, make sure it's reported as NOT supported
VkPhysicalDeviceSamplerYcbcrConversionFeatures *ycbcr =
(VkPhysicalDeviceSamplerYcbcrConversionFeatures *)FindNextStruct(
pFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
if(ycbcr)
{
RDCWARN("Forcibly disabling support for YCbCr Conversion");
ycbcr->samplerYcbcrConversion = VK_FALSE;
}
// if the user is requesting protected memory, make sure it's reported as NOT supported
VkPhysicalDeviceProtectedMemoryFeatures *protectedMem =
(VkPhysicalDeviceProtectedMemoryFeatures *)FindNextStruct(
@@ -466,6 +466,12 @@ bool WrappedVulkan::Serialise_vkCreateSampler(SerialiserType &ser, VkDevice devi
AddResource(Sampler, ResourceType::Sampler, "Sampler");
DerivedResource(device, Sampler);
const VkSamplerYcbcrConversionInfo *ycbcr = (const VkSamplerYcbcrConversionInfo *)FindNextStruct(
&CreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO);
if(ycbcr)
{
DerivedResource(ycbcr->conversion, Sampler);
}
}
return true;
@@ -503,6 +509,15 @@ VkResult WrappedVulkan::vkCreateSampler(VkDevice device, const VkSamplerCreateIn
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pSampler);
record->AddChunk(chunk);
const VkSamplerYcbcrConversionInfo *ycbcr =
(const VkSamplerYcbcrConversionInfo *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO);
if(ycbcr)
{
VkResourceRecord *ycbcrRecord = GetRecord(ycbcr->conversion);
record->AddParent(ycbcrRecord);
}
}
else
{
+11 -1
View File
@@ -1800,7 +1800,17 @@ void DoSerialise(SerialiserType &ser, VKPipe::BindingElement &el)
SERIALISE_MEMBER(borderColor);
SERIALISE_MEMBER(unnormalized);
SIZE_CHECK(152);
SERIALISE_MEMBER(ycbcrSampler);
SERIALISE_MEMBER(ycbcrModel);
SERIALISE_MEMBER(ycbcrRange);
SERIALISE_MEMBER(ycbcrSwizzle);
SERIALISE_MEMBER(xChromaOffset);
SERIALISE_MEMBER(yChromaOffset);
SERIALISE_MEMBER(chromaFilter);
SERIALISE_MEMBER(forceExplicitReconstruction);
SIZE_CHECK(200);
};
template <typename SerialiserType>
+30 -3
View File
@@ -791,7 +791,7 @@ void main()
VkPipeline pipe = VK_NULL_HANDLE;
VkPipelineLayout layout = VK_NULL_HANDLE;
VkDescriptorSet descset = VK_NULL_HANDLE;
} ycbcr[2];
} ycbcr[6];
VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrFeats = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
@@ -808,6 +808,9 @@ void main()
{
createInfo.chromaFilter = VK_FILTER_LINEAR;
createInfo.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
createInfo.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
createInfo.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
createInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020;
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
@@ -818,7 +821,31 @@ void main()
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
vkCreateSamplerYcbcrConversionKHR(device, &createInfo, NULL, &ycbcr[1].conv);
ycbcr[0].name = "YCbCr 601 Narrow";
ycbcr[1].name = "YCbCr 601 Narrow";
createInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
vkCreateSamplerYcbcrConversionKHR(device, &createInfo, NULL, &ycbcr[2].conv);
ycbcr[2].name = "RGB Identity Narrow";
createInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
vkCreateSamplerYcbcrConversionKHR(device, &createInfo, NULL, &ycbcr[3].conv);
ycbcr[3].name = "RGB Identity Full";
createInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY;
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
vkCreateSamplerYcbcrConversionKHR(device, &createInfo, NULL, &ycbcr[4].conv);
ycbcr[4].name = "YCbCr Identity Narrow";
createInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY;
createInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
vkCreateSamplerYcbcrConversionKHR(device, &createInfo, NULL, &ycbcr[5].conv);
ycbcr[5].name = "YCbCr Identity Full";
pipeCreateInfo.stages = {
CompileShaderModule(common + vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
@@ -933,7 +960,7 @@ void main()
vkCmdDraw(cmd, 4, 1, 0, 0);
}
x += 100.0f;
x += 60.0f;
}
vkCmdEndRenderPass(cmd);