mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-16 20:31:20 +00:00
BUG=dawn:21 Change-Id: I98499385d7397ab431e1bbe00add7ef01941cca6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7160 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
449 lines
12 KiB
C++
449 lines
12 KiB
C++
// Copyright 2017 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 <gtest/gtest.h>
|
|
|
|
#include "dawn_native/CommandAllocator.h"
|
|
|
|
#include <limits>
|
|
|
|
using namespace dawn_native;
|
|
|
|
// Definition of the command types used in the tests
|
|
enum class CommandType {
|
|
Draw,
|
|
Pipeline,
|
|
PushConstants,
|
|
Big,
|
|
Small,
|
|
};
|
|
|
|
struct CommandDraw {
|
|
uint32_t first;
|
|
uint32_t count;
|
|
};
|
|
|
|
struct CommandPipeline {
|
|
uint64_t pipeline;
|
|
uint32_t attachmentPoint;
|
|
};
|
|
|
|
struct CommandPushConstants {
|
|
uint8_t size;
|
|
uint8_t offset;
|
|
};
|
|
|
|
constexpr int kBigBufferSize = 65536;
|
|
|
|
struct CommandBig {
|
|
uint32_t buffer[kBigBufferSize];
|
|
};
|
|
|
|
struct CommandSmall {
|
|
uint16_t data;
|
|
};
|
|
|
|
// Test allocating nothing works
|
|
TEST(CommandAllocator, DoNothingAllocator) {
|
|
CommandAllocator allocator;
|
|
}
|
|
|
|
// Test iterating over nothing works
|
|
TEST(CommandAllocator, DoNothingAllocatorWithIterator) {
|
|
CommandAllocator allocator;
|
|
CommandIterator iterator(std::move(allocator));
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
|
|
// Test basic usage of allocator + iterator
|
|
TEST(CommandAllocator, Basic) {
|
|
CommandAllocator allocator;
|
|
|
|
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
|
uint32_t myAttachmentPoint = 2;
|
|
uint32_t myFirst = 42;
|
|
uint32_t myCount = 16;
|
|
|
|
{
|
|
CommandPipeline* pipeline = allocator.Allocate<CommandPipeline>(CommandType::Pipeline);
|
|
pipeline->pipeline = myPipeline;
|
|
pipeline->attachmentPoint = myAttachmentPoint;
|
|
|
|
CommandDraw* draw = allocator.Allocate<CommandDraw>(CommandType::Draw);
|
|
draw->first = myFirst;
|
|
draw->count = myCount;
|
|
}
|
|
|
|
{
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
|
|
bool hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Pipeline);
|
|
|
|
CommandPipeline* pipeline = iterator.NextCommand<CommandPipeline>();
|
|
ASSERT_EQ(pipeline->pipeline, myPipeline);
|
|
ASSERT_EQ(pipeline->attachmentPoint, myAttachmentPoint);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Draw);
|
|
|
|
CommandDraw* draw = iterator.NextCommand<CommandDraw>();
|
|
ASSERT_EQ(draw->first, myFirst);
|
|
ASSERT_EQ(draw->count, myCount);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
}
|
|
|
|
// Test basic usage of allocator + iterator with data
|
|
TEST(CommandAllocator, BasicWithData) {
|
|
CommandAllocator allocator;
|
|
|
|
uint8_t mySize = 8;
|
|
uint8_t myOffset = 3;
|
|
uint32_t myValues[5] = {6, 42, 0xFFFFFFFF, 0, 54};
|
|
|
|
{
|
|
CommandPushConstants* pushConstants = allocator.Allocate<CommandPushConstants>(CommandType::PushConstants);
|
|
pushConstants->size = mySize;
|
|
pushConstants->offset = myOffset;
|
|
|
|
uint32_t* values = allocator.AllocateData<uint32_t>(5);
|
|
for (size_t i = 0; i < 5; i++) {
|
|
values[i] = myValues[i];
|
|
}
|
|
}
|
|
|
|
{
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
|
|
bool hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::PushConstants);
|
|
|
|
CommandPushConstants* pushConstants = iterator.NextCommand<CommandPushConstants>();
|
|
ASSERT_EQ(pushConstants->size, mySize);
|
|
ASSERT_EQ(pushConstants->offset, myOffset);
|
|
|
|
uint32_t* values = iterator.NextData<uint32_t>(5);
|
|
for (size_t i = 0; i < 5; i++) {
|
|
ASSERT_EQ(values[i], myValues[i]);
|
|
}
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
}
|
|
|
|
// Test basic iterating several times
|
|
TEST(CommandAllocator, MultipleIterations) {
|
|
CommandAllocator allocator;
|
|
|
|
uint32_t myFirst = 42;
|
|
uint32_t myCount = 16;
|
|
|
|
{
|
|
CommandDraw* draw = allocator.Allocate<CommandDraw>(CommandType::Draw);
|
|
draw->first = myFirst;
|
|
draw->count = myCount;
|
|
}
|
|
|
|
{
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
|
|
// First iteration
|
|
bool hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Draw);
|
|
|
|
CommandDraw* draw = iterator.NextCommand<CommandDraw>();
|
|
ASSERT_EQ(draw->first, myFirst);
|
|
ASSERT_EQ(draw->count, myCount);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
// Second iteration
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Draw);
|
|
|
|
draw = iterator.NextCommand<CommandDraw>();
|
|
ASSERT_EQ(draw->first, myFirst);
|
|
ASSERT_EQ(draw->count, myCount);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
}
|
|
// Test large commands work
|
|
TEST(CommandAllocator, LargeCommands) {
|
|
CommandAllocator allocator;
|
|
|
|
const int kCommandCount = 5;
|
|
|
|
uint32_t count = 0;
|
|
for (int i = 0; i < kCommandCount; i++) {
|
|
CommandBig* big = allocator.Allocate<CommandBig>(CommandType::Big);
|
|
for (int j = 0; j < kBigBufferSize; j++) {
|
|
big->buffer[j] = count ++;
|
|
}
|
|
}
|
|
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
count = 0;
|
|
int numCommands = 0;
|
|
while (iterator.NextCommandId(&type)) {
|
|
ASSERT_EQ(type, CommandType::Big);
|
|
|
|
CommandBig* big = iterator.NextCommand<CommandBig>();
|
|
for (int i = 0; i < kBigBufferSize; i++) {
|
|
ASSERT_EQ(big->buffer[i], count);
|
|
count ++;
|
|
}
|
|
numCommands ++;
|
|
}
|
|
ASSERT_EQ(numCommands, kCommandCount);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
|
|
// Test many small commands work
|
|
TEST(CommandAllocator, ManySmallCommands) {
|
|
CommandAllocator allocator;
|
|
|
|
// Stay under max representable uint16_t
|
|
const int kCommandCount = 50000;
|
|
|
|
uint16_t count = 0;
|
|
for (int i = 0; i < kCommandCount; i++) {
|
|
CommandSmall* small = allocator.Allocate<CommandSmall>(CommandType::Small);
|
|
small->data = count ++;
|
|
}
|
|
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
count = 0;
|
|
int numCommands = 0;
|
|
while (iterator.NextCommandId(&type)) {
|
|
ASSERT_EQ(type, CommandType::Small);
|
|
|
|
CommandSmall* small = iterator.NextCommand<CommandSmall>();
|
|
ASSERT_EQ(small->data, count);
|
|
count ++;
|
|
numCommands ++;
|
|
}
|
|
ASSERT_EQ(numCommands, kCommandCount);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
|
|
/* ________
|
|
* / \
|
|
* | POUIC! |
|
|
* \_ ______/
|
|
* v
|
|
* ()_()
|
|
* (O.o)
|
|
* (> <)o
|
|
*/
|
|
|
|
// Test usage of iterator.Reset
|
|
TEST(CommandAllocator, IteratorReset) {
|
|
CommandAllocator allocator;
|
|
|
|
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
|
uint32_t myAttachmentPoint = 2;
|
|
uint32_t myFirst = 42;
|
|
uint32_t myCount = 16;
|
|
|
|
{
|
|
CommandPipeline* pipeline = allocator.Allocate<CommandPipeline>(CommandType::Pipeline);
|
|
pipeline->pipeline = myPipeline;
|
|
pipeline->attachmentPoint = myAttachmentPoint;
|
|
|
|
CommandDraw* draw = allocator.Allocate<CommandDraw>(CommandType::Draw);
|
|
draw->first = myFirst;
|
|
draw->count = myCount;
|
|
}
|
|
|
|
{
|
|
CommandIterator iterator(std::move(allocator));
|
|
CommandType type;
|
|
|
|
bool hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Pipeline);
|
|
|
|
CommandPipeline* pipeline = iterator.NextCommand<CommandPipeline>();
|
|
ASSERT_EQ(pipeline->pipeline, myPipeline);
|
|
ASSERT_EQ(pipeline->attachmentPoint, myAttachmentPoint);
|
|
|
|
iterator.Reset();
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Pipeline);
|
|
|
|
pipeline = iterator.NextCommand<CommandPipeline>();
|
|
ASSERT_EQ(pipeline->pipeline, myPipeline);
|
|
ASSERT_EQ(pipeline->attachmentPoint, myAttachmentPoint);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_TRUE(hasNext);
|
|
ASSERT_EQ(type, CommandType::Draw);
|
|
|
|
CommandDraw* draw = iterator.NextCommand<CommandDraw>();
|
|
ASSERT_EQ(draw->first, myFirst);
|
|
ASSERT_EQ(draw->count, myCount);
|
|
|
|
hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
}
|
|
|
|
// Test iterating empty iterators
|
|
TEST(CommandAllocator, EmptyIterator) {
|
|
{
|
|
CommandAllocator allocator;
|
|
CommandIterator iterator(std::move(allocator));
|
|
|
|
CommandType type;
|
|
bool hasNext = iterator.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
{
|
|
CommandAllocator allocator;
|
|
CommandIterator iterator1(std::move(allocator));
|
|
CommandIterator iterator2(std::move(iterator1));
|
|
|
|
CommandType type;
|
|
bool hasNext = iterator2.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator1.DataWasDestroyed();
|
|
iterator2.DataWasDestroyed();
|
|
}
|
|
{
|
|
CommandIterator iterator1;
|
|
CommandIterator iterator2(std::move(iterator1));
|
|
|
|
CommandType type;
|
|
bool hasNext = iterator2.NextCommandId(&type);
|
|
ASSERT_FALSE(hasNext);
|
|
|
|
iterator1.DataWasDestroyed();
|
|
iterator2.DataWasDestroyed();
|
|
}
|
|
}
|
|
|
|
template <size_t A>
|
|
struct alignas(A) AlignedStruct {
|
|
char dummy;
|
|
};
|
|
|
|
// Test for overflows in Allocate's computations, size 1 variant
|
|
TEST(CommandAllocator, AllocationOverflow_1) {
|
|
CommandAllocator allocator;
|
|
AlignedStruct<1>* data =
|
|
allocator.AllocateData<AlignedStruct<1>>(std::numeric_limits<size_t>::max() / 1);
|
|
ASSERT_EQ(data, nullptr);
|
|
}
|
|
|
|
// Test for overflows in Allocate's computations, size 2 variant
|
|
TEST(CommandAllocator, AllocationOverflow_2) {
|
|
CommandAllocator allocator;
|
|
AlignedStruct<2>* data =
|
|
allocator.AllocateData<AlignedStruct<2>>(std::numeric_limits<size_t>::max() / 2);
|
|
ASSERT_EQ(data, nullptr);
|
|
}
|
|
|
|
// Test for overflows in Allocate's computations, size 4 variant
|
|
TEST(CommandAllocator, AllocationOverflow_4) {
|
|
CommandAllocator allocator;
|
|
AlignedStruct<4>* data =
|
|
allocator.AllocateData<AlignedStruct<4>>(std::numeric_limits<size_t>::max() / 4);
|
|
ASSERT_EQ(data, nullptr);
|
|
}
|
|
|
|
// Test for overflows in Allocate's computations, size 8 variant
|
|
TEST(CommandAllocator, AllocationOverflow_8) {
|
|
CommandAllocator allocator;
|
|
AlignedStruct<8>* data =
|
|
allocator.AllocateData<AlignedStruct<8>>(std::numeric_limits<size_t>::max() / 8);
|
|
ASSERT_EQ(data, nullptr);
|
|
}
|
|
|
|
template <int DefaultValue>
|
|
struct IntWithDefault {
|
|
IntWithDefault() : value(DefaultValue) {
|
|
}
|
|
|
|
int value;
|
|
};
|
|
|
|
// Test that the allcator correctly defaults initalizes data for Allocate
|
|
TEST(CommandAllocator, AllocateDefaultInitializes) {
|
|
CommandAllocator allocator;
|
|
|
|
IntWithDefault<42>* int42 = allocator.Allocate<IntWithDefault<42>>(CommandType::Draw);
|
|
ASSERT_EQ(int42->value, 42);
|
|
|
|
IntWithDefault<43>* int43 = allocator.Allocate<IntWithDefault<43>>(CommandType::Draw);
|
|
ASSERT_EQ(int43->value, 43);
|
|
|
|
IntWithDefault<44>* int44 = allocator.Allocate<IntWithDefault<44>>(CommandType::Draw);
|
|
ASSERT_EQ(int44->value, 44);
|
|
|
|
CommandIterator iterator(std::move(allocator));
|
|
iterator.DataWasDestroyed();
|
|
}
|
|
|
|
// Test that the allcator correctly defaults initalizes data for AllocateData
|
|
TEST(CommandAllocator, AllocateDataDefaultInitializes) {
|
|
CommandAllocator allocator;
|
|
|
|
IntWithDefault<33>* int33 = allocator.AllocateData<IntWithDefault<33>>(1);
|
|
ASSERT_EQ(int33[0].value, 33);
|
|
|
|
IntWithDefault<34>* int34 = allocator.AllocateData<IntWithDefault<34>>(2);
|
|
ASSERT_EQ(int34[0].value, 34);
|
|
ASSERT_EQ(int34[0].value, 34);
|
|
|
|
IntWithDefault<35>* int35 = allocator.AllocateData<IntWithDefault<35>>(3);
|
|
ASSERT_EQ(int35[0].value, 35);
|
|
ASSERT_EQ(int35[1].value, 35);
|
|
ASSERT_EQ(int35[2].value, 35);
|
|
|
|
CommandIterator iterator(std::move(allocator));
|
|
iterator.DataWasDestroyed();
|
|
}
|