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:
parent
c9b9290cc8
commit
050ab49a23
11
dawn.json
11
dawn.json
|
@ -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": [
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue