Add validation for fragment output and attachment interface matching
Validation rules discussed at https://github.com/gpuweb/gpuweb/issues/2013 Bug: dawn:1063 Change-Id: I264eecb7c548f29975e5459a7ad020105acab634 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/61383 Commit-Queue: Shrek Shao <shrekshao@google.com> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
6ef39372f8
commit
4f2edf576e
|
@ -158,7 +158,7 @@ namespace dawn_native {
|
|||
|
||||
auto AddColorFormat = [&AddFormat](wgpu::TextureFormat format, bool renderable,
|
||||
bool supportsStorageUsage, uint32_t byteSize,
|
||||
SampleTypeBit sampleTypes) {
|
||||
SampleTypeBit sampleTypes, uint8_t componentCount) {
|
||||
Format internalFormat;
|
||||
internalFormat.format = format;
|
||||
internalFormat.isRenderable = renderable;
|
||||
|
@ -166,6 +166,7 @@ namespace dawn_native {
|
|||
internalFormat.isSupported = true;
|
||||
internalFormat.supportsStorageUsage = supportsStorageUsage;
|
||||
internalFormat.aspects = Aspect::Color;
|
||||
internalFormat.componentCount = componentCount;
|
||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||
firstAspect->block.byteSize = byteSize;
|
||||
firstAspect->block.width = 1;
|
||||
|
@ -202,6 +203,7 @@ namespace dawn_native {
|
|||
internalFormat.isSupported = true;
|
||||
internalFormat.supportsStorageUsage = false;
|
||||
internalFormat.aspects = Aspect::Depth;
|
||||
internalFormat.componentCount = 1;
|
||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||
firstAspect->block.byteSize = byteSize;
|
||||
firstAspect->block.width = 1;
|
||||
|
@ -220,6 +222,7 @@ namespace dawn_native {
|
|||
internalFormat.isSupported = false;
|
||||
internalFormat.supportsStorageUsage = false;
|
||||
internalFormat.aspects = Aspect::Stencil;
|
||||
internalFormat.componentCount = 1;
|
||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||
firstAspect->block.byteSize = 1;
|
||||
firstAspect->block.width = 1;
|
||||
|
@ -231,7 +234,8 @@ namespace dawn_native {
|
|||
};
|
||||
|
||||
auto AddCompressedFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize,
|
||||
uint32_t width, uint32_t height, bool isSupported) {
|
||||
uint32_t width, uint32_t height, bool isSupported,
|
||||
uint8_t componentCount) {
|
||||
Format internalFormat;
|
||||
internalFormat.format = format;
|
||||
internalFormat.isRenderable = false;
|
||||
|
@ -239,6 +243,7 @@ namespace dawn_native {
|
|||
internalFormat.isSupported = isSupported;
|
||||
internalFormat.supportsStorageUsage = false;
|
||||
internalFormat.aspects = Aspect::Color;
|
||||
internalFormat.componentCount = componentCount;
|
||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||
firstAspect->block.byteSize = byteSize;
|
||||
firstAspect->block.width = width;
|
||||
|
@ -249,74 +254,74 @@ namespace dawn_native {
|
|||
AddFormat(internalFormat);
|
||||
};
|
||||
|
||||
auto AddMultiAspectFormat = [&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
||||
wgpu::TextureFormat firstFormat,
|
||||
wgpu::TextureFormat secondFormat,
|
||||
bool isRenderable, bool isSupported) {
|
||||
Format internalFormat;
|
||||
internalFormat.format = format;
|
||||
internalFormat.isRenderable = isRenderable;
|
||||
internalFormat.isCompressed = false;
|
||||
internalFormat.isSupported = isSupported;
|
||||
internalFormat.supportsStorageUsage = false;
|
||||
internalFormat.aspects = aspects;
|
||||
auto AddMultiAspectFormat =
|
||||
[&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
||||
wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
|
||||
bool isRenderable, bool isSupported, uint8_t componentCount) {
|
||||
Format internalFormat;
|
||||
internalFormat.format = format;
|
||||
internalFormat.isRenderable = isRenderable;
|
||||
internalFormat.isCompressed = false;
|
||||
internalFormat.isSupported = isSupported;
|
||||
internalFormat.supportsStorageUsage = false;
|
||||
internalFormat.aspects = aspects;
|
||||
internalFormat.componentCount = componentCount;
|
||||
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
|
||||
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
|
||||
|
||||
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
|
||||
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
|
||||
internalFormat.aspectInfo[0] = table[firstFormatIndex].aspectInfo[0];
|
||||
internalFormat.aspectInfo[1] = table[secondFormatIndex].aspectInfo[0];
|
||||
|
||||
internalFormat.aspectInfo[0] = table[firstFormatIndex].aspectInfo[0];
|
||||
internalFormat.aspectInfo[1] = table[secondFormatIndex].aspectInfo[0];
|
||||
|
||||
AddFormat(internalFormat);
|
||||
};
|
||||
AddFormat(internalFormat);
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
// 1 byte color formats
|
||||
AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, 1, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, 1, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, 1, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, 1, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, 1, kAnyFloat, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, 1, kAnyFloat, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, 1, SampleTypeBit::Uint, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, 1, SampleTypeBit::Sint, 1);
|
||||
|
||||
// 2 bytes color formats
|
||||
AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, 2, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, 2, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::R16Float, true, false, 2, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, 2, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, 2, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, 2, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, 2, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, 2, SampleTypeBit::Uint, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, 2, SampleTypeBit::Sint, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R16Float, true, false, 2, kAnyFloat, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, 2, kAnyFloat, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, 2, kAnyFloat, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, 2, SampleTypeBit::Uint, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, 2, SampleTypeBit::Sint, 2);
|
||||
|
||||
// 4 bytes color formats
|
||||
AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, 4, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, 4, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::R32Float, true, true, 4, SampleTypeBit::UnfilterableFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, 4, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, 4, SampleTypeBit::Uint, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, 4, SampleTypeBit::Sint, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::R32Float, true, true, 4, SampleTypeBit::UnfilterableFloat, 1);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, 4, SampleTypeBit::Uint, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat, 4);
|
||||
|
||||
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, 4, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat, 3);
|
||||
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, 4, kAnyFloat, 3);
|
||||
|
||||
// 8 bytes color formats
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, 8, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, 8, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, 8, SampleTypeBit::UnfilterableFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, 8, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, 8, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, 8, kAnyFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, 8, SampleTypeBit::Uint, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, 8, SampleTypeBit::Sint, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, 8, SampleTypeBit::UnfilterableFloat, 2);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, 8, SampleTypeBit::Uint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, 8, SampleTypeBit::Sint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, 8, kAnyFloat, 4);
|
||||
|
||||
// 16 bytes color formats
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, 16, SampleTypeBit::Uint);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, 16, SampleTypeBit::Sint);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, SampleTypeBit::UnfilterableFloat);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, 16, SampleTypeBit::Uint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, 16, SampleTypeBit::Sint, 4);
|
||||
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, SampleTypeBit::UnfilterableFloat, 4);
|
||||
|
||||
// Depth-stencil formats
|
||||
AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4);
|
||||
|
@ -327,30 +332,30 @@ namespace dawn_native {
|
|||
// TODO(dawn:666): Implement the stencil8 format
|
||||
AddStencilFormat(wgpu::TextureFormat::Stencil8);
|
||||
AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, true);
|
||||
Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, true, 2);
|
||||
// TODO(dawn:690): Implement Depth16Unorm, Depth24UnormStencil8, Depth32FloatStencil8.
|
||||
|
||||
// BC compressed formats
|
||||
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported, 1);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported, 2);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported, 2);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported, 3);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported, 3);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||
|
||||
// multi-planar formats
|
||||
const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
|
||||
AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
|
||||
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, isMultiPlanarFormatSupported);
|
||||
wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, isMultiPlanarFormatSupported, 3);
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace dawn_native {
|
|||
bool isSupported;
|
||||
bool supportsStorageUsage;
|
||||
Aspect aspects;
|
||||
// Only used for renderable color formats, number of color channels.
|
||||
uint8_t componentCount;
|
||||
|
||||
bool IsColor() const;
|
||||
bool HasDepth() const;
|
||||
|
|
|
@ -253,10 +253,22 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError ValidateColorTargetState(DeviceBase* device,
|
||||
const ColorTargetState* descriptor,
|
||||
bool fragmentWritten,
|
||||
wgpu::TextureComponentType fragmentOutputBaseType) {
|
||||
bool BlendFactorContainsSrcAlpha(const wgpu::BlendFactor& blendFactor) {
|
||||
return blendFactor == wgpu::BlendFactor::SrcAlpha ||
|
||||
blendFactor == wgpu::BlendFactor::OneMinusSrcAlpha ||
|
||||
blendFactor == wgpu::BlendFactor::SrcAlphaSaturated;
|
||||
}
|
||||
|
||||
bool BlendFactorContainsSrc(const wgpu::BlendFactor& blendFactor) {
|
||||
return blendFactor == wgpu::BlendFactor::Src ||
|
||||
blendFactor == wgpu::BlendFactor::OneMinusSrc;
|
||||
}
|
||||
|
||||
MaybeError ValidateColorTargetState(
|
||||
DeviceBase* device,
|
||||
const ColorTargetState* descriptor,
|
||||
bool fragmentWritten,
|
||||
const EntryPointMetadata::FragmentOutputVariableInfo& fragmentOutputVariable) {
|
||||
if (descriptor->nextInChain != nullptr) {
|
||||
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
||||
}
|
||||
|
@ -278,10 +290,37 @@ namespace dawn_native {
|
|||
"Color format must be blendable when blending is enabled");
|
||||
}
|
||||
if (fragmentWritten) {
|
||||
if (fragmentOutputBaseType != format->GetAspectInfo(Aspect::Color).baseType) {
|
||||
if (fragmentOutputVariable.baseType !=
|
||||
format->GetAspectInfo(Aspect::Color).baseType) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Color format must match the fragment stage output type");
|
||||
}
|
||||
|
||||
if (fragmentOutputVariable.componentCount < format->componentCount) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"The fragment stage output components count must be no fewer than the "
|
||||
"color format channel count");
|
||||
}
|
||||
|
||||
if (descriptor->blend) {
|
||||
if (fragmentOutputVariable.componentCount < 4u) {
|
||||
// No alpha channel output
|
||||
// Make sure there's no alpha involved in the blending operation
|
||||
if (BlendFactorContainsSrcAlpha(descriptor->blend->color.srcFactor) ||
|
||||
BlendFactorContainsSrcAlpha(descriptor->blend->color.dstFactor)) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Color blending factor is reading alpha but it is missing from "
|
||||
"fragment output");
|
||||
}
|
||||
if (descriptor->blend->alpha.srcFactor != wgpu::BlendFactor::Zero ||
|
||||
BlendFactorContainsSrc(descriptor->blend->alpha.dstFactor) ||
|
||||
BlendFactorContainsSrcAlpha(descriptor->blend->alpha.dstFactor)) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Alpha blending factor is reading alpha but it is missing from "
|
||||
"fragment output");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (descriptor->writeMask != wgpu::ColorWriteMask::None) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
|
@ -311,10 +350,10 @@ namespace dawn_native {
|
|||
descriptor->module->GetEntryPoint(descriptor->entryPoint);
|
||||
for (ColorAttachmentIndex i(uint8_t(0));
|
||||
i < ColorAttachmentIndex(static_cast<uint8_t>(descriptor->targetCount)); ++i) {
|
||||
DAWN_TRY(
|
||||
ValidateColorTargetState(device, &descriptor->targets[static_cast<uint8_t>(i)],
|
||||
fragmentMetadata.fragmentOutputsWritten[i],
|
||||
fragmentMetadata.fragmentOutputFormatBaseTypes[i]));
|
||||
DAWN_TRY(ValidateColorTargetState(device,
|
||||
&descriptor->targets[static_cast<uint8_t>(i)],
|
||||
fragmentMetadata.fragmentOutputsWritten[i],
|
||||
fragmentMetadata.fragmentOutputVariables[i]));
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
|
@ -875,8 +875,16 @@ namespace dawn_native {
|
|||
ColorAttachmentIndex attachment(
|
||||
static_cast<uint8_t>(unsanitizedAttachment));
|
||||
DAWN_TRY_ASSIGN(
|
||||
metadata->fragmentOutputFormatBaseTypes[attachment],
|
||||
metadata->fragmentOutputVariables[attachment].baseType,
|
||||
TintComponentTypeToTextureComponentType(output_var.component_type));
|
||||
uint32_t componentCount;
|
||||
DAWN_TRY_ASSIGN(componentCount,
|
||||
TintCompositionTypeToInterStageComponentCount(
|
||||
output_var.composition_type));
|
||||
// componentCount should be no larger than 4u
|
||||
ASSERT(componentCount <= 4u);
|
||||
metadata->fragmentOutputVariables[attachment].componentCount =
|
||||
componentCount;
|
||||
metadata->fragmentOutputsWritten.set(attachment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,8 +173,12 @@ namespace dawn_native {
|
|||
ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> usedVertexInputs;
|
||||
|
||||
// An array to record the basic types (float, int and uint) of the fragment shader outputs.
|
||||
ityp::array<ColorAttachmentIndex, wgpu::TextureComponentType, kMaxColorAttachments>
|
||||
fragmentOutputFormatBaseTypes;
|
||||
struct FragmentOutputVariableInfo {
|
||||
wgpu::TextureComponentType baseType;
|
||||
uint8_t componentCount;
|
||||
};
|
||||
ityp::array<ColorAttachmentIndex, FragmentOutputVariableInfo, kMaxColorAttachments>
|
||||
fragmentOutputVariables;
|
||||
ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> fragmentOutputsWritten;
|
||||
|
||||
struct InterStageVariableInfo {
|
||||
|
|
|
@ -288,8 +288,9 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
spirv_cross::SPIRType::BaseType shaderFragmentOutputBaseType =
|
||||
compiler.get_type(fragmentOutput.base_type_id).basetype;
|
||||
metadata->fragmentOutputFormatBaseTypes[attachment] =
|
||||
SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType);
|
||||
// spriv path so temporarily always set to 4u to always pass validation
|
||||
metadata->fragmentOutputVariables[attachment] = {
|
||||
SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType), 4u};
|
||||
metadata->fragmentOutputsWritten.set(attachment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,14 @@ class RenderPipelineValidationTest : public ValidationTest {
|
|||
wgpu::ShaderModule fsModuleUint;
|
||||
};
|
||||
|
||||
namespace {
|
||||
bool BlendFactorContainsSrcAlpha(const wgpu::BlendFactor& blendFactor) {
|
||||
return blendFactor == wgpu::BlendFactor::SrcAlpha ||
|
||||
blendFactor == wgpu::BlendFactor::OneMinusSrcAlpha ||
|
||||
blendFactor == wgpu::BlendFactor::SrcAlphaSaturated;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Test cases where creation should succeed
|
||||
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
|
||||
{
|
||||
|
@ -216,28 +224,26 @@ TEST_F(RenderPipelineValidationTest, NonBlendableFormat) {
|
|||
|
||||
// Tests that the format of the color state descriptor must match the output of the fragment shader.
|
||||
TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
|
||||
constexpr uint32_t kNumTextureFormatBaseType = 3u;
|
||||
std::array<const char*, kNumTextureFormatBaseType> kScalarTypes = {{"f32", "i32", "u32"}};
|
||||
std::array<wgpu::TextureFormat, kNumTextureFormatBaseType> kColorFormats = {
|
||||
{wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8Sint,
|
||||
wgpu::TextureFormat::RGBA8Uint}};
|
||||
std::array<const char*, 3> kScalarTypes = {{"f32", "i32", "u32"}};
|
||||
std::array<wgpu::TextureFormat, 3> kColorFormats = {{wgpu::TextureFormat::RGBA8Unorm,
|
||||
wgpu::TextureFormat::RGBA8Sint,
|
||||
wgpu::TextureFormat::RGBA8Uint}};
|
||||
|
||||
for (size_t i = 0; i < kNumTextureFormatBaseType; ++i) {
|
||||
for (size_t j = 0; j < kNumTextureFormatBaseType; ++j) {
|
||||
utils::ComboRenderPipelineDescriptor descriptor;
|
||||
descriptor.vertex.module = vsModule;
|
||||
for (size_t i = 0; i < kScalarTypes.size(); ++i) {
|
||||
utils::ComboRenderPipelineDescriptor descriptor;
|
||||
descriptor.vertex.module = vsModule;
|
||||
std::ostringstream stream;
|
||||
stream << R"(
|
||||
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<)"
|
||||
<< kScalarTypes[i] << R"(> {
|
||||
var result : vec4<)"
|
||||
<< kScalarTypes[i] << R"(>;
|
||||
return result;
|
||||
})";
|
||||
descriptor.cFragment.module = utils::CreateShaderModule(device, stream.str().c_str());
|
||||
|
||||
for (size_t j = 0; j < kColorFormats.size(); ++j) {
|
||||
descriptor.cTargets[0].format = kColorFormats[j];
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << R"(
|
||||
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<)"
|
||||
<< kScalarTypes[i] << R"(> {
|
||||
var result : vec4<)"
|
||||
<< kScalarTypes[i] << R"(>;
|
||||
return result;
|
||||
})";
|
||||
descriptor.cFragment.module = utils::CreateShaderModule(device, stream.str().c_str());
|
||||
|
||||
if (i == j) {
|
||||
device.CreateRenderPipeline(&descriptor);
|
||||
} else {
|
||||
|
@ -247,6 +253,110 @@ TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests that the component count of the color state target format must be fewer than that of the
|
||||
// fragment shader output.
|
||||
TEST_F(RenderPipelineValidationTest, FragmentOutputComponentCountCompatibility) {
|
||||
std::array<wgpu::TextureFormat, 3> kColorFormats = {wgpu::TextureFormat::R8Unorm,
|
||||
wgpu::TextureFormat::RG8Unorm,
|
||||
wgpu::TextureFormat::RGBA8Unorm};
|
||||
|
||||
std::array<wgpu::BlendFactor, 8> kBlendFactors = {wgpu::BlendFactor::Zero,
|
||||
wgpu::BlendFactor::One,
|
||||
wgpu::BlendFactor::SrcAlpha,
|
||||
wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
wgpu::BlendFactor::Src,
|
||||
wgpu::BlendFactor::DstAlpha,
|
||||
wgpu::BlendFactor::OneMinusDstAlpha,
|
||||
wgpu::BlendFactor::Dst};
|
||||
|
||||
for (size_t componentCount = 1; componentCount <= 4; ++componentCount) {
|
||||
utils::ComboRenderPipelineDescriptor descriptor;
|
||||
descriptor.vertex.module = vsModule;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << R"(
|
||||
[[stage(fragment)]] fn main() -> [[location(0)]] )";
|
||||
switch (componentCount) {
|
||||
case 1:
|
||||
stream << R"(f32 {
|
||||
return 1.0;
|
||||
})";
|
||||
break;
|
||||
case 2:
|
||||
stream << R"(vec2<f32> {
|
||||
return vec2<f32>(1.0, 1.0);
|
||||
})";
|
||||
break;
|
||||
case 3:
|
||||
stream << R"(vec3<f32> {
|
||||
return vec3<f32>(1.0, 1.0, 1.0);
|
||||
})";
|
||||
break;
|
||||
case 4:
|
||||
stream << R"(vec4<f32> {
|
||||
return vec4<f32>(1.0, 1.0, 1.0, 1.0);
|
||||
})";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
descriptor.cFragment.module = utils::CreateShaderModule(device, stream.str().c_str());
|
||||
|
||||
for (auto colorFormat : kColorFormats) {
|
||||
descriptor.cTargets[0].format = colorFormat;
|
||||
|
||||
descriptor.cTargets[0].blend = nullptr;
|
||||
if (componentCount >= utils::GetWGSLRenderableColorTextureComponentCount(colorFormat)) {
|
||||
device.CreateRenderPipeline(&descriptor);
|
||||
} else {
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
|
||||
descriptor.cTargets[0].blend = &descriptor.cBlends[0];
|
||||
|
||||
for (auto colorSrcFactor : kBlendFactors) {
|
||||
descriptor.cBlends[0].color.srcFactor = colorSrcFactor;
|
||||
for (auto colorDstFactor : kBlendFactors) {
|
||||
descriptor.cBlends[0].color.dstFactor = colorDstFactor;
|
||||
for (auto alphaSrcFactor : kBlendFactors) {
|
||||
descriptor.cBlends[0].alpha.srcFactor = alphaSrcFactor;
|
||||
for (auto alphaDstFactor : kBlendFactors) {
|
||||
descriptor.cBlends[0].alpha.dstFactor = alphaDstFactor;
|
||||
|
||||
bool valid = true;
|
||||
if (componentCount >=
|
||||
utils::GetWGSLRenderableColorTextureComponentCount(colorFormat)) {
|
||||
if (BlendFactorContainsSrcAlpha(
|
||||
descriptor.cTargets[0].blend->color.srcFactor) ||
|
||||
BlendFactorContainsSrcAlpha(
|
||||
descriptor.cTargets[0].blend->color.dstFactor) ||
|
||||
descriptor.cTargets[0].blend->alpha.srcFactor !=
|
||||
wgpu::BlendFactor::Zero ||
|
||||
descriptor.cTargets[0].blend->alpha.dstFactor ==
|
||||
wgpu::BlendFactor::Src ||
|
||||
descriptor.cTargets[0].blend->alpha.dstFactor ==
|
||||
wgpu::BlendFactor::OneMinusSrc ||
|
||||
BlendFactorContainsSrcAlpha(
|
||||
descriptor.cTargets[0].blend->alpha.dstFactor)) {
|
||||
valid = componentCount == 4;
|
||||
}
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
device.CreateRenderPipeline(&descriptor);
|
||||
} else {
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests that the sample count of the render pipeline must be valid.
|
||||
TEST_F(RenderPipelineValidationTest, SampleCount) {
|
||||
{
|
||||
|
|
|
@ -449,8 +449,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
|||
};
|
||||
[[group(0), binding(0)]] var<uniform> buffer0 : U;
|
||||
|
||||
[[stage(fragment)]] fn main() -> [[location(0)]] f32 {
|
||||
return buffer0.heapSize;
|
||||
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
|
||||
return vec4<f32>(buffer0.heapSize, 0.0, 0.0, 1.0);
|
||||
})");
|
||||
|
||||
wgpu::BlendState blend;
|
||||
|
|
|
@ -304,6 +304,47 @@ namespace utils {
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t GetWGSLRenderableColorTextureComponentCount(wgpu::TextureFormat textureFormat) {
|
||||
switch (textureFormat) {
|
||||
case wgpu::TextureFormat::R8Unorm:
|
||||
case wgpu::TextureFormat::R8Uint:
|
||||
case wgpu::TextureFormat::R8Sint:
|
||||
case wgpu::TextureFormat::R16Uint:
|
||||
case wgpu::TextureFormat::R16Sint:
|
||||
case wgpu::TextureFormat::R16Float:
|
||||
case wgpu::TextureFormat::R32Float:
|
||||
case wgpu::TextureFormat::R32Uint:
|
||||
case wgpu::TextureFormat::R32Sint:
|
||||
return 1u;
|
||||
case wgpu::TextureFormat::RG8Unorm:
|
||||
case wgpu::TextureFormat::RG8Uint:
|
||||
case wgpu::TextureFormat::RG8Sint:
|
||||
case wgpu::TextureFormat::RG16Uint:
|
||||
case wgpu::TextureFormat::RG16Sint:
|
||||
case wgpu::TextureFormat::RG16Float:
|
||||
case wgpu::TextureFormat::RG32Float:
|
||||
case wgpu::TextureFormat::RG32Uint:
|
||||
case wgpu::TextureFormat::RG32Sint:
|
||||
return 2u;
|
||||
case wgpu::TextureFormat::RGBA8Unorm:
|
||||
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||
case wgpu::TextureFormat::RGBA8Uint:
|
||||
case wgpu::TextureFormat::RGBA8Sint:
|
||||
case wgpu::TextureFormat::BGRA8Unorm:
|
||||
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||
case wgpu::TextureFormat::RGB10A2Unorm:
|
||||
case wgpu::TextureFormat::RGBA16Uint:
|
||||
case wgpu::TextureFormat::RGBA16Sint:
|
||||
case wgpu::TextureFormat::RGBA16Float:
|
||||
case wgpu::TextureFormat::RGBA32Float:
|
||||
case wgpu::TextureFormat::RGBA32Uint:
|
||||
case wgpu::TextureFormat::RGBA32Sint:
|
||||
return 4u;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetWGSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
|
||||
switch (textureFormat) {
|
||||
case wgpu::TextureFormat::RGBA8Unorm:
|
||||
|
|
|
@ -95,6 +95,7 @@ namespace utils {
|
|||
|
||||
const char* GetWGSLColorTextureComponentType(wgpu::TextureFormat textureFormat);
|
||||
const char* GetWGSLImageFormatQualifier(wgpu::TextureFormat textureFormat);
|
||||
uint32_t GetWGSLRenderableColorTextureComponentCount(wgpu::TextureFormat textureFormat);
|
||||
|
||||
wgpu::TextureDimension ViewDimensionToTextureDimension(
|
||||
const wgpu::TextureViewDimension dimension);
|
||||
|
|
Loading…
Reference in New Issue