Implement RenderPassEncoder::SetViewport - front end

This patch implements RenderPassEncoder::SetViewport. It also adds
validation code, and validation tests as well.

BUG=dawn:53
TEST=dawn_unittests

Change-Id: Idc27f4098761a57fc10e53be82bd3c4b35b53cb4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8542
Commit-Queue: Yunchao He <yunchao.he@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Yunchao He 2019-07-04 15:30:59 +00:00 committed by Commit Bot service account
parent c9b9290cc8
commit 050ab49a23
7 changed files with 282 additions and 0 deletions

View File

@ -825,6 +825,17 @@
{"name": "color", "type": "color", "annotation": "const*"}
]
},
{
"name": "set viewport",
"args": [
{"name": "x", "type": "float"},
{"name": "y", "type": "float"},
{"name": "width", "type": "float"},
{"name": "height", "type": "float"},
{"name": "min depth", "type": "float"},
{"name": "max depth", "type": "float"}
]
},
{
"name": "set scissor rect",
"args": [

View File

@ -1209,6 +1209,10 @@ namespace dawn_native {
mIterator.NextCommand<SetBlendColorCmd>();
} break;
case Command::SetViewport: {
mIterator.NextCommand<SetViewportCmd>();
} break;
case Command::SetScissorRect: {
mIterator.NextCommand<SetScissorRectCmd>();
} break;

View File

@ -112,6 +112,10 @@ namespace dawn_native {
SetStencilReferenceCmd* cmd = commands->NextCommand<SetStencilReferenceCmd>();
cmd->~SetStencilReferenceCmd();
} break;
case Command::SetViewport: {
SetViewportCmd* cmd = commands->NextCommand<SetViewportCmd>();
cmd->~SetViewportCmd();
} break;
case Command::SetScissorRect: {
SetScissorRectCmd* cmd = commands->NextCommand<SetScissorRectCmd>();
cmd->~SetScissorRectCmd();
@ -229,6 +233,10 @@ namespace dawn_native {
commands->NextCommand<SetStencilReferenceCmd>();
break;
case Command::SetViewport:
commands->NextCommand<SetViewportCmd>();
break;
case Command::SetScissorRect:
commands->NextCommand<SetScissorRectCmd>();
break;

View File

@ -51,6 +51,7 @@ namespace dawn_native {
SetComputePipeline,
SetRenderPipeline,
SetStencilReference,
SetViewport,
SetScissorRect,
SetBlendColor,
SetBindGroup,
@ -192,6 +193,10 @@ namespace dawn_native {
uint32_t reference;
};
struct SetViewportCmd {
float x, y, width, height, minDepth, maxDepth;
};
struct SetScissorRectCmd {
uint32_t x, y, width, height;
};

View File

@ -21,6 +21,7 @@
#include "dawn_native/Device.h"
#include "dawn_native/RenderPipeline.h"
#include <math.h>
#include <string.h>
namespace dawn_native {
@ -140,6 +141,44 @@ namespace dawn_native {
cmd->color = *color;
}
void RenderPassEncoderBase::SetViewport(float x,
float y,
float width,
float height,
float minDepth,
float maxDepth) {
if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) {
return;
}
if (isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) ||
isnan(maxDepth)) {
mTopLevelEncoder->HandleError("NaN is not allowed.");
return;
}
// TODO(yunchao.he@intel.com): there are more restrictions for x, y, width and height in
// Vulkan, and height can be a negative value in Vulkan 1.1. Revisit this part later (say,
// for WebGPU v1).
if (width <= 0 || height <= 0) {
mTopLevelEncoder->HandleError("Width and height must be greater than 0.");
return;
}
if (minDepth < 0 || minDepth > 1 || maxDepth < 0 || maxDepth > 1) {
mTopLevelEncoder->HandleError("minDepth and maxDepth must be in [0, 1].");
return;
}
SetViewportCmd* cmd = mAllocator->Allocate<SetViewportCmd>(Command::SetViewport);
cmd->x = x;
cmd->y = y;
cmd->width = width;
cmd->height = height;
cmd->minDepth = minDepth;
cmd->maxDepth = maxDepth;
}
void RenderPassEncoderBase::SetScissorRect(uint32_t x,
uint32_t y,
uint32_t width,

View File

@ -50,6 +50,12 @@ namespace dawn_native {
void SetStencilReference(uint32_t reference);
void SetBlendColor(const Color* color);
void SetViewport(float x,
float y,
float width,
float height,
float minDepth,
float maxDepth);
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
template <typename T>

View File

@ -14,6 +14,215 @@
#include "tests/unittests/validation/ValidationTest.h"
#include <cmath>
class SetViewportTest : public ValidationTest {};
// Test to check basic use of SetViewport
TEST_F(SetViewportTest, Success) {
DummyRenderPass renderPass(device);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.0, 1.0);
pass.EndPass();
}
encoder.Finish();
}
// Test to check that NaN in viewport parameters is not allowed
TEST_F(SetViewportTest, ViewportParameterNaN) {
DummyRenderPass renderPass(device);
// x or y is NaN.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
}
// Test to check that an empty viewport is not allowed
TEST_F(SetViewportTest, EmptyViewport) {
DummyRenderPass renderPass(device);
// Width of viewport is zero.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
// Height of viewport is zero.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
// Both width and height of viewport are zero.
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
}
// Test to check that viewport larger than the framebuffer is allowed
TEST_F(SetViewportTest, ViewportLargerThanFramebuffer) {
DummyRenderPass renderPass(device);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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();
}
// Test to check that negative x in viewport is allowed
TEST_F(SetViewportTest, NegativeX) {
DummyRenderPass renderPass(device);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.SetViewport(-1.0, 0.0, 1.0, 1.0, 0.0, 1.0);
pass.EndPass();
}
encoder.Finish();
}
// Test to check that negative y in viewport is allowed
TEST_F(SetViewportTest, NegativeY) {
DummyRenderPass renderPass(device);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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_F(SetViewportTest, MinDepthOutOfRange) {
DummyRenderPass renderPass(device);
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
}
// Test to check that maxDepth out of range [0, 1] is not allowed
TEST_F(SetViewportTest, MaxDepthOutOfRange) {
DummyRenderPass renderPass(device);
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::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());
}
}
// Test to check that minDepth equal or less than maxDepth is allowed
TEST_F(SetViewportTest, MinDepthEqualOrLessThanMaxDepth) {
DummyRenderPass renderPass(device);
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.5, 0.5);
pass.EndPass();
encoder.Finish();
}
{
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.SetViewport(0.0, 0.0, 1.0, 1.0, 0.8, 0.5);
pass.EndPass();
encoder.Finish();
}
}
class SetScissorRectTest : public ValidationTest {
};