Implement Validation For DepthStencilAttachment ReadOnly

Implements validation for RenderPassDepthStencilAttachmentDescriptor depthReadOnly and
stencilReadOnly flags to match WebGPU specification. Includes corresponding unit tests.

bug: dawn:485
Change-Id: I21e624850d5a393469569417f102fb979dbfdf27
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24602
Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Brandon Jones 2020-07-10 23:13:58 +00:00 committed by Commit Bot service account
parent 8c255acbe4
commit 7695afc902
5 changed files with 107 additions and 1 deletions

View File

@ -1147,9 +1147,11 @@
{"name": "depth load op", "type": "load op"}, {"name": "depth load op", "type": "load op"},
{"name": "depth store op", "type": "store op"}, {"name": "depth store op", "type": "store op"},
{"name": "clear depth", "type": "float"}, {"name": "clear depth", "type": "float"},
{"name": "depth read only", "type": "bool", "default": "false"},
{"name": "stencil load op", "type": "load op"}, {"name": "stencil load op", "type": "load op"},
{"name": "stencil store op", "type": "store op"}, {"name": "stencil store op", "type": "store op"},
{"name": "clear stencil", "type": "uint32_t", "default": "0"} {"name": "clear stencil", "type": "uint32_t", "default": "0"},
{"name": "stencil read only", "type": "bool", "default": "false"}
] ]
}, },

View File

@ -298,6 +298,31 @@ namespace dawn_native {
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp)); DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp));
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp)); DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp));
if (attachment->GetAspect() == wgpu::TextureAspect::All &&
attachment->GetFormat().HasStencil() &&
depthStencilAttachment->depthReadOnly != depthStencilAttachment->stencilReadOnly) {
return DAWN_VALIDATION_ERROR(
"depthReadOnly and stencilReadOnly must be the same when texture aspect is "
"'all'");
}
if (depthStencilAttachment->depthReadOnly &&
(depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load ||
depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store)) {
return DAWN_VALIDATION_ERROR(
"depthLoadOp must be load and depthStoreOp must be store when depthReadOnly "
"is true.");
}
if (depthStencilAttachment->stencilReadOnly &&
(depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load ||
depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store)) {
return DAWN_VALIDATION_ERROR(
"stencilLoadOp must be load and stencilStoreOp must be store when "
"stencilReadOnly "
"is true.");
}
if (depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear && if (depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear &&
std::isnan(depthStencilAttachment->clearDepth)) { std::isnan(depthStencilAttachment->clearDepth)) {
return DAWN_VALIDATION_ERROR("Depth clear value cannot be NaN"); return DAWN_VALIDATION_ERROR("Depth clear value cannot be NaN");

View File

@ -571,6 +571,7 @@ namespace dawn_native {
TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor) TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor)
: ObjectBase(texture->GetDevice()), : ObjectBase(texture->GetDevice()),
mTexture(texture), mTexture(texture),
mAspect(descriptor->aspect),
mFormat(GetDevice()->GetValidInternalFormat(descriptor->format)), mFormat(GetDevice()->GetValidInternalFormat(descriptor->format)),
mDimension(descriptor->dimension), mDimension(descriptor->dimension),
mRange({descriptor->baseMipLevel, descriptor->mipLevelCount, descriptor->baseArrayLayer, mRange({descriptor->baseMipLevel, descriptor->mipLevelCount, descriptor->baseArrayLayer,
@ -596,6 +597,11 @@ namespace dawn_native {
return mTexture.Get(); return mTexture.Get();
} }
wgpu::TextureAspect TextureViewBase::GetAspect() const {
ASSERT(!IsError());
return mAspect;
}
const Format& TextureViewBase::GetFormat() const { const Format& TextureViewBase::GetFormat() const {
ASSERT(!IsError()); ASSERT(!IsError());
return mFormat; return mFormat;

View File

@ -126,6 +126,7 @@ namespace dawn_native {
const TextureBase* GetTexture() const; const TextureBase* GetTexture() const;
TextureBase* GetTexture(); TextureBase* GetTexture();
wgpu::TextureAspect GetAspect() const;
const Format& GetFormat() const; const Format& GetFormat() const;
wgpu::TextureViewDimension GetDimension() const; wgpu::TextureViewDimension GetDimension() const;
uint32_t GetBaseMipLevel() const; uint32_t GetBaseMipLevel() const;
@ -139,6 +140,7 @@ namespace dawn_native {
Ref<TextureBase> mTexture; Ref<TextureBase> mTexture;
wgpu::TextureAspect mAspect;
// TODO(cwallez@chromium.org): This should be deduplicated in the Device // TODO(cwallez@chromium.org): This should be deduplicated in the Device
const Format& mFormat; const Format& mFormat;
wgpu::TextureViewDimension mDimension; wgpu::TextureViewDimension mDimension;

View File

@ -762,6 +762,77 @@ namespace {
} }
} }
TEST_F(RenderPassDescriptorValidationTest, ValidateDepthStencilReadOnly) {
wgpu::TextureView colorView =
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::RGBA8Unorm);
wgpu::TextureView depthStencilView =
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8);
wgpu::TextureView depthStencilViewNoStencil =
Create2DAttachment(device, 1, 1, wgpu::TextureFormat::Depth24Plus);
// Tests that a read-only pass with depthReadOnly set to true succeeds.
{
utils::ComboRenderPassDescriptor renderPass({colorView}, depthStencilView);
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.depthReadOnly = true;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.stencilReadOnly = true;
AssertBeginRenderPassSuccess(&renderPass);
}
// Tests that a pass with mismatched depthReadOnly and stencilReadOnly values passes when
// there is no stencil component in the format.
{
utils::ComboRenderPassDescriptor renderPass({colorView}, depthStencilViewNoStencil);
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.depthReadOnly = true;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.stencilReadOnly = false;
AssertBeginRenderPassSuccess(&renderPass);
}
// Tests that a pass with mismatched depthReadOnly and stencilReadOnly values fails when
// both depth and stencil components exist.
{
utils::ComboRenderPassDescriptor renderPass({colorView}, depthStencilView);
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.depthReadOnly = true;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.stencilReadOnly = false;
AssertBeginRenderPassError(&renderPass);
}
// Tests that a pass with loadOp set to clear and readOnly set to true fails.
{
utils::ComboRenderPassDescriptor renderPass({colorView}, depthStencilView);
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Clear;
renderPass.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.depthReadOnly = true;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Clear;
renderPass.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
renderPass.cDepthStencilAttachmentInfo.stencilReadOnly = true;
AssertBeginRenderPassError(&renderPass);
}
// Tests that a pass with storeOp set to clear and readOnly set to true fails.
{
utils::ComboRenderPassDescriptor renderPass({colorView}, depthStencilView);
renderPass.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Clear;
renderPass.cDepthStencilAttachmentInfo.depthReadOnly = true;
renderPass.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
renderPass.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Clear;
renderPass.cDepthStencilAttachmentInfo.stencilReadOnly = true;
AssertBeginRenderPassError(&renderPass);
}
}
// TODO(cwallez@chromium.org): Constraints on attachment aliasing? // TODO(cwallez@chromium.org): Constraints on attachment aliasing?
} // anonymous namespace } // anonymous namespace