mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-14 15:46:28 +00:00
Make SetViewport validation match upstream WebGPU.
As a side-effect this allows empty viewports which need special handling in Vulkan because it is not allowed to set width to 0 (but ok to set height to 0). Validation tests are updated to cover the new validation checks. Most of the viewport end2end tests are rewritten because they didn't pass the new validation. A new end2end test is added to test various kinds of empty viewports to cover the extra logic in the Vulkan backend. Bug: dawn:542 Change-Id: I8bb25612eeed04162a6b942983167eacab3a1906 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/29681 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
1c25198384
commit
6c3da3dc5b
@@ -14,213 +14,123 @@
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class SetViewportTest : public ValidationTest {};
|
||||
class SetViewportTest : public ValidationTest {
|
||||
protected:
|
||||
void TestViewportCall(bool success,
|
||||
float x,
|
||||
float y,
|
||||
float width,
|
||||
float height,
|
||||
float minDepth,
|
||||
float maxDepth) {
|
||||
utils::BasicRenderPass rp = utils::CreateBasicRenderPass(device, kWidth, kHeight);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rp.renderPassInfo);
|
||||
pass.SetViewport(x, y, width, height, minDepth, maxDepth);
|
||||
pass.EndPass();
|
||||
|
||||
if (success) {
|
||||
encoder.Finish();
|
||||
} else {
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint32_t kWidth = 5;
|
||||
static constexpr uint32_t kHeight = 3;
|
||||
};
|
||||
|
||||
// Test to check basic use of SetViewport
|
||||
TEST_F(SetViewportTest, Success) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
}
|
||||
encoder.Finish();
|
||||
TestViewportCall(true, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Test to check that NaN in viewport parameters is not allowed
|
||||
TEST_F(SetViewportTest, ViewportParameterNaN) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
// x or y is NaN.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(NAN, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// width or height is NaN.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, NAN, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// minDepth or maxDepth is NaN.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, NAN, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
TestViewportCall(false, NAN, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, NAN, 1.0, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, NAN, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, NAN, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, NAN, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 0.0, NAN);
|
||||
}
|
||||
|
||||
// Test to check that an empty viewport is not allowed
|
||||
// Test to check that an empty viewport is allowed.
|
||||
TEST_F(SetViewportTest, EmptyViewport) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
// Width of viewport is zero.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 0.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
TestViewportCall(true, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0);
|
||||
|
||||
// Height of viewport is zero.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 0.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
TestViewportCall(true, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
// Both width and height of viewport are zero.
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
TestViewportCall(true, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Test to check that viewport larger than the framebuffer is allowed
|
||||
// Test to check that viewport larger than the framebuffer is disallowed
|
||||
TEST_F(SetViewportTest, ViewportLargerThanFramebuffer) {
|
||||
DummyRenderPass renderPass(device);
|
||||
// Control case: width and height are set to the render target size.
|
||||
TestViewportCall(true, 0.0, 0.0, kWidth, kHeight, 0.0, 1.0);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, renderPass.width + 1, renderPass.height + 1, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
}
|
||||
encoder.Finish();
|
||||
// Width is larger than the rendertarget's width
|
||||
TestViewportCall(false, 0.0, 0.0, kWidth + 1.0, kHeight, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, nextafter(float(kWidth), 1000.0f), kHeight, 0.0, 1.0);
|
||||
|
||||
// Height is larger than the rendertarget's height
|
||||
TestViewportCall(false, 0.0, 0.0, kWidth, kHeight + 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, kWidth, nextafter(float(kHeight), 1000.0f), 0.0, 1.0);
|
||||
|
||||
// x + width is larger than the rendertarget's width
|
||||
TestViewportCall(false, 2.0, 0.0, kWidth - 1.0, kHeight, 0.0, 1.0);
|
||||
TestViewportCall(false, 1.0, 0.0, nextafter(float(kWidth - 1.0), 1000.0f), kHeight, 0.0, 1.0);
|
||||
|
||||
// Height is larger than the rendertarget's height
|
||||
TestViewportCall(false, 0.0, 2.0, kWidth, kHeight - 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 1.0, kWidth, nextafter(float(kHeight - 1.0), 1000.0f), 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Test to check that negative x in viewport is allowed
|
||||
TEST_F(SetViewportTest, NegativeX) {
|
||||
DummyRenderPass renderPass(device);
|
||||
// Test to check that negative x in viewport is disallowed
|
||||
TEST_F(SetViewportTest, NegativeXYWidthHeight) {
|
||||
// Control case: everything set to 0 is allowed.
|
||||
TestViewportCall(true, +0.0, +0.0, +0.0, +0.0, 0.0, 1.0);
|
||||
TestViewportCall(true, -0.0, -0.0, -0.0, -0.0, 0.0, 1.0);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(-1.0, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
}
|
||||
encoder.Finish();
|
||||
// Nonzero negative values are disallowed
|
||||
TestViewportCall(false, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, -1.0, 1.0, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, -1.0, 1.0, 0.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, -1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Test to check that negative y in viewport is allowed
|
||||
TEST_F(SetViewportTest, NegativeY) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, -1.0, 1.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
}
|
||||
encoder.Finish();
|
||||
}
|
||||
|
||||
// Test to check that negative width in viewport is not allowed
|
||||
TEST_F(SetViewportTest, NegativeWidth) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, -1.0, 1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
|
||||
// Test to check that negative height in viewport is not allowed
|
||||
TEST_F(SetViewportTest, NegativeHeight) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 0.0, -1.0, 0.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
}
|
||||
|
||||
// Test to check that minDepth out of range [0, 1] is not allowed
|
||||
// Test to check that minDepth out of range [0, 1] is disallowed
|
||||
TEST_F(SetViewportTest, MinDepthOutOfRange) {
|
||||
DummyRenderPass renderPass(device);
|
||||
// MinDepth is -1
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, -1.0, 1.0);
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, -1.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 2.0, 1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
// MinDepth is 2 or 1 + epsilon
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 2.0, 1.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, nextafter(1.0f, 1000.0f), 1.0);
|
||||
}
|
||||
|
||||
// Test to check that maxDepth out of range [0, 1] is not allowed
|
||||
// Test to check that minDepth out of range [0, 1] is disallowed
|
||||
TEST_F(SetViewportTest, MaxDepthOutOfRange) {
|
||||
DummyRenderPass renderPass(device);
|
||||
// MaxDepth is -1
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 1.0, -1.0);
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.0, -1.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.0, 2.0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
// MaxDepth is 2 or 1 + epsilon
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 1.0, nextafter(1.0f, 1000.0f));
|
||||
}
|
||||
|
||||
// Test to check that minDepth equal or greater than maxDepth is allowed
|
||||
// Test to check that minDepth equal or greater than maxDepth is disallowed
|
||||
TEST_F(SetViewportTest, MinDepthEqualOrGreaterThanMaxDepth) {
|
||||
DummyRenderPass renderPass(device);
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.5, 0.5);
|
||||
pass.EndPass();
|
||||
encoder.Finish();
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.8, 0.5);
|
||||
pass.EndPass();
|
||||
encoder.Finish();
|
||||
}
|
||||
TestViewportCall(true, 0.0, 0.0, 1.0, 1.0, 0.5, 0.5);
|
||||
TestViewportCall(false, 0.0, 0.0, 1.0, 1.0, 0.8, 0.5);
|
||||
}
|
||||
|
||||
class SetScissorRectTest : public ValidationTest {};
|
||||
|
||||
Reference in New Issue
Block a user