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,
|
auto AddColorFormat = [&AddFormat](wgpu::TextureFormat format, bool renderable,
|
||||||
bool supportsStorageUsage, uint32_t byteSize,
|
bool supportsStorageUsage, uint32_t byteSize,
|
||||||
SampleTypeBit sampleTypes) {
|
SampleTypeBit sampleTypes, uint8_t componentCount) {
|
||||||
Format internalFormat;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
internalFormat.isRenderable = renderable;
|
internalFormat.isRenderable = renderable;
|
||||||
|
@ -166,6 +166,7 @@ namespace dawn_native {
|
||||||
internalFormat.isSupported = true;
|
internalFormat.isSupported = true;
|
||||||
internalFormat.supportsStorageUsage = supportsStorageUsage;
|
internalFormat.supportsStorageUsage = supportsStorageUsage;
|
||||||
internalFormat.aspects = Aspect::Color;
|
internalFormat.aspects = Aspect::Color;
|
||||||
|
internalFormat.componentCount = componentCount;
|
||||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||||
firstAspect->block.byteSize = byteSize;
|
firstAspect->block.byteSize = byteSize;
|
||||||
firstAspect->block.width = 1;
|
firstAspect->block.width = 1;
|
||||||
|
@ -202,6 +203,7 @@ namespace dawn_native {
|
||||||
internalFormat.isSupported = true;
|
internalFormat.isSupported = true;
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = Aspect::Depth;
|
internalFormat.aspects = Aspect::Depth;
|
||||||
|
internalFormat.componentCount = 1;
|
||||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||||
firstAspect->block.byteSize = byteSize;
|
firstAspect->block.byteSize = byteSize;
|
||||||
firstAspect->block.width = 1;
|
firstAspect->block.width = 1;
|
||||||
|
@ -220,6 +222,7 @@ namespace dawn_native {
|
||||||
internalFormat.isSupported = false;
|
internalFormat.isSupported = false;
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = Aspect::Stencil;
|
internalFormat.aspects = Aspect::Stencil;
|
||||||
|
internalFormat.componentCount = 1;
|
||||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||||
firstAspect->block.byteSize = 1;
|
firstAspect->block.byteSize = 1;
|
||||||
firstAspect->block.width = 1;
|
firstAspect->block.width = 1;
|
||||||
|
@ -231,7 +234,8 @@ namespace dawn_native {
|
||||||
};
|
};
|
||||||
|
|
||||||
auto AddCompressedFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize,
|
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;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
internalFormat.isRenderable = false;
|
internalFormat.isRenderable = false;
|
||||||
|
@ -239,6 +243,7 @@ namespace dawn_native {
|
||||||
internalFormat.isSupported = isSupported;
|
internalFormat.isSupported = isSupported;
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = Aspect::Color;
|
internalFormat.aspects = Aspect::Color;
|
||||||
|
internalFormat.componentCount = componentCount;
|
||||||
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
AspectInfo* firstAspect = internalFormat.aspectInfo.data();
|
||||||
firstAspect->block.byteSize = byteSize;
|
firstAspect->block.byteSize = byteSize;
|
||||||
firstAspect->block.width = width;
|
firstAspect->block.width = width;
|
||||||
|
@ -249,10 +254,10 @@ namespace dawn_native {
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto AddMultiAspectFormat = [&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
auto AddMultiAspectFormat =
|
||||||
wgpu::TextureFormat firstFormat,
|
[&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
|
||||||
wgpu::TextureFormat secondFormat,
|
wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
|
||||||
bool isRenderable, bool isSupported) {
|
bool isRenderable, bool isSupported, uint8_t componentCount) {
|
||||||
Format internalFormat;
|
Format internalFormat;
|
||||||
internalFormat.format = format;
|
internalFormat.format = format;
|
||||||
internalFormat.isRenderable = isRenderable;
|
internalFormat.isRenderable = isRenderable;
|
||||||
|
@ -260,7 +265,7 @@ namespace dawn_native {
|
||||||
internalFormat.isSupported = isSupported;
|
internalFormat.isSupported = isSupported;
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = aspects;
|
internalFormat.aspects = aspects;
|
||||||
|
internalFormat.componentCount = componentCount;
|
||||||
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
|
const size_t firstFormatIndex = ComputeFormatIndex(firstFormat);
|
||||||
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
|
const size_t secondFormatIndex = ComputeFormatIndex(secondFormat);
|
||||||
|
|
||||||
|
@ -272,51 +277,51 @@ namespace dawn_native {
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// 1 byte color formats
|
// 1 byte color formats
|
||||||
AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, 1, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, 1, kAnyFloat, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, 1, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, 1, kAnyFloat, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, 1, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, 1, SampleTypeBit::Uint, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, 1, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, 1, SampleTypeBit::Sint, 1);
|
||||||
|
|
||||||
// 2 bytes color formats
|
// 2 bytes color formats
|
||||||
AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, 2, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, 2, SampleTypeBit::Uint, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, 2, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, 2, SampleTypeBit::Sint, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R16Float, true, false, 2, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::R16Float, true, false, 2, kAnyFloat, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, 2, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, 2, kAnyFloat, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, 2, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, 2, kAnyFloat, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, 2, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, 2, SampleTypeBit::Uint, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, 2, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, 2, SampleTypeBit::Sint, 2);
|
||||||
|
|
||||||
// 4 bytes color formats
|
// 4 bytes color formats
|
||||||
AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, 4, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, 4, SampleTypeBit::Uint, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, 4, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, 4, SampleTypeBit::Sint, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::R32Float, true, true, 4, SampleTypeBit::UnfilterableFloat);
|
AddColorFormat(wgpu::TextureFormat::R32Float, true, true, 4, SampleTypeBit::UnfilterableFloat, 1);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, 4, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, 4, SampleTypeBit::Uint, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, SampleTypeBit::Sint, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, kAnyFloat, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, kAnyFloat, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, kAnyFloat, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, kAnyFloat, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, SampleTypeBit::Uint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, SampleTypeBit::Sint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, kAnyFloat, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, kAnyFloat, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, kAnyFloat, 4);
|
||||||
|
|
||||||
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, 4, kAnyFloat, 3);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, 4, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, 4, kAnyFloat, 3);
|
||||||
|
|
||||||
// 8 bytes color formats
|
// 8 bytes color formats
|
||||||
AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, 8, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, 8, SampleTypeBit::Uint, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, 8, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, 8, SampleTypeBit::Sint, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, 8, SampleTypeBit::UnfilterableFloat);
|
AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, 8, SampleTypeBit::UnfilterableFloat, 2);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, 8, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, 8, SampleTypeBit::Uint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, 8, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, 8, SampleTypeBit::Sint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, 8, kAnyFloat);
|
AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, 8, kAnyFloat, 4);
|
||||||
|
|
||||||
// 16 bytes color formats
|
// 16 bytes color formats
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, 16, SampleTypeBit::Uint);
|
AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, 16, SampleTypeBit::Uint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, 16, SampleTypeBit::Sint);
|
AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, 16, SampleTypeBit::Sint, 4);
|
||||||
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, SampleTypeBit::UnfilterableFloat);
|
AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, SampleTypeBit::UnfilterableFloat, 4);
|
||||||
|
|
||||||
// Depth-stencil formats
|
// Depth-stencil formats
|
||||||
AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4);
|
AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4);
|
||||||
|
@ -327,30 +332,30 @@ namespace dawn_native {
|
||||||
// TODO(dawn:666): Implement the stencil8 format
|
// TODO(dawn:666): Implement the stencil8 format
|
||||||
AddStencilFormat(wgpu::TextureFormat::Stencil8);
|
AddStencilFormat(wgpu::TextureFormat::Stencil8);
|
||||||
AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8,
|
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.
|
// TODO(dawn:690): Implement Depth16Unorm, Depth24UnormStencil8, Depth32FloatStencil8.
|
||||||
|
|
||||||
// BC compressed formats
|
// BC compressed formats
|
||||||
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
|
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported, 1);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported, 2);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported, 2);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported, 3);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported, 3);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
|
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
|
||||||
|
|
||||||
// multi-planar formats
|
// multi-planar formats
|
||||||
const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
|
const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
|
||||||
AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
|
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
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,8 @@ namespace dawn_native {
|
||||||
bool isSupported;
|
bool isSupported;
|
||||||
bool supportsStorageUsage;
|
bool supportsStorageUsage;
|
||||||
Aspect aspects;
|
Aspect aspects;
|
||||||
|
// Only used for renderable color formats, number of color channels.
|
||||||
|
uint8_t componentCount;
|
||||||
|
|
||||||
bool IsColor() const;
|
bool IsColor() const;
|
||||||
bool HasDepth() const;
|
bool HasDepth() const;
|
||||||
|
|
|
@ -253,10 +253,22 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateColorTargetState(DeviceBase* device,
|
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,
|
const ColorTargetState* descriptor,
|
||||||
bool fragmentWritten,
|
bool fragmentWritten,
|
||||||
wgpu::TextureComponentType fragmentOutputBaseType) {
|
const EntryPointMetadata::FragmentOutputVariableInfo& fragmentOutputVariable) {
|
||||||
if (descriptor->nextInChain != nullptr) {
|
if (descriptor->nextInChain != nullptr) {
|
||||||
return DAWN_VALIDATION_ERROR("nextInChain must be 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");
|
"Color format must be blendable when blending is enabled");
|
||||||
}
|
}
|
||||||
if (fragmentWritten) {
|
if (fragmentWritten) {
|
||||||
if (fragmentOutputBaseType != format->GetAspectInfo(Aspect::Color).baseType) {
|
if (fragmentOutputVariable.baseType !=
|
||||||
|
format->GetAspectInfo(Aspect::Color).baseType) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Color format must match the fragment stage output type");
|
"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 {
|
} else {
|
||||||
if (descriptor->writeMask != wgpu::ColorWriteMask::None) {
|
if (descriptor->writeMask != wgpu::ColorWriteMask::None) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
|
@ -311,10 +350,10 @@ namespace dawn_native {
|
||||||
descriptor->module->GetEntryPoint(descriptor->entryPoint);
|
descriptor->module->GetEntryPoint(descriptor->entryPoint);
|
||||||
for (ColorAttachmentIndex i(uint8_t(0));
|
for (ColorAttachmentIndex i(uint8_t(0));
|
||||||
i < ColorAttachmentIndex(static_cast<uint8_t>(descriptor->targetCount)); ++i) {
|
i < ColorAttachmentIndex(static_cast<uint8_t>(descriptor->targetCount)); ++i) {
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateColorTargetState(device,
|
||||||
ValidateColorTargetState(device, &descriptor->targets[static_cast<uint8_t>(i)],
|
&descriptor->targets[static_cast<uint8_t>(i)],
|
||||||
fragmentMetadata.fragmentOutputsWritten[i],
|
fragmentMetadata.fragmentOutputsWritten[i],
|
||||||
fragmentMetadata.fragmentOutputFormatBaseTypes[i]));
|
fragmentMetadata.fragmentOutputVariables[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -875,8 +875,16 @@ namespace dawn_native {
|
||||||
ColorAttachmentIndex attachment(
|
ColorAttachmentIndex attachment(
|
||||||
static_cast<uint8_t>(unsanitizedAttachment));
|
static_cast<uint8_t>(unsanitizedAttachment));
|
||||||
DAWN_TRY_ASSIGN(
|
DAWN_TRY_ASSIGN(
|
||||||
metadata->fragmentOutputFormatBaseTypes[attachment],
|
metadata->fragmentOutputVariables[attachment].baseType,
|
||||||
TintComponentTypeToTextureComponentType(output_var.component_type));
|
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);
|
metadata->fragmentOutputsWritten.set(attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,8 +173,12 @@ namespace dawn_native {
|
||||||
ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> usedVertexInputs;
|
ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> usedVertexInputs;
|
||||||
|
|
||||||
// An array to record the basic types (float, int and uint) of the fragment shader outputs.
|
// An array to record the basic types (float, int and uint) of the fragment shader outputs.
|
||||||
ityp::array<ColorAttachmentIndex, wgpu::TextureComponentType, kMaxColorAttachments>
|
struct FragmentOutputVariableInfo {
|
||||||
fragmentOutputFormatBaseTypes;
|
wgpu::TextureComponentType baseType;
|
||||||
|
uint8_t componentCount;
|
||||||
|
};
|
||||||
|
ityp::array<ColorAttachmentIndex, FragmentOutputVariableInfo, kMaxColorAttachments>
|
||||||
|
fragmentOutputVariables;
|
||||||
ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> fragmentOutputsWritten;
|
ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments> fragmentOutputsWritten;
|
||||||
|
|
||||||
struct InterStageVariableInfo {
|
struct InterStageVariableInfo {
|
||||||
|
|
|
@ -288,8 +288,9 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
spirv_cross::SPIRType::BaseType shaderFragmentOutputBaseType =
|
spirv_cross::SPIRType::BaseType shaderFragmentOutputBaseType =
|
||||||
compiler.get_type(fragmentOutput.base_type_id).basetype;
|
compiler.get_type(fragmentOutput.base_type_id).basetype;
|
||||||
metadata->fragmentOutputFormatBaseTypes[attachment] =
|
// spriv path so temporarily always set to 4u to always pass validation
|
||||||
SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType);
|
metadata->fragmentOutputVariables[attachment] = {
|
||||||
|
SpirvBaseTypeToTextureComponentType(shaderFragmentOutputBaseType), 4u};
|
||||||
metadata->fragmentOutputsWritten.set(attachment);
|
metadata->fragmentOutputsWritten.set(attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,14 @@ class RenderPipelineValidationTest : public ValidationTest {
|
||||||
wgpu::ShaderModule fsModuleUint;
|
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 cases where creation should succeed
|
||||||
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
|
TEST_F(RenderPipelineValidationTest, CreationSuccess) {
|
||||||
{
|
{
|
||||||
|
@ -216,18 +224,14 @@ TEST_F(RenderPipelineValidationTest, NonBlendableFormat) {
|
||||||
|
|
||||||
// Tests that the format of the color state descriptor must match the output of the fragment shader.
|
// Tests that the format of the color state descriptor must match the output of the fragment shader.
|
||||||
TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
|
TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
|
||||||
constexpr uint32_t kNumTextureFormatBaseType = 3u;
|
std::array<const char*, 3> kScalarTypes = {{"f32", "i32", "u32"}};
|
||||||
std::array<const char*, kNumTextureFormatBaseType> kScalarTypes = {{"f32", "i32", "u32"}};
|
std::array<wgpu::TextureFormat, 3> kColorFormats = {{wgpu::TextureFormat::RGBA8Unorm,
|
||||||
std::array<wgpu::TextureFormat, kNumTextureFormatBaseType> kColorFormats = {
|
wgpu::TextureFormat::RGBA8Sint,
|
||||||
{wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8Sint,
|
|
||||||
wgpu::TextureFormat::RGBA8Uint}};
|
wgpu::TextureFormat::RGBA8Uint}};
|
||||||
|
|
||||||
for (size_t i = 0; i < kNumTextureFormatBaseType; ++i) {
|
for (size_t i = 0; i < kScalarTypes.size(); ++i) {
|
||||||
for (size_t j = 0; j < kNumTextureFormatBaseType; ++j) {
|
|
||||||
utils::ComboRenderPipelineDescriptor descriptor;
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
descriptor.vertex.module = vsModule;
|
descriptor.vertex.module = vsModule;
|
||||||
descriptor.cTargets[0].format = kColorFormats[j];
|
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << R"(
|
stream << R"(
|
||||||
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<)"
|
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<)"
|
||||||
|
@ -238,6 +242,8 @@ TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
|
||||||
})";
|
})";
|
||||||
descriptor.cFragment.module = utils::CreateShaderModule(device, stream.str().c_str());
|
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];
|
||||||
if (i == j) {
|
if (i == j) {
|
||||||
device.CreateRenderPipeline(&descriptor);
|
device.CreateRenderPipeline(&descriptor);
|
||||||
} else {
|
} 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.
|
/// Tests that the sample count of the render pipeline must be valid.
|
||||||
TEST_F(RenderPipelineValidationTest, SampleCount) {
|
TEST_F(RenderPipelineValidationTest, SampleCount) {
|
||||||
{
|
{
|
||||||
|
|
|
@ -449,8 +449,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
||||||
};
|
};
|
||||||
[[group(0), binding(0)]] var<uniform> buffer0 : U;
|
[[group(0), binding(0)]] var<uniform> buffer0 : U;
|
||||||
|
|
||||||
[[stage(fragment)]] fn main() -> [[location(0)]] f32 {
|
[[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
|
||||||
return buffer0.heapSize;
|
return vec4<f32>(buffer0.heapSize, 0.0, 0.0, 1.0);
|
||||||
})");
|
})");
|
||||||
|
|
||||||
wgpu::BlendState blend;
|
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) {
|
const char* GetWGSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
|
||||||
switch (textureFormat) {
|
switch (textureFormat) {
|
||||||
case wgpu::TextureFormat::RGBA8Unorm:
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
|
|
@ -95,6 +95,7 @@ namespace utils {
|
||||||
|
|
||||||
const char* GetWGSLColorTextureComponentType(wgpu::TextureFormat textureFormat);
|
const char* GetWGSLColorTextureComponentType(wgpu::TextureFormat textureFormat);
|
||||||
const char* GetWGSLImageFormatQualifier(wgpu::TextureFormat textureFormat);
|
const char* GetWGSLImageFormatQualifier(wgpu::TextureFormat textureFormat);
|
||||||
|
uint32_t GetWGSLRenderableColorTextureComponentCount(wgpu::TextureFormat textureFormat);
|
||||||
|
|
||||||
wgpu::TextureDimension ViewDimensionToTextureDimension(
|
wgpu::TextureDimension ViewDimensionToTextureDimension(
|
||||||
const wgpu::TextureViewDimension dimension);
|
const wgpu::TextureViewDimension dimension);
|
||||||
|
|
Loading…
Reference in New Issue