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": "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",
|
"name": "set scissor rect",
|
||||||
"args": [
|
"args": [
|
||||||
|
|
|
@ -1209,6 +1209,10 @@ namespace dawn_native {
|
||||||
mIterator.NextCommand<SetBlendColorCmd>();
|
mIterator.NextCommand<SetBlendColorCmd>();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Command::SetViewport: {
|
||||||
|
mIterator.NextCommand<SetViewportCmd>();
|
||||||
|
} break;
|
||||||
|
|
||||||
case Command::SetScissorRect: {
|
case Command::SetScissorRect: {
|
||||||
mIterator.NextCommand<SetScissorRectCmd>();
|
mIterator.NextCommand<SetScissorRectCmd>();
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -112,6 +112,10 @@ namespace dawn_native {
|
||||||
SetStencilReferenceCmd* cmd = commands->NextCommand<SetStencilReferenceCmd>();
|
SetStencilReferenceCmd* cmd = commands->NextCommand<SetStencilReferenceCmd>();
|
||||||
cmd->~SetStencilReferenceCmd();
|
cmd->~SetStencilReferenceCmd();
|
||||||
} break;
|
} break;
|
||||||
|
case Command::SetViewport: {
|
||||||
|
SetViewportCmd* cmd = commands->NextCommand<SetViewportCmd>();
|
||||||
|
cmd->~SetViewportCmd();
|
||||||
|
} break;
|
||||||
case Command::SetScissorRect: {
|
case Command::SetScissorRect: {
|
||||||
SetScissorRectCmd* cmd = commands->NextCommand<SetScissorRectCmd>();
|
SetScissorRectCmd* cmd = commands->NextCommand<SetScissorRectCmd>();
|
||||||
cmd->~SetScissorRectCmd();
|
cmd->~SetScissorRectCmd();
|
||||||
|
@ -229,6 +233,10 @@ namespace dawn_native {
|
||||||
commands->NextCommand<SetStencilReferenceCmd>();
|
commands->NextCommand<SetStencilReferenceCmd>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Command::SetViewport:
|
||||||
|
commands->NextCommand<SetViewportCmd>();
|
||||||
|
break;
|
||||||
|
|
||||||
case Command::SetScissorRect:
|
case Command::SetScissorRect:
|
||||||
commands->NextCommand<SetScissorRectCmd>();
|
commands->NextCommand<SetScissorRectCmd>();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace dawn_native {
|
||||||
SetComputePipeline,
|
SetComputePipeline,
|
||||||
SetRenderPipeline,
|
SetRenderPipeline,
|
||||||
SetStencilReference,
|
SetStencilReference,
|
||||||
|
SetViewport,
|
||||||
SetScissorRect,
|
SetScissorRect,
|
||||||
SetBlendColor,
|
SetBlendColor,
|
||||||
SetBindGroup,
|
SetBindGroup,
|
||||||
|
@ -192,6 +193,10 @@ namespace dawn_native {
|
||||||
uint32_t reference;
|
uint32_t reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SetViewportCmd {
|
||||||
|
float x, y, width, height, minDepth, maxDepth;
|
||||||
|
};
|
||||||
|
|
||||||
struct SetScissorRectCmd {
|
struct SetScissorRectCmd {
|
||||||
uint32_t x, y, width, height;
|
uint32_t x, y, width, height;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
@ -140,6 +141,44 @@ namespace dawn_native {
|
||||||
cmd->color = *color;
|
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,
|
void RenderPassEncoderBase::SetScissorRect(uint32_t x,
|
||||||
uint32_t y,
|
uint32_t y,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
|
|
|
@ -50,6 +50,12 @@ namespace dawn_native {
|
||||||
|
|
||||||
void SetStencilReference(uint32_t reference);
|
void SetStencilReference(uint32_t reference);
|
||||||
void SetBlendColor(const Color* color);
|
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);
|
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -14,6 +14,215 @@
|
||||||
|
|
||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#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 {
|
class SetScissorRectTest : public ValidationTest {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue