blob: e98d1c025b936404fa664cadabee518ce31f1665 [file] [log] [blame]
// Copyright 2018 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/unittests/validation/ValidationTest.h"
#include "common/Constants.h"
namespace {
class RenderPassDescriptorValidationTest : public ValidationTest {
};
dawn::Texture CreateTexture(dawn::Device& device,
dawn::TextureDimension dimension,
dawn::TextureFormat format,
uint32_t width,
uint32_t height,
uint32_t arrayLayer,
uint32_t levelCount) {
dawn::TextureDescriptor descriptor;
descriptor.dimension = dimension;
descriptor.size.width = width;
descriptor.size.height = height;
descriptor.size.depth = 1;
descriptor.arrayLayer = arrayLayer;
descriptor.format = format;
descriptor.levelCount = levelCount;
descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
return device.CreateTexture(&descriptor);
}
dawn::TextureView Create2DAttachment(dawn::Device& device,
uint32_t width,
uint32_t height,
dawn::TextureFormat format) {
dawn::Texture texture = CreateTexture(
device, dawn::TextureDimension::e2D, format, width, height, 1, 1);
return texture.CreateDefaultTextureView();
}
// A render pass with no attachments isn't valid
TEST_F(RenderPassDescriptorValidationTest, Empty) {
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.GetResult();
}
// A render pass with only one color or one depth attachment is ok
TEST_F(RenderPassDescriptorValidationTest, OneAttachment) {
// One color attachment
{
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color, dawn::LoadOp::Clear)
.GetResult();
}
// One depth-stencil attachment
{
dawn::TextureView depthStencil = Create2DAttachment(device, 1, 1, dawn::TextureFormat::D32FloatS8Uint);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(depthStencil, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
}
// Test OOB color attachment indices are handled
TEST_F(RenderPassDescriptorValidationTest, ColorAttachmentOutOfBounds) {
// For setting the color attachment, control case
{
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(kMaxColorAttachments - 1, color, dawn::LoadOp::Clear)
.GetResult();
}
// For setting the color attachment, OOB
{
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(kMaxColorAttachments, color, dawn::LoadOp::Clear)
.GetResult();
}
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
// For setting the clear color, control case
{
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color, dawn::LoadOp::Clear)
.SetColorAttachmentClearColor(kMaxColorAttachments - 1, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
// For setting the clear color, OOB
{
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color, dawn::LoadOp::Clear)
.SetColorAttachmentClearColor(kMaxColorAttachments, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
}
// Test setting a clear value without an attachment and vice-versa is ok.
TEST_F(RenderPassDescriptorValidationTest, ClearAndAttachmentMismatchIsOk) {
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
// For cleared attachment 0 doesn't get a color, clear color for 1 is unused
{
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color, dawn::LoadOp::Clear)
.SetColorAttachmentClearColor(1, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
// Clear depth stencil doesn't get values
{
dawn::TextureView depthStencil = Create2DAttachment(device, 1, 1, dawn::TextureFormat::D32FloatS8Uint);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(depthStencil, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// Clear values for depth-stencil when it isn't used
{
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color, dawn::LoadOp::Clear)
.SetDepthStencilAttachmentClearValue(0.0f, 0)
.GetResult();
}
}
// Attachments must have the same size
TEST_F(RenderPassDescriptorValidationTest, SizeMustMatch) {
dawn::TextureView color1x1A = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
dawn::TextureView color1x1B = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
dawn::TextureView color2x2 = Create2DAttachment(device, 2, 2, dawn::TextureFormat::R8G8B8A8Unorm);
dawn::TextureView depthStencil1x1 = Create2DAttachment(device, 1, 1, dawn::TextureFormat::D32FloatS8Uint);
dawn::TextureView depthStencil2x2 = Create2DAttachment(device, 2, 2, dawn::TextureFormat::D32FloatS8Uint);
// Control case: all the same size (1x1)
{
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color1x1A, dawn::LoadOp::Clear)
.SetColorAttachment(1, color1x1B, dawn::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil1x1, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// One of the color attachments has a different size
{
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color1x1A, dawn::LoadOp::Clear)
.SetColorAttachment(1, color2x2, dawn::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil1x1, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// The depth stencil attachment has a different size
{
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, color1x1A, dawn::LoadOp::Clear)
.SetColorAttachment(1, color1x1B, dawn::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil2x2, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
}
// Attachments formats must match whether they are used for color or depth-stencil
TEST_F(RenderPassDescriptorValidationTest, FormatMismatch) {
dawn::TextureView color = Create2DAttachment(device, 1, 1, dawn::TextureFormat::R8G8B8A8Unorm);
dawn::TextureView depthStencil = Create2DAttachment(device, 1, 1, dawn::TextureFormat::D32FloatS8Uint);
// Using depth-stencil for color
{
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, depthStencil, dawn::LoadOp::Clear)
.GetResult();
}
// Using color for depth-stencil
{
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(color, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
}
// Currently only texture views with layerCount == 1 are allowed to be color and depth stencil
// attachments
TEST_F(RenderPassDescriptorValidationTest, TextureViewLayerCountForColorAndDepthStencil) {
constexpr uint32_t kLevelCount = 1;
constexpr uint32_t kSize = 32;
constexpr dawn::TextureFormat kColorFormat = dawn::TextureFormat::R8G8B8A8Unorm;
constexpr dawn::TextureFormat kDepthStencilFormat = dawn::TextureFormat::D32FloatS8Uint;
constexpr uint32_t kArrayLayers = 10;
dawn::Texture colorTexture = CreateTexture(
device, dawn::TextureDimension::e2D, kColorFormat, kSize, kSize, kArrayLayers, kLevelCount);
dawn::Texture depthStencilTexture = CreateTexture(
device, dawn::TextureDimension::e2D, kDepthStencilFormat, kSize, kSize, kArrayLayers,
kLevelCount);
dawn::TextureViewDescriptor baseDescriptor;
baseDescriptor.dimension = dawn::TextureViewDimension::e2DArray;
baseDescriptor.baseArrayLayer = 0;
baseDescriptor.layerCount = kArrayLayers;
baseDescriptor.baseMipLevel = 0;
baseDescriptor.levelCount = kLevelCount;
// Using 2D array texture view with layerCount > 1 is not allowed for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.layerCount = 5;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D array texture view with layerCount > 1 is not allowed for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.layerCount = 5;
dawn::TextureView depthStencilView = depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(depthStencilView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D array texture view that covers the first layer of the texture is OK for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.baseArrayLayer = 0;
descriptor.layerCount = 1;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D array texture view that covers the first layer is OK for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.baseArrayLayer = 0;
descriptor.layerCount = 1;
dawn::TextureView depthStencilTextureView =
depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(
depthStencilTextureView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D array texture view that covers the last layer is OK for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.baseArrayLayer = kArrayLayers - 1;
descriptor.layerCount = 1;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D array texture view that covers the last layer is OK for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.baseArrayLayer = kArrayLayers - 1;
descriptor.layerCount = 1;
dawn::TextureView depthStencilTextureView =
depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(
depthStencilTextureView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
}
// Only 2D texture views with levelCount == 1 are allowed to be color attachments
TEST_F(RenderPassDescriptorValidationTest, TextureViewLevelCountForColorAndDepthStencil) {
constexpr uint32_t kArrayLayers = 1;
constexpr uint32_t kSize = 32;
constexpr dawn::TextureFormat kColorFormat = dawn::TextureFormat::R8G8B8A8Unorm;
constexpr dawn::TextureFormat kDepthStencilFormat = dawn::TextureFormat::D32FloatS8Uint;
constexpr uint32_t kLevelCount = 4;
dawn::Texture colorTexture = CreateTexture(
device, dawn::TextureDimension::e2D, kColorFormat, kSize, kSize, kArrayLayers, kLevelCount);
dawn::Texture depthStencilTexture = CreateTexture(
device, dawn::TextureDimension::e2D, kDepthStencilFormat, kSize, kSize, kArrayLayers,
kLevelCount);
dawn::TextureViewDescriptor baseDescriptor;
baseDescriptor.dimension = dawn::TextureViewDimension::e2D;
baseDescriptor.baseArrayLayer = 0;
baseDescriptor.layerCount = kArrayLayers;
baseDescriptor.baseMipLevel = 0;
baseDescriptor.levelCount = kLevelCount;
// Using 2D texture view with levelCount > 1 is not allowed for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.levelCount = 2;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D texture view with levelCount > 1 is not allowed for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.levelCount = 2;
dawn::TextureView depthStencilView = depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeError(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(depthStencilView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D texture view that covers the first level of the texture is OK for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.baseMipLevel = 0;
descriptor.levelCount = 1;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D texture view that covers the first level is OK for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.baseMipLevel = 0;
descriptor.levelCount = 1;
dawn::TextureView depthStencilTextureView =
depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(
depthStencilTextureView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D texture view that covers the last level is OK for color
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kColorFormat;
descriptor.baseMipLevel = kLevelCount - 1;
descriptor.levelCount = 1;
dawn::TextureView colorTextureView = colorTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetColorAttachment(0, colorTextureView, dawn::LoadOp::Clear)
.GetResult();
}
// Using 2D texture view that covers the last level is OK for depth stencil
{
dawn::TextureViewDescriptor descriptor = baseDescriptor;
descriptor.format = kDepthStencilFormat;
descriptor.baseMipLevel = kLevelCount - 1;
descriptor.levelCount = 1;
dawn::TextureView depthStencilTextureView =
depthStencilTexture.CreateTextureView(&descriptor);
AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
.SetDepthStencilAttachment(
depthStencilTextureView, dawn::LoadOp::Clear, dawn::LoadOp::Clear)
.GetResult();
}
}
// TODO(cwallez@chromium.org): Constraints on attachment aliasing?
} // anonymous namespace