mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-20 10:25:28 +00:00
Autoformat all tests and examples
Bug: none Change-Id: I69904944db1d4c2fbcca74bb8b66b5a7524e76bb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24642 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
3d80b5c378
commit
2afea0c671
@@ -20,8 +20,8 @@
|
||||
// This is ANGLE's BitSetIterator_unittests.cpp file.
|
||||
|
||||
class BitSetIteratorTest : public testing::Test {
|
||||
protected:
|
||||
std::bitset<40> mStateBits;
|
||||
protected:
|
||||
std::bitset<40> mStateBits;
|
||||
};
|
||||
|
||||
// Simple iterator test.
|
||||
|
||||
@@ -324,4 +324,4 @@ TEST(BuddyAllocatorTests, VariousSizeSameAlignment) {
|
||||
ASSERT_EQ(allocator.Allocate(16, alignment), 16ull);
|
||||
|
||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 0u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,4 +355,4 @@ TEST(BuddyMemoryAllocatorTests, AllocationOverflow) {
|
||||
constexpr uint64_t largeBlock = (1ull << 63) + 1;
|
||||
ResourceMemoryAllocation invalidAllocation = allocator.Allocate(largeBlock);
|
||||
ASSERT_EQ(invalidAllocation.GetInfo().mMethod, AllocationMethod::kInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ TEST(CommandAllocator, BasicWithData) {
|
||||
uint32_t myValues[5] = {6, 42, 0xFFFFFFFF, 0, 54};
|
||||
|
||||
{
|
||||
CommandPushConstants* pushConstants = allocator.Allocate<CommandPushConstants>(CommandType::PushConstants);
|
||||
CommandPushConstants* pushConstants =
|
||||
allocator.Allocate<CommandPushConstants>(CommandType::PushConstants);
|
||||
pushConstants->size = mySize;
|
||||
pushConstants->offset = myOffset;
|
||||
|
||||
@@ -209,7 +210,7 @@ TEST(CommandAllocator, LargeCommands) {
|
||||
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 ++;
|
||||
big->buffer[j] = count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,9 +224,9 @@ TEST(CommandAllocator, LargeCommands) {
|
||||
CommandBig* big = iterator.NextCommand<CommandBig>();
|
||||
for (int i = 0; i < kBigBufferSize; i++) {
|
||||
ASSERT_EQ(big->buffer[i], count);
|
||||
count ++;
|
||||
count++;
|
||||
}
|
||||
numCommands ++;
|
||||
numCommands++;
|
||||
}
|
||||
ASSERT_EQ(numCommands, kCommandCount);
|
||||
|
||||
@@ -242,7 +243,7 @@ TEST(CommandAllocator, ManySmallCommands) {
|
||||
uint16_t count = 0;
|
||||
for (int i = 0; i < kCommandCount; i++) {
|
||||
CommandSmall* small = allocator.Allocate<CommandSmall>(CommandType::Small);
|
||||
small->data = count ++;
|
||||
small->data = count++;
|
||||
}
|
||||
|
||||
CommandIterator iterator(std::move(allocator));
|
||||
@@ -254,8 +255,8 @@ TEST(CommandAllocator, ManySmallCommands) {
|
||||
|
||||
CommandSmall* small = iterator.NextCommand<CommandSmall>();
|
||||
ASSERT_EQ(small->data, count);
|
||||
count ++;
|
||||
numCommands ++;
|
||||
count++;
|
||||
numCommands++;
|
||||
}
|
||||
ASSERT_EQ(numCommands, kCommandCount);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace wgpu {
|
||||
A = 8,
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct IsDawnBitmask<Color> {
|
||||
static constexpr bool enable = true;
|
||||
};
|
||||
|
||||
@@ -21,278 +21,260 @@ using namespace dawn_native;
|
||||
|
||||
namespace {
|
||||
|
||||
int dummySuccess = 0xbeef;
|
||||
const char* dummyErrorMessage = "I am an error message :3";
|
||||
int dummySuccess = 0xbeef;
|
||||
const char* dummyErrorMessage = "I am an error message :3";
|
||||
|
||||
// Check returning a success MaybeError with {};
|
||||
TEST(ErrorTests, Error_Success) {
|
||||
auto ReturnSuccess = []() -> MaybeError {
|
||||
return {};
|
||||
};
|
||||
// Check returning a success MaybeError with {};
|
||||
TEST(ErrorTests, Error_Success) {
|
||||
auto ReturnSuccess = []() -> MaybeError { return {}; };
|
||||
|
||||
MaybeError result = ReturnSuccess();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
}
|
||||
MaybeError result = ReturnSuccess();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
}
|
||||
|
||||
// Check returning an error MaybeError with "return DAWN_VALIDATION_ERROR"
|
||||
TEST(ErrorTests, Error_Error) {
|
||||
auto ReturnError = []() -> MaybeError {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check returning an error MaybeError with "return DAWN_VALIDATION_ERROR"
|
||||
TEST(ErrorTests, Error_Error) {
|
||||
auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
|
||||
|
||||
MaybeError result = ReturnError();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
MaybeError result = ReturnError();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check returning a success ResultOrError with an implicit conversion
|
||||
TEST(ErrorTests, ResultOrError_Success) {
|
||||
auto ReturnSuccess = []() -> ResultOrError<int*> {
|
||||
return &dummySuccess;
|
||||
};
|
||||
// Check returning a success ResultOrError with an implicit conversion
|
||||
TEST(ErrorTests, ResultOrError_Success) {
|
||||
auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };
|
||||
|
||||
ResultOrError<int*> result = ReturnSuccess();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
|
||||
}
|
||||
ResultOrError<int*> result = ReturnSuccess();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
|
||||
}
|
||||
|
||||
// Check returning an error ResultOrError with "return DAWN_VALIDATION_ERROR"
|
||||
TEST(ErrorTests, ResultOrError_Error) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check returning an error ResultOrError with "return DAWN_VALIDATION_ERROR"
|
||||
TEST(ErrorTests, ResultOrError_Error) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
|
||||
ResultOrError<int*> result = ReturnError();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
ResultOrError<int*> result = ReturnError();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check DAWN_TRY handles successes correctly.
|
||||
TEST(ErrorTests, TRY_Success) {
|
||||
auto ReturnSuccess = []() -> MaybeError {
|
||||
return {};
|
||||
};
|
||||
// Check DAWN_TRY handles successes correctly.
|
||||
TEST(ErrorTests, TRY_Success) {
|
||||
auto ReturnSuccess = []() -> MaybeError { return {}; };
|
||||
|
||||
// We need to check that DAWN_TRY doesn't return on successes
|
||||
bool tryReturned = true;
|
||||
// We need to check that DAWN_TRY doesn't return on successes
|
||||
bool tryReturned = true;
|
||||
|
||||
auto Try = [ReturnSuccess, &tryReturned]() -> MaybeError {
|
||||
DAWN_TRY(ReturnSuccess());
|
||||
tryReturned = false;
|
||||
return {};
|
||||
};
|
||||
auto Try = [ReturnSuccess, &tryReturned]() -> MaybeError {
|
||||
DAWN_TRY(ReturnSuccess());
|
||||
tryReturned = false;
|
||||
return {};
|
||||
};
|
||||
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_FALSE(tryReturned);
|
||||
}
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_FALSE(tryReturned);
|
||||
}
|
||||
|
||||
// Check DAWN_TRY handles errors correctly.
|
||||
TEST(ErrorTests, TRY_Error) {
|
||||
auto ReturnError = []() -> MaybeError {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check DAWN_TRY handles errors correctly.
|
||||
TEST(ErrorTests, TRY_Error) {
|
||||
auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
|
||||
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
DAWN_TRY(ReturnError());
|
||||
// DAWN_TRY should return before this point
|
||||
EXPECT_FALSE(true);
|
||||
return {};
|
||||
};
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
DAWN_TRY(ReturnError());
|
||||
// DAWN_TRY should return before this point
|
||||
EXPECT_FALSE(true);
|
||||
return {};
|
||||
};
|
||||
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check DAWN_TRY adds to the backtrace.
|
||||
TEST(ErrorTests, TRY_AddsToBacktrace) {
|
||||
auto ReturnError = []() -> MaybeError {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check DAWN_TRY adds to the backtrace.
|
||||
TEST(ErrorTests, TRY_AddsToBacktrace) {
|
||||
auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
|
||||
|
||||
auto SingleTry = [ReturnError]() -> MaybeError {
|
||||
DAWN_TRY(ReturnError());
|
||||
return {};
|
||||
};
|
||||
auto SingleTry = [ReturnError]() -> MaybeError {
|
||||
DAWN_TRY(ReturnError());
|
||||
return {};
|
||||
};
|
||||
|
||||
auto DoubleTry = [SingleTry]() -> MaybeError {
|
||||
DAWN_TRY(SingleTry());
|
||||
return {};
|
||||
};
|
||||
auto DoubleTry = [SingleTry]() -> MaybeError {
|
||||
DAWN_TRY(SingleTry());
|
||||
return {};
|
||||
};
|
||||
|
||||
MaybeError singleResult = SingleTry();
|
||||
ASSERT_TRUE(singleResult.IsError());
|
||||
MaybeError singleResult = SingleTry();
|
||||
ASSERT_TRUE(singleResult.IsError());
|
||||
|
||||
MaybeError doubleResult = DoubleTry();
|
||||
ASSERT_TRUE(doubleResult.IsError());
|
||||
MaybeError doubleResult = DoubleTry();
|
||||
ASSERT_TRUE(doubleResult.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
|
||||
|
||||
ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
|
||||
}
|
||||
ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
|
||||
}
|
||||
|
||||
// Check DAWN_TRY_ASSIGN handles successes correctly.
|
||||
TEST(ErrorTests, TRY_RESULT_Success) {
|
||||
auto ReturnSuccess = []() -> ResultOrError<int*> {
|
||||
return &dummySuccess;
|
||||
};
|
||||
// Check DAWN_TRY_ASSIGN handles successes correctly.
|
||||
TEST(ErrorTests, TRY_RESULT_Success) {
|
||||
auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };
|
||||
|
||||
// We need to check that DAWN_TRY doesn't return on successes
|
||||
bool tryReturned = true;
|
||||
// We need to check that DAWN_TRY doesn't return on successes
|
||||
bool tryReturned = true;
|
||||
|
||||
auto Try = [ReturnSuccess, &tryReturned]() -> ResultOrError<int*> {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnSuccess());
|
||||
tryReturned = false;
|
||||
auto Try = [ReturnSuccess, &tryReturned]() -> ResultOrError<int*> {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnSuccess());
|
||||
tryReturned = false;
|
||||
|
||||
EXPECT_EQ(result, &dummySuccess);
|
||||
return result;
|
||||
};
|
||||
EXPECT_EQ(result, &dummySuccess);
|
||||
return result;
|
||||
};
|
||||
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_FALSE(tryReturned);
|
||||
ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
|
||||
}
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsSuccess());
|
||||
ASSERT_FALSE(tryReturned);
|
||||
ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
|
||||
}
|
||||
|
||||
// Check DAWN_TRY_ASSIGN handles errors correctly.
|
||||
TEST(ErrorTests, TRY_RESULT_Error) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check DAWN_TRY_ASSIGN handles errors correctly.
|
||||
TEST(ErrorTests, TRY_RESULT_Error) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
|
||||
auto Try = [ReturnError]() -> ResultOrError<int*> {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
auto Try = [ReturnError]() -> ResultOrError<int*> {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
|
||||
// DAWN_TRY should return before this point
|
||||
EXPECT_FALSE(true);
|
||||
return &dummySuccess;
|
||||
};
|
||||
// DAWN_TRY should return before this point
|
||||
EXPECT_FALSE(true);
|
||||
return &dummySuccess;
|
||||
};
|
||||
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check DAWN_TRY_ASSIGN adds to the backtrace.
|
||||
TEST(ErrorTests, TRY_RESULT_AddsToBacktrace) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check DAWN_TRY_ASSIGN adds to the backtrace.
|
||||
TEST(ErrorTests, TRY_RESULT_AddsToBacktrace) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
|
||||
auto SingleTry = [ReturnError]() -> ResultOrError<int*> {
|
||||
DAWN_TRY(ReturnError());
|
||||
return &dummySuccess;
|
||||
};
|
||||
auto SingleTry = [ReturnError]() -> ResultOrError<int*> {
|
||||
DAWN_TRY(ReturnError());
|
||||
return &dummySuccess;
|
||||
};
|
||||
|
||||
auto DoubleTry = [SingleTry]() -> ResultOrError<int*> {
|
||||
DAWN_TRY(SingleTry());
|
||||
return &dummySuccess;
|
||||
};
|
||||
auto DoubleTry = [SingleTry]() -> ResultOrError<int*> {
|
||||
DAWN_TRY(SingleTry());
|
||||
return &dummySuccess;
|
||||
};
|
||||
|
||||
ResultOrError<int*> singleResult = SingleTry();
|
||||
ASSERT_TRUE(singleResult.IsError());
|
||||
ResultOrError<int*> singleResult = SingleTry();
|
||||
ASSERT_TRUE(singleResult.IsError());
|
||||
|
||||
ResultOrError<int*> doubleResult = DoubleTry();
|
||||
ASSERT_TRUE(doubleResult.IsError());
|
||||
ResultOrError<int*> doubleResult = DoubleTry();
|
||||
ASSERT_TRUE(doubleResult.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
|
||||
std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
|
||||
|
||||
ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
|
||||
}
|
||||
ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
|
||||
}
|
||||
|
||||
// Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
|
||||
TEST(ErrorTests, TRY_RESULT_ConversionToError) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
|
||||
TEST(ErrorTests, TRY_RESULT_ConversionToError) {
|
||||
auto ReturnError = []() -> ResultOrError<int*> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
int* result = nullptr;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
|
||||
return {};
|
||||
};
|
||||
return {};
|
||||
};
|
||||
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
|
||||
// Version without Result<E*, T*>
|
||||
TEST(ErrorTests, TRY_RESULT_ConversionToErrorNonPointer) {
|
||||
auto ReturnError = []() -> ResultOrError<int> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
|
||||
// Version without Result<E*, T*>
|
||||
TEST(ErrorTests, TRY_RESULT_ConversionToErrorNonPointer) {
|
||||
auto ReturnError = []() -> ResultOrError<int> {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
int result = 0;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
auto Try = [ReturnError]() -> MaybeError {
|
||||
int result = 0;
|
||||
DAWN_TRY_ASSIGN(result, ReturnError());
|
||||
DAWN_UNUSED(result);
|
||||
|
||||
return {};
|
||||
};
|
||||
return {};
|
||||
};
|
||||
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
MaybeError result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
|
||||
// Check DAWN_TRY handles errors correctly.
|
||||
TEST(ErrorTests, TRY_ConversionToErrorOrResult) {
|
||||
auto ReturnError = []() -> MaybeError {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
|
||||
// Check DAWN_TRY handles errors correctly.
|
||||
TEST(ErrorTests, TRY_ConversionToErrorOrResult) {
|
||||
auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
|
||||
|
||||
auto Try = [ReturnError]() -> ResultOrError<int*>{
|
||||
DAWN_TRY(ReturnError());
|
||||
return &dummySuccess;
|
||||
};
|
||||
auto Try = [ReturnError]() -> ResultOrError<int*> {
|
||||
DAWN_TRY(ReturnError());
|
||||
return &dummySuccess;
|
||||
};
|
||||
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
ResultOrError<int*> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
// Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
|
||||
// Check DAWN_TRY handles errors correctly. Version without Result<E*, T*>
|
||||
TEST(ErrorTests, TRY_ConversionToErrorOrResultNonPointer) {
|
||||
auto ReturnError = []() -> MaybeError {
|
||||
return DAWN_VALIDATION_ERROR(dummyErrorMessage);
|
||||
};
|
||||
// Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
|
||||
// Check DAWN_TRY handles errors correctly. Version without Result<E*, T*>
|
||||
TEST(ErrorTests, TRY_ConversionToErrorOrResultNonPointer) {
|
||||
auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
|
||||
|
||||
auto Try = [ReturnError]() -> ResultOrError<int>{
|
||||
DAWN_TRY(ReturnError());
|
||||
return 42;
|
||||
};
|
||||
auto Try = [ReturnError]() -> ResultOrError<int> {
|
||||
DAWN_TRY(ReturnError());
|
||||
return 42;
|
||||
};
|
||||
|
||||
ResultOrError<int> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
ResultOrError<int> result = Try();
|
||||
ASSERT_TRUE(result.IsError());
|
||||
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
std::unique_ptr<ErrorData> errorData = result.AcquireError();
|
||||
ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -362,4 +362,4 @@ TEST(LinkedList, IsInList) {
|
||||
EXPECT_TRUE(n.IsInList());
|
||||
n.RemoveFromList();
|
||||
EXPECT_FALSE(n.IsInList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,4 +194,3 @@ TEST(ObjectBase, AssignNullptr) {
|
||||
obj = nullptr;
|
||||
ASSERT_EQ(refcount, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ TEST(PerStage, IterateAllStages) {
|
||||
counts[SingleShaderStage::Compute] = 0;
|
||||
|
||||
for (auto stage : IterateStages(kAllStages)) {
|
||||
counts[stage] ++;
|
||||
counts[stage]++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 1);
|
||||
@@ -64,7 +64,7 @@ TEST(PerStage, IterateOneStage) {
|
||||
counts[SingleShaderStage::Compute] = 0;
|
||||
|
||||
for (auto stage : IterateStages(wgpu::ShaderStage::Fragment)) {
|
||||
counts[stage] ++;
|
||||
counts[stage]++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
||||
@@ -80,7 +80,7 @@ TEST(PerStage, IterateNoStages) {
|
||||
counts[SingleShaderStage::Compute] = 0;
|
||||
|
||||
for (auto stage : IterateStages(wgpu::ShaderStage::Fragment & wgpu::ShaderStage::Vertex)) {
|
||||
counts[stage] ++;
|
||||
counts[stage]++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
||||
|
||||
@@ -410,4 +410,4 @@ TEST(Ref, MoveAssignmentDerived) {
|
||||
|
||||
destination = nullptr;
|
||||
EXPECT_TRUE(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,363 +19,367 @@
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T, typename E>
|
||||
void TestError(Result<T, E>* result, E expectedError) {
|
||||
EXPECT_TRUE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
template <typename T, typename E>
|
||||
void TestError(Result<T, E>* result, E expectedError) {
|
||||
EXPECT_TRUE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
|
||||
std::unique_ptr<E> storedError = result->AcquireError();
|
||||
EXPECT_EQ(*storedError, expectedError);
|
||||
}
|
||||
|
||||
template<typename T, typename E>
|
||||
void TestSuccess(Result<T, E>* result, T expectedSuccess) {
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_TRUE(result->IsSuccess());
|
||||
|
||||
const T storedSuccess = result->AcquireSuccess();
|
||||
EXPECT_EQ(storedSuccess, expectedSuccess);
|
||||
|
||||
// Once the success is acquired, result has an empty
|
||||
// payload and is neither in the success nor error state.
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
}
|
||||
|
||||
static int dummyError = 0xbeef;
|
||||
static float dummySuccess = 42.0f;
|
||||
static const float dummyConstSuccess = 42.0f;
|
||||
|
||||
class AClass : public RefCounted {
|
||||
public:
|
||||
int a = 0;
|
||||
};
|
||||
|
||||
// Tests using the following overload of TestSuccess make
|
||||
// local Ref instances to dummySuccessObj. Tests should
|
||||
// ensure any local Ref objects made along the way continue
|
||||
// to point to dummySuccessObj.
|
||||
template <typename T, typename E>
|
||||
void TestSuccess(Result<Ref<T>, E>* result, T* expectedSuccess) {
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_TRUE(result->IsSuccess());
|
||||
|
||||
// AClass starts with a reference count of 1 and stored
|
||||
// on the stack in the caller. The result parameter should
|
||||
// hold the only other reference to the object.
|
||||
EXPECT_EQ(expectedSuccess->GetRefCountForTesting(), 2u);
|
||||
|
||||
const Ref<T> storedSuccess = result->AcquireSuccess();
|
||||
EXPECT_EQ(storedSuccess.Get(), expectedSuccess);
|
||||
|
||||
// Once the success is acquired, result has an empty
|
||||
// payload and is neither in the success nor error state.
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
|
||||
// Once we call AcquireSuccess, result no longer stores
|
||||
// the object. storedSuccess should contain the only other
|
||||
// reference to the object.
|
||||
EXPECT_EQ(storedSuccess->GetRefCountForTesting(), 2u);
|
||||
}
|
||||
|
||||
// Result<void, E*>
|
||||
|
||||
// Test constructing an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ConstructingError) {
|
||||
Result<void, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, MovingError) {
|
||||
Result<void, int> result(std::make_unique<int>(dummyError));
|
||||
Result<void, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ReturningError) {
|
||||
auto CreateError = []() -> Result<void, int> { return {std::make_unique<int>(dummyError)}; };
|
||||
|
||||
Result<void, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ConstructingSuccess) {
|
||||
Result<void, int> result;
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.IsError());
|
||||
}
|
||||
|
||||
// Test moving a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, MovingSuccess) {
|
||||
Result<void, int> result;
|
||||
Result<void, int> movedResult(std::move(result));
|
||||
EXPECT_TRUE(movedResult.IsSuccess());
|
||||
EXPECT_FALSE(movedResult.IsError());
|
||||
}
|
||||
|
||||
// Test returning a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ReturningSuccess) {
|
||||
auto CreateError = []() -> Result<void, int> { return {}; };
|
||||
|
||||
Result<void, int> result = CreateError();
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.IsError());
|
||||
}
|
||||
|
||||
// Result<T*, E*>
|
||||
|
||||
// Test constructing an error Result<T*, E>
|
||||
TEST(ResultBothPointer, ConstructingError) {
|
||||
Result<float*, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<T*, E>
|
||||
TEST(ResultBothPointer, MovingError) {
|
||||
Result<float*, int> result(std::make_unique<int>(dummyError));
|
||||
Result<float*, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<T*, E>
|
||||
TEST(ResultBothPointer, ReturningError) {
|
||||
auto CreateError = []() -> Result<float*, int> { return {std::make_unique<int>(dummyError)}; };
|
||||
|
||||
Result<float*, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<T*, E>
|
||||
TEST(ResultBothPointer, ConstructingSuccess) {
|
||||
Result<float*, int> result(&dummySuccess);
|
||||
TestSuccess(&result, &dummySuccess);
|
||||
}
|
||||
|
||||
// Test moving a success Result<T*, E>
|
||||
TEST(ResultBothPointer, MovingSuccess) {
|
||||
Result<float*, int> result(&dummySuccess);
|
||||
Result<float*, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &dummySuccess);
|
||||
}
|
||||
|
||||
// Test returning a success Result<T*, E>
|
||||
TEST(ResultBothPointer, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<float*, int*> {
|
||||
return {&dummySuccess};
|
||||
};
|
||||
|
||||
Result<float*, int*> result = CreateSuccess();
|
||||
TestSuccess(&result, &dummySuccess);
|
||||
}
|
||||
|
||||
// Tests converting from a Result<TChild*, E>
|
||||
TEST(ResultBothPointer, ConversionFromChildClass) {
|
||||
struct T {
|
||||
int a;
|
||||
};
|
||||
struct TChild : T {};
|
||||
|
||||
TChild child;
|
||||
T* childAsT = &child;
|
||||
{
|
||||
Result<T*, int> result(&child);
|
||||
TestSuccess(&result, childAsT);
|
||||
std::unique_ptr<E> storedError = result->AcquireError();
|
||||
EXPECT_EQ(*storedError, expectedError);
|
||||
}
|
||||
{
|
||||
Result<TChild*, int> resultChild(&child);
|
||||
Result<T*, int> result(std::move(resultChild));
|
||||
TestSuccess(&result, childAsT);
|
||||
|
||||
template <typename T, typename E>
|
||||
void TestSuccess(Result<T, E>* result, T expectedSuccess) {
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_TRUE(result->IsSuccess());
|
||||
|
||||
const T storedSuccess = result->AcquireSuccess();
|
||||
EXPECT_EQ(storedSuccess, expectedSuccess);
|
||||
|
||||
// Once the success is acquired, result has an empty
|
||||
// payload and is neither in the success nor error state.
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
}
|
||||
{
|
||||
Result<TChild*, int> resultChild(&child);
|
||||
Result<T*, int> result = std::move(resultChild);
|
||||
TestSuccess(&result, childAsT);
|
||||
|
||||
static int dummyError = 0xbeef;
|
||||
static float dummySuccess = 42.0f;
|
||||
static const float dummyConstSuccess = 42.0f;
|
||||
|
||||
class AClass : public RefCounted {
|
||||
public:
|
||||
int a = 0;
|
||||
};
|
||||
|
||||
// Tests using the following overload of TestSuccess make
|
||||
// local Ref instances to dummySuccessObj. Tests should
|
||||
// ensure any local Ref objects made along the way continue
|
||||
// to point to dummySuccessObj.
|
||||
template <typename T, typename E>
|
||||
void TestSuccess(Result<Ref<T>, E>* result, T* expectedSuccess) {
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_TRUE(result->IsSuccess());
|
||||
|
||||
// AClass starts with a reference count of 1 and stored
|
||||
// on the stack in the caller. The result parameter should
|
||||
// hold the only other reference to the object.
|
||||
EXPECT_EQ(expectedSuccess->GetRefCountForTesting(), 2u);
|
||||
|
||||
const Ref<T> storedSuccess = result->AcquireSuccess();
|
||||
EXPECT_EQ(storedSuccess.Get(), expectedSuccess);
|
||||
|
||||
// Once the success is acquired, result has an empty
|
||||
// payload and is neither in the success nor error state.
|
||||
EXPECT_FALSE(result->IsError());
|
||||
EXPECT_FALSE(result->IsSuccess());
|
||||
|
||||
// Once we call AcquireSuccess, result no longer stores
|
||||
// the object. storedSuccess should contain the only other
|
||||
// reference to the object.
|
||||
EXPECT_EQ(storedSuccess->GetRefCountForTesting(), 2u);
|
||||
}
|
||||
}
|
||||
|
||||
// Result<const T*, E>
|
||||
// Result<void, E*>
|
||||
|
||||
// Test constructing an error Result<const T*, E>
|
||||
TEST(ResultBothPointerWithConstResult, ConstructingError) {
|
||||
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
// Test constructing an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ConstructingError) {
|
||||
Result<void, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<const T*, E>
|
||||
TEST(ResultBothPointerWithConstResult, MovingError) {
|
||||
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
||||
Result<const float*, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
// Test moving an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, MovingError) {
|
||||
Result<void, int> result(std::make_unique<int>(dummyError));
|
||||
Result<void, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ReturningError) {
|
||||
auto CreateError = []() -> Result<const float*, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
// Test returning an error Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ReturningError) {
|
||||
auto CreateError = []() -> Result<void, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
Result<void, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ConstructingSuccess) {
|
||||
Result<void, int> result;
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.IsError());
|
||||
}
|
||||
|
||||
// Test moving a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, MovingSuccess) {
|
||||
Result<void, int> result;
|
||||
Result<void, int> movedResult(std::move(result));
|
||||
EXPECT_TRUE(movedResult.IsSuccess());
|
||||
EXPECT_FALSE(movedResult.IsError());
|
||||
}
|
||||
|
||||
// Test returning a success Result<void, E>
|
||||
TEST(ResultOnlyPointerError, ReturningSuccess) {
|
||||
auto CreateError = []() -> Result<void, int> { return {}; };
|
||||
|
||||
Result<void, int> result = CreateError();
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
EXPECT_FALSE(result.IsError());
|
||||
}
|
||||
|
||||
// Result<T*, E*>
|
||||
|
||||
// Test constructing an error Result<T*, E>
|
||||
TEST(ResultBothPointer, ConstructingError) {
|
||||
Result<float*, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<T*, E>
|
||||
TEST(ResultBothPointer, MovingError) {
|
||||
Result<float*, int> result(std::make_unique<int>(dummyError));
|
||||
Result<float*, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<T*, E>
|
||||
TEST(ResultBothPointer, ReturningError) {
|
||||
auto CreateError = []() -> Result<float*, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
Result<float*, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<T*, E>
|
||||
TEST(ResultBothPointer, ConstructingSuccess) {
|
||||
Result<float*, int> result(&dummySuccess);
|
||||
TestSuccess(&result, &dummySuccess);
|
||||
}
|
||||
|
||||
// Test moving a success Result<T*, E>
|
||||
TEST(ResultBothPointer, MovingSuccess) {
|
||||
Result<float*, int> result(&dummySuccess);
|
||||
Result<float*, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &dummySuccess);
|
||||
}
|
||||
|
||||
// Test returning a success Result<T*, E>
|
||||
TEST(ResultBothPointer, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<float*, int*> { return {&dummySuccess}; };
|
||||
|
||||
Result<float*, int*> result = CreateSuccess();
|
||||
TestSuccess(&result, &dummySuccess);
|
||||
}
|
||||
|
||||
// Tests converting from a Result<TChild*, E>
|
||||
TEST(ResultBothPointer, ConversionFromChildClass) {
|
||||
struct T {
|
||||
int a;
|
||||
};
|
||||
struct TChild : T {};
|
||||
|
||||
TChild child;
|
||||
T* childAsT = &child;
|
||||
{
|
||||
Result<T*, int> result(&child);
|
||||
TestSuccess(&result, childAsT);
|
||||
}
|
||||
{
|
||||
Result<TChild*, int> resultChild(&child);
|
||||
Result<T*, int> result(std::move(resultChild));
|
||||
TestSuccess(&result, childAsT);
|
||||
}
|
||||
{
|
||||
Result<TChild*, int> resultChild(&child);
|
||||
Result<T*, int> result = std::move(resultChild);
|
||||
TestSuccess(&result, childAsT);
|
||||
}
|
||||
}
|
||||
|
||||
// Result<const T*, E>
|
||||
|
||||
// Test constructing an error Result<const T*, E>
|
||||
TEST(ResultBothPointerWithConstResult, ConstructingError) {
|
||||
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<const T*, E>
|
||||
TEST(ResultBothPointerWithConstResult, MovingError) {
|
||||
Result<const float*, int> result(std::make_unique<int>(dummyError));
|
||||
Result<const float*, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ReturningError) {
|
||||
auto CreateError = []() -> Result<const float*, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
Result<const float*, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ConstructingSuccess) {
|
||||
Result<const float*, int> result(&dummyConstSuccess);
|
||||
TestSuccess(&result, &dummyConstSuccess);
|
||||
}
|
||||
|
||||
// Test moving a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, MovingSuccess) {
|
||||
Result<const float*, int> result(&dummyConstSuccess);
|
||||
Result<const float*, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &dummyConstSuccess);
|
||||
}
|
||||
|
||||
// Test returning a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<const float*, int> { return {&dummyConstSuccess}; };
|
||||
|
||||
Result<const float*, int> result = CreateSuccess();
|
||||
TestSuccess(&result, &dummyConstSuccess);
|
||||
}
|
||||
|
||||
// Result<Ref<T>, E>
|
||||
|
||||
// Test constructing an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ConstructingError) {
|
||||
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, MovingError) {
|
||||
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
||||
Result<Ref<AClass>, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ReturningError) {
|
||||
auto CreateError = []() -> Result<Ref<AClass>, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
Result<Ref<AClass>, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ConstructingSuccess) {
|
||||
AClass success;
|
||||
|
||||
Ref<AClass> refObj(&success);
|
||||
Result<Ref<AClass>, int> result(std::move(refObj));
|
||||
TestSuccess(&result, &success);
|
||||
}
|
||||
|
||||
// Test moving a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, MovingSuccess) {
|
||||
AClass success;
|
||||
|
||||
Ref<AClass> refObj(&success);
|
||||
Result<Ref<AClass>, int> result(std::move(refObj));
|
||||
Result<Ref<AClass>, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &success);
|
||||
}
|
||||
|
||||
// Test returning a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ReturningSuccess) {
|
||||
AClass success;
|
||||
auto CreateSuccess = [&success]() -> Result<Ref<AClass>, int> {
|
||||
return Ref<AClass>(&success);
|
||||
};
|
||||
|
||||
Result<Ref<AClass>, int> result = CreateSuccess();
|
||||
TestSuccess(&result, &success);
|
||||
}
|
||||
|
||||
class OtherClass {
|
||||
public:
|
||||
int a = 0;
|
||||
};
|
||||
class Base : public RefCounted {};
|
||||
class Child : public OtherClass, public Base {};
|
||||
|
||||
Result<const float*, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
// Test constructing a Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildConstructor) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
// Test constructing a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ConstructingSuccess) {
|
||||
Result<const float*, int> result(&dummyConstSuccess);
|
||||
TestSuccess(&result, &dummyConstSuccess);
|
||||
}
|
||||
Result<Ref<Base>, int> result(std::move(refChild));
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
// Test moving a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, MovingSuccess) {
|
||||
Result<const float*, int> result(&dummyConstSuccess);
|
||||
Result<const float*, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &dummyConstSuccess);
|
||||
}
|
||||
// Test copy constructing Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildCopyConstructor) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
// Test returning a success Result<const T*, E*>
|
||||
TEST(ResultBothPointerWithConstResult, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<const float*, int> { return {&dummyConstSuccess}; };
|
||||
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
||||
Result<Ref<Base>, int> result(std::move(resultChild));
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
Result<const float*, int> result = CreateSuccess();
|
||||
TestSuccess(&result, &dummyConstSuccess);
|
||||
}
|
||||
// Test assignment operator for Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildAssignmentOperator) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
// Result<Ref<T>, E>
|
||||
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
||||
Result<Ref<Base>, int> result = std::move(resultChild);
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
// Test constructing an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ConstructingError) {
|
||||
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
// Result<T, E>
|
||||
|
||||
// Test moving an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, MovingError) {
|
||||
Result<Ref<AClass>, int> result(std::make_unique<int>(dummyError));
|
||||
Result<Ref<AClass>, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
// Test constructing an error Result<T, E>
|
||||
TEST(ResultGeneric, ConstructingError) {
|
||||
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ReturningError) {
|
||||
auto CreateError = []() -> Result<Ref<AClass>, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
// Test moving an error Result<T, E>
|
||||
TEST(ResultGeneric, MovingError) {
|
||||
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
||||
Result<std::vector<float>, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
Result<Ref<AClass>, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
// Test returning an error Result<T, E>
|
||||
TEST(ResultGeneric, ReturningError) {
|
||||
auto CreateError = []() -> Result<std::vector<float>, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
// Test constructing a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ConstructingSuccess) {
|
||||
AClass success;
|
||||
Result<std::vector<float>, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
Ref<AClass> refObj(&success);
|
||||
Result<Ref<AClass>, int> result(std::move(refObj));
|
||||
TestSuccess(&result, &success);
|
||||
}
|
||||
// Test constructing a success Result<T, E>
|
||||
TEST(ResultGeneric, ConstructingSuccess) {
|
||||
Result<std::vector<float>, int> result({1.0f});
|
||||
TestSuccess(&result, {1.0f});
|
||||
}
|
||||
|
||||
// Test moving a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, MovingSuccess) {
|
||||
AClass success;
|
||||
// Test moving a success Result<T, E>
|
||||
TEST(ResultGeneric, MovingSuccess) {
|
||||
Result<std::vector<float>, int> result({1.0f});
|
||||
Result<std::vector<float>, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, {1.0f});
|
||||
}
|
||||
|
||||
Ref<AClass> refObj(&success);
|
||||
Result<Ref<AClass>, int> result(std::move(refObj));
|
||||
Result<Ref<AClass>, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, &success);
|
||||
}
|
||||
// Test returning a success Result<T, E>
|
||||
TEST(ResultGeneric, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<std::vector<float>, int> { return {{1.0f}}; };
|
||||
|
||||
// Test returning a success Result<Ref<T>, E>
|
||||
TEST(ResultRefT, ReturningSuccess) {
|
||||
AClass success;
|
||||
auto CreateSuccess = [&success]() -> Result<Ref<AClass>, int> { return Ref<AClass>(&success); };
|
||||
|
||||
Result<Ref<AClass>, int> result = CreateSuccess();
|
||||
TestSuccess(&result, &success);
|
||||
}
|
||||
|
||||
class OtherClass {
|
||||
public:
|
||||
int a = 0;
|
||||
};
|
||||
class Base : public RefCounted {};
|
||||
class Child : public OtherClass, public Base {};
|
||||
|
||||
// Test constructing a Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildConstructor) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
Result<Ref<Base>, int> result(std::move(refChild));
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
// Test copy constructing Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildCopyConstructor) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
||||
Result<Ref<Base>, int> result(std::move(resultChild));
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
// Test assignment operator for Result<Ref<TChild>, E>
|
||||
TEST(ResultRefT, ConversionFromChildAssignmentOperator) {
|
||||
Child child;
|
||||
Ref<Child> refChild(&child);
|
||||
|
||||
Result<Ref<Child>, int> resultChild(std::move(refChild));
|
||||
Result<Ref<Base>, int> result = std::move(resultChild);
|
||||
TestSuccess<Base>(&result, &child);
|
||||
}
|
||||
|
||||
// Result<T, E>
|
||||
|
||||
// Test constructing an error Result<T, E>
|
||||
TEST(ResultGeneric, ConstructingError) {
|
||||
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test moving an error Result<T, E>
|
||||
TEST(ResultGeneric, MovingError) {
|
||||
Result<std::vector<float>, int> result(std::make_unique<int>(dummyError));
|
||||
Result<std::vector<float>, int> movedResult(std::move(result));
|
||||
TestError(&movedResult, dummyError);
|
||||
}
|
||||
|
||||
// Test returning an error Result<T, E>
|
||||
TEST(ResultGeneric, ReturningError) {
|
||||
auto CreateError = []() -> Result<std::vector<float>, int> {
|
||||
return {std::make_unique<int>(dummyError)};
|
||||
};
|
||||
|
||||
Result<std::vector<float>, int> result = CreateError();
|
||||
TestError(&result, dummyError);
|
||||
}
|
||||
|
||||
// Test constructing a success Result<T, E>
|
||||
TEST(ResultGeneric, ConstructingSuccess) {
|
||||
Result<std::vector<float>, int> result({1.0f});
|
||||
TestSuccess(&result, {1.0f});
|
||||
}
|
||||
|
||||
// Test moving a success Result<T, E>
|
||||
TEST(ResultGeneric, MovingSuccess) {
|
||||
Result<std::vector<float>, int> result({1.0f});
|
||||
Result<std::vector<float>, int> movedResult(std::move(result));
|
||||
TestSuccess(&movedResult, {1.0f});
|
||||
}
|
||||
|
||||
// Test returning a success Result<T, E>
|
||||
TEST(ResultGeneric, ReturningSuccess) {
|
||||
auto CreateSuccess = []() -> Result<std::vector<float>, int> { return {{1.0f}}; };
|
||||
|
||||
Result<std::vector<float>, int> result = CreateSuccess();
|
||||
TestSuccess(&result, {1.0f});
|
||||
}
|
||||
Result<std::vector<float>, int> result = CreateSuccess();
|
||||
TestSuccess(&result, {1.0f});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -174,4 +174,4 @@ TEST(RingBufferAllocatorTests, RingBufferOverflow) {
|
||||
ASSERT_EQ(allocator.Allocate(1, serial), 0u);
|
||||
ASSERT_EQ(allocator.Allocate(std::numeric_limits<uint64_t>::max(), serial + 1),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,4 +153,4 @@ TEST(SerialQueue, LastSerial) {
|
||||
|
||||
queue.Enqueue({2}, 1);
|
||||
EXPECT_EQ(queue.LastSerial(), 1u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,21 +21,19 @@
|
||||
|
||||
// Make our own Base - Backend object pair, reusing the CommandBuffer name
|
||||
namespace dawn_native {
|
||||
class CommandBufferBase : public RefCounted {
|
||||
};
|
||||
}
|
||||
class CommandBufferBase : public RefCounted {};
|
||||
} // namespace dawn_native
|
||||
|
||||
using namespace dawn_native;
|
||||
|
||||
class MyCommandBuffer : public CommandBufferBase {
|
||||
};
|
||||
class MyCommandBuffer : public CommandBufferBase {};
|
||||
|
||||
struct MyBackendTraits {
|
||||
using CommandBufferType = MyCommandBuffer;
|
||||
};
|
||||
|
||||
// Instanciate ToBackend for our "backend"
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
auto ToBackend(T&& common) -> decltype(ToBackendBase<MyBackendTraits>(common)) {
|
||||
return ToBackendBase<MyBackendTraits>(common);
|
||||
}
|
||||
@@ -71,7 +69,8 @@ TEST(ToBackend, Ref) {
|
||||
const Ref<CommandBufferBase> base(cmdBuf);
|
||||
|
||||
const auto& backendCmdBuf = ToBackend(base);
|
||||
static_assert(std::is_same<decltype(ToBackend(base)), const Ref<MyCommandBuffer>&>::value, "");
|
||||
static_assert(std::is_same<decltype(ToBackend(base)), const Ref<MyCommandBuffer>&>::value,
|
||||
"");
|
||||
ASSERT_EQ(cmdBuf, backendCmdBuf.Get());
|
||||
|
||||
cmdBuf->Release();
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace {
|
||||
|
||||
// Check that the offset is aligned
|
||||
void ValidateOffset(const TextureCopySplit& copySplit) {
|
||||
ASSERT_TRUE(Align(copySplit.offset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) == copySplit.offset);
|
||||
ASSERT_TRUE(Align(copySplit.offset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
|
||||
copySplit.offset);
|
||||
}
|
||||
|
||||
bool RangesOverlap(uint32_t minA, uint32_t maxA, uint32_t minB, uint32_t maxB) {
|
||||
@@ -68,9 +69,15 @@ namespace {
|
||||
const auto& a = copySplit.copies[i];
|
||||
for (uint32_t j = i + 1; j < copySplit.count; ++j) {
|
||||
const auto& b = copySplit.copies[j];
|
||||
bool overlapX = RangesOverlap(a.textureOffset.x, a.textureOffset.x + a.copySize.width, b.textureOffset.x, b.textureOffset.x + b.copySize.width);
|
||||
bool overlapY = RangesOverlap(a.textureOffset.y, a.textureOffset.y + a.copySize.height, b.textureOffset.y, b.textureOffset.y + b.copySize.height);
|
||||
bool overlapZ = RangesOverlap(a.textureOffset.z, a.textureOffset.z + a.copySize.depth, b.textureOffset.z, b.textureOffset.z + b.copySize.depth);
|
||||
bool overlapX =
|
||||
RangesOverlap(a.textureOffset.x, a.textureOffset.x + a.copySize.width,
|
||||
b.textureOffset.x, b.textureOffset.x + b.copySize.width);
|
||||
bool overlapY =
|
||||
RangesOverlap(a.textureOffset.y, a.textureOffset.y + a.copySize.height,
|
||||
b.textureOffset.y, b.textureOffset.y + b.copySize.height);
|
||||
bool overlapZ =
|
||||
RangesOverlap(a.textureOffset.z, a.textureOffset.z + a.copySize.depth,
|
||||
b.textureOffset.z, b.textureOffset.z + b.copySize.depth);
|
||||
ASSERT_TRUE(!overlapX || !overlapY || !overlapZ);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +112,8 @@ namespace {
|
||||
ASSERT_EQ(maxZ, textureSpec.z + textureSpec.depth);
|
||||
}
|
||||
|
||||
// Validate that the number of pixels copied is exactly equal to the number of pixels in the texture region
|
||||
// Validate that the number of pixels copied is exactly equal to the number of pixels in the
|
||||
// texture region
|
||||
void ValidatePixelCount(const TextureSpec& textureSpec, const TextureCopySplit& copySplit) {
|
||||
uint32_t count = 0;
|
||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||
@@ -116,7 +124,9 @@ namespace {
|
||||
}
|
||||
|
||||
// Check that every buffer offset is at the correct pixel location
|
||||
void ValidateBufferOffset(const TextureSpec& textureSpec, const BufferSpec& bufferSpec, const TextureCopySplit& copySplit) {
|
||||
void ValidateBufferOffset(const TextureSpec& textureSpec,
|
||||
const BufferSpec& bufferSpec,
|
||||
const TextureCopySplit& copySplit) {
|
||||
ASSERT_TRUE(copySplit.count > 0);
|
||||
|
||||
uint32_t texelsPerBlock = textureSpec.blockWidth * textureSpec.blockHeight;
|
||||
@@ -149,7 +159,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateCopySplit(const TextureSpec& textureSpec, const BufferSpec& bufferSpec, const TextureCopySplit& copySplit) {
|
||||
void ValidateCopySplit(const TextureSpec& textureSpec,
|
||||
const BufferSpec& bufferSpec,
|
||||
const TextureCopySplit& copySplit) {
|
||||
ValidateFootprints(copySplit);
|
||||
ValidateOffset(copySplit);
|
||||
ValidateDisjoint(copySplit);
|
||||
@@ -176,8 +188,13 @@ namespace {
|
||||
os << "CopySplit" << std::endl;
|
||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||
const auto& copy = copySplit.copies[i];
|
||||
os << " " << i << ": Texture at (" << copy.textureOffset.x << ", " << copy.textureOffset.y << ", " << copy.textureOffset.z << "), size (" << copy.copySize.width << ", " << copy.copySize.height << ", " << copy.copySize.depth << ")" << std::endl;
|
||||
os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", " << copy.bufferOffset.y << ", " << copy.bufferOffset.z << "), footprint (" << copy.bufferSize.width << ", " << copy.bufferSize.height << ", " << copy.bufferSize.depth << ")" << std::endl;
|
||||
os << " " << i << ": Texture at (" << copy.textureOffset.x << ", "
|
||||
<< copy.textureOffset.y << ", " << copy.textureOffset.z << "), size ("
|
||||
<< copy.copySize.width << ", " << copy.copySize.height << ", " << copy.copySize.depth
|
||||
<< ")" << std::endl;
|
||||
os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", " << copy.bufferOffset.y
|
||||
<< ", " << copy.bufferOffset.z << "), footprint (" << copy.bufferSize.width << ", "
|
||||
<< copy.bufferSize.height << ", " << copy.bufferSize.depth << ")" << std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
@@ -260,42 +277,40 @@ namespace {
|
||||
}
|
||||
|
||||
// Define a list of values to set properties in the spec structs
|
||||
constexpr uint32_t kCheckValues[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, // small values
|
||||
16, 32, 64, 128, 256, 512, 1024, 2048, // powers of 2
|
||||
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
|
||||
17, 33, 65, 129, 257, 513, 1025, 2049
|
||||
};
|
||||
constexpr uint32_t kCheckValues[] = {1, 2, 3, 4, 5, 6, 7, 8, // small values
|
||||
16, 32, 64, 128, 256, 512, 1024, 2048, // powers of 2
|
||||
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
|
||||
17, 33, 65, 129, 257, 513, 1025, 2049};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class CopySplitTest : public testing::Test {
|
||||
protected:
|
||||
TextureCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
|
||||
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
||||
textureSpec.height % textureSpec.blockHeight == 0);
|
||||
dawn_native::Format fakeFormat = {};
|
||||
fakeFormat.blockWidth = textureSpec.blockWidth;
|
||||
fakeFormat.blockHeight = textureSpec.blockHeight;
|
||||
fakeFormat.blockByteSize = textureSpec.texelBlockSizeInBytes;
|
||||
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
||||
{textureSpec.x, textureSpec.y, textureSpec.z},
|
||||
{textureSpec.width, textureSpec.height, textureSpec.depth}, fakeFormat,
|
||||
bufferSpec.offset, bufferSpec.bytesPerRow, bufferSpec.rowsPerImage);
|
||||
ValidateCopySplit(textureSpec, bufferSpec, copySplit);
|
||||
return copySplit;
|
||||
}
|
||||
protected:
|
||||
TextureCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
|
||||
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
||||
textureSpec.height % textureSpec.blockHeight == 0);
|
||||
dawn_native::Format fakeFormat = {};
|
||||
fakeFormat.blockWidth = textureSpec.blockWidth;
|
||||
fakeFormat.blockHeight = textureSpec.blockHeight;
|
||||
fakeFormat.blockByteSize = textureSpec.texelBlockSizeInBytes;
|
||||
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
||||
{textureSpec.x, textureSpec.y, textureSpec.z},
|
||||
{textureSpec.width, textureSpec.height, textureSpec.depth}, fakeFormat,
|
||||
bufferSpec.offset, bufferSpec.bytesPerRow, bufferSpec.rowsPerImage);
|
||||
ValidateCopySplit(textureSpec, bufferSpec, copySplit);
|
||||
return copySplit;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CopySplitTest, General) {
|
||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -310,12 +325,12 @@ TEST_F(CopySplitTest, TextureWidth) {
|
||||
}
|
||||
textureSpec.width = val;
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -331,12 +346,12 @@ TEST_F(CopySplitTest, TextureHeight) {
|
||||
}
|
||||
textureSpec.height = val;
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -349,12 +364,12 @@ TEST_F(CopySplitTest, TextureX) {
|
||||
for (uint32_t val : kCheckValues) {
|
||||
textureSpec.x = val;
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -367,12 +382,12 @@ TEST_F(CopySplitTest, TextureY) {
|
||||
for (uint32_t val : kCheckValues) {
|
||||
textureSpec.y = val;
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -385,12 +400,12 @@ TEST_F(CopySplitTest, TexelSize) {
|
||||
for (uint32_t texelSize : {4, 8, 16, 32, 64}) {
|
||||
textureSpec.texelBlockSizeInBytes = texelSize;
|
||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -407,8 +422,9 @@ TEST_F(CopySplitTest, BufferOffset) {
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
@@ -426,8 +442,9 @@ TEST_F(CopySplitTest, RowPitch) {
|
||||
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
||||
if (HasFatalFailure()) {
|
||||
std::ostringstream message;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
||||
<< copySplit << std::endl;
|
||||
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
||||
<< std::endl
|
||||
<< copySplit << std::endl;
|
||||
FAIL() << message.str();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,16 +121,10 @@ TEST_F(BindGroupValidationTest, BindingSetTwice) {
|
||||
{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::Sampler}});
|
||||
|
||||
// Control case: check that different bindings work
|
||||
utils::MakeBindGroup(device, layout, {
|
||||
{0, mSampler},
|
||||
{1, mSampler}
|
||||
});
|
||||
utils::MakeBindGroup(device, layout, {{0, mSampler}, {1, mSampler}});
|
||||
|
||||
// Check that setting the same binding twice is invalid
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {
|
||||
{0, mSampler},
|
||||
{0, mSampler}
|
||||
}));
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, mSampler}, {0, mSampler}}));
|
||||
}
|
||||
|
||||
// Check that a sampler binding must contain exactly one sampler
|
||||
@@ -406,7 +400,7 @@ TEST_F(BindGroupValidationTest, BufferBindingOOB) {
|
||||
utils::MakeBindGroup(device, layout, {{0, buffer, 0, 256}});
|
||||
|
||||
// Success case, touching the end of the buffer works
|
||||
utils::MakeBindGroup(device, layout, {{0, buffer, 3*256, 256}});
|
||||
utils::MakeBindGroup(device, layout, {{0, buffer, 3 * 256, 256}});
|
||||
|
||||
// Error case, zero size is invalid.
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 1024, 0}}));
|
||||
@@ -419,16 +413,17 @@ TEST_F(BindGroupValidationTest, BufferBindingOOB) {
|
||||
utils::MakeBindGroup(device, layout, {{0, buffer, 256, wgpu::kWholeSize}});
|
||||
|
||||
// Error case, offset is OOB
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 256*5, 0}}));
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 256 * 5, 0}}));
|
||||
|
||||
// Error case, size is OOB
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 0, 256*5}}));
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 0, 256 * 5}}));
|
||||
|
||||
// Error case, offset+size is OOB
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 1024, 256}}));
|
||||
|
||||
// Error case, offset+size overflows to be 0
|
||||
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 256, uint32_t(0) - uint32_t(256)}}));
|
||||
ASSERT_DEVICE_ERROR(
|
||||
utils::MakeBindGroup(device, layout, {{0, buffer, 256, uint32_t(0) - uint32_t(256)}}));
|
||||
}
|
||||
|
||||
// Tests constraints to be sure the uniform buffer binding isn't too large
|
||||
@@ -1191,8 +1186,8 @@ TEST_F(SetBindGroupValidationTest, DynamicOffsetOrder) {
|
||||
|
||||
// Create buffers which are 3x, 2x, and 1x the size of the minimum buffer offset, plus 4 bytes
|
||||
// to spare (to avoid zero-sized bindings). We will offset the bindings so they reach the very
|
||||
// end of the buffer. Any mismatch applying too-large of an offset to a smaller buffer will hit the
|
||||
// out-of-bounds condition during validation.
|
||||
// end of the buffer. Any mismatch applying too-large of an offset to a smaller buffer will hit
|
||||
// the out-of-bounds condition during validation.
|
||||
wgpu::Buffer buffer3x =
|
||||
CreateBuffer(3 * kMinDynamicBufferOffsetAlignment + 4, wgpu::BufferUsage::Storage);
|
||||
wgpu::Buffer buffer2x =
|
||||
@@ -1487,7 +1482,6 @@ class BindGroupLayoutCompatibilityTest : public ValidationTest {
|
||||
wgpu::RenderPipeline CreateFSRenderPipeline(
|
||||
const char* fsShader,
|
||||
std::vector<wgpu::BindGroupLayout> bindGroupLayout) {
|
||||
|
||||
wgpu::ShaderModule vsModule =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
@@ -1520,7 +1514,7 @@ class BindGroupLayoutCompatibilityTest : public ValidationTest {
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
})",
|
||||
std::move(bindGroupLayout));
|
||||
std::move(bindGroupLayout));
|
||||
}
|
||||
|
||||
wgpu::ComputePipeline CreateComputePipeline(
|
||||
@@ -1558,7 +1552,7 @@ class BindGroupLayoutCompatibilityTest : public ValidationTest {
|
||||
} rdst;
|
||||
void main() {
|
||||
})",
|
||||
std::move(bindGroupLayout));
|
||||
std::move(bindGroupLayout));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
using namespace testing;
|
||||
|
||||
class MockBufferMapReadCallback {
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
Call,
|
||||
(WGPUBufferMapAsyncStatus status,
|
||||
const uint32_t* ptr,
|
||||
uint64_t dataLength,
|
||||
void* userdata));
|
||||
public:
|
||||
MOCK_METHOD(void,
|
||||
Call,
|
||||
(WGPUBufferMapAsyncStatus status,
|
||||
const uint32_t* ptr,
|
||||
uint64_t dataLength,
|
||||
void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockBufferMapReadCallback> mockBufferMapReadCallback;
|
||||
@@ -41,11 +41,11 @@ static void ToMockBufferMapReadCallback(WGPUBufferMapAsyncStatus status,
|
||||
}
|
||||
|
||||
class MockBufferMapWriteCallback {
|
||||
public:
|
||||
MOCK_METHOD(
|
||||
void,
|
||||
Call,
|
||||
(WGPUBufferMapAsyncStatus status, uint32_t* ptr, uint64_t dataLength, void* userdata));
|
||||
public:
|
||||
MOCK_METHOD(
|
||||
void,
|
||||
Call,
|
||||
(WGPUBufferMapAsyncStatus status, uint32_t* ptr, uint64_t dataLength, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockBufferMapWriteCallback> mockBufferMapWriteCallback;
|
||||
@@ -59,57 +59,57 @@ static void ToMockBufferMapWriteCallback(WGPUBufferMapAsyncStatus status,
|
||||
}
|
||||
|
||||
class BufferValidationTest : public ValidationTest {
|
||||
protected:
|
||||
wgpu::Buffer CreateMapReadBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::MapRead;
|
||||
protected:
|
||||
wgpu::Buffer CreateMapReadBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::MapRead;
|
||||
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
wgpu::Buffer CreateMapWriteBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::MapWrite;
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
wgpu::Buffer CreateMapWriteBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::MapWrite;
|
||||
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::CreateBufferMappedResult CreateBufferMapped(uint64_t size, wgpu::BufferUsage usage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = usage;
|
||||
wgpu::CreateBufferMappedResult CreateBufferMapped(uint64_t size, wgpu::BufferUsage usage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = usage;
|
||||
|
||||
return device.CreateBufferMapped(&descriptor);
|
||||
}
|
||||
return device.CreateBufferMapped(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = usage;
|
||||
descriptor.mappedAtCreation = true;
|
||||
wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = usage;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
wgpu::Queue queue;
|
||||
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
|
||||
mockBufferMapReadCallback = std::make_unique<MockBufferMapReadCallback>();
|
||||
mockBufferMapWriteCallback = std::make_unique<MockBufferMapWriteCallback>();
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
mockBufferMapReadCallback = std::make_unique<MockBufferMapReadCallback>();
|
||||
mockBufferMapWriteCallback = std::make_unique<MockBufferMapWriteCallback>();
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Delete mocks so that expectations are checked
|
||||
mockBufferMapReadCallback = nullptr;
|
||||
mockBufferMapWriteCallback = nullptr;
|
||||
void TearDown() override {
|
||||
// Delete mocks so that expectations are checked
|
||||
mockBufferMapReadCallback = nullptr;
|
||||
mockBufferMapWriteCallback = nullptr;
|
||||
|
||||
ValidationTest::TearDown();
|
||||
}
|
||||
ValidationTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
// Test case where creation should succeed
|
||||
@@ -416,7 +416,8 @@ TEST_F(BufferValidationTest, UnmapInsideMapWriteCallback) {
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the callback
|
||||
// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
|
||||
// callback
|
||||
TEST_F(BufferValidationTest, DestroyInsideMapReadCallback) {
|
||||
wgpu::Buffer buf = CreateMapReadBuffer(4);
|
||||
|
||||
@@ -429,7 +430,8 @@ TEST_F(BufferValidationTest, DestroyInsideMapReadCallback) {
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the callback
|
||||
// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the
|
||||
// callback
|
||||
TEST_F(BufferValidationTest, DestroyInsideMapWriteCallback) {
|
||||
wgpu::Buffer buf = CreateMapWriteBuffer(4);
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
class CommandBufferValidationTest : public ValidationTest {
|
||||
};
|
||||
class CommandBufferValidationTest : public ValidationTest {};
|
||||
|
||||
// Test for an empty command buffer
|
||||
TEST_F(CommandBufferValidationTest, Empty) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
|
||||
class ComputeValidationTest : public ValidationTest {
|
||||
};
|
||||
class ComputeValidationTest : public ValidationTest {};
|
||||
|
||||
//TODO(cwallez@chromium.org): Add a regression test for Disptach validation trying to acces the input state.
|
||||
// TODO(cwallez@chromium.org): Add a regression test for Disptach validation trying to acces the
|
||||
// input state.
|
||||
|
||||
@@ -1168,8 +1168,8 @@ TEST_F(CopyCommandTest_T2T, 2DTextureDepthStencil) {
|
||||
|
||||
TEST_F(CopyCommandTest_T2T, 2DTextureArrayDepthStencil) {
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture source = Create2DTexture(
|
||||
16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture destination = Create2DTexture(
|
||||
16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
@@ -1179,8 +1179,8 @@ TEST_F(CopyCommandTest_T2T, 2DTextureArrayDepthStencil) {
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture source = Create2DTexture(
|
||||
16, 16, 1, 1, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture destination = Create2DTexture(
|
||||
16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
@@ -1190,8 +1190,8 @@ TEST_F(CopyCommandTest_T2T, 2DTextureArrayDepthStencil) {
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::Texture source = Create2DTexture(16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture source = Create2DTexture(
|
||||
16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopySrc);
|
||||
wgpu::Texture destination = Create2DTexture(
|
||||
16, 16, 1, 3, wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureUsage::CopyDst);
|
||||
|
||||
@@ -1659,4 +1659,4 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, CopyToMultipleArrayLayers) {
|
||||
{0, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +223,7 @@ TEST_F(SetViewportTest, MinDepthEqualOrGreaterThanMaxDepth) {
|
||||
}
|
||||
}
|
||||
|
||||
class SetScissorRectTest : public ValidationTest {
|
||||
};
|
||||
class SetScissorRectTest : public ValidationTest {};
|
||||
|
||||
// Test to check basic use of SetScissor
|
||||
TEST_F(SetScissorRectTest, Success) {
|
||||
@@ -284,8 +283,7 @@ TEST_F(SetScissorRectTest, ScissorLargerThanFramebuffer) {
|
||||
encoder.Finish();
|
||||
}
|
||||
|
||||
class SetBlendColorTest : public ValidationTest {
|
||||
};
|
||||
class SetBlendColorTest : public ValidationTest {};
|
||||
|
||||
// Test to check basic use of SetBlendColor
|
||||
TEST_F(SetBlendColorTest, Success) {
|
||||
@@ -315,8 +313,7 @@ TEST_F(SetBlendColorTest, AnyValueAllowed) {
|
||||
encoder.Finish();
|
||||
}
|
||||
|
||||
class SetStencilReferenceTest : public ValidationTest {
|
||||
};
|
||||
class SetStencilReferenceTest : public ValidationTest {};
|
||||
|
||||
// Test to check basic use of SetStencilReferenceTest
|
||||
TEST_F(SetStencilReferenceTest, Success) {
|
||||
|
||||
@@ -18,181 +18,180 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class QueueSubmitValidationTest : public ValidationTest {
|
||||
};
|
||||
class QueueSubmitValidationTest : public ValidationTest {};
|
||||
|
||||
// Test submitting with a mapped buffer is disallowed
|
||||
TEST_F(QueueSubmitValidationTest, SubmitWithMappedBuffer) {
|
||||
// Create a map-write buffer.
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
|
||||
descriptor.size = 4;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
// Create a fake copy destination buffer
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
wgpu::Buffer targetBuffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
// Create a command buffer that reads from the mappable buffer.
|
||||
wgpu::CommandBuffer commands;
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToBuffer(buffer, 0, targetBuffer, 0, 4);
|
||||
commands = encoder.Finish();
|
||||
}
|
||||
|
||||
wgpu::Queue queue = device.GetDefaultQueue();
|
||||
|
||||
// Submitting when the buffer has never been mapped should succeed
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
// Map the buffer, submitting when the buffer is mapped should fail
|
||||
buffer.MapWriteAsync(nullptr, nullptr);
|
||||
|
||||
// Try submitting before the callback is fired.
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
|
||||
WaitForAllOperations(device);
|
||||
|
||||
// Try submitting after the callback is fired.
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
|
||||
// Unmap the buffer, queue submit should succeed
|
||||
buffer.Unmap();
|
||||
queue.Submit(1, &commands);
|
||||
}
|
||||
|
||||
class QueueWriteBufferValidationTest : public ValidationTest {
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
|
||||
protected:
|
||||
wgpu::Buffer CreateBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
};
|
||||
|
||||
// Test the success case for WriteBuffer
|
||||
TEST_F(QueueWriteBufferValidationTest, Success) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint32_t foo = 0x01020304;
|
||||
queue.WriteBuffer(buf, 0, &foo, sizeof(foo));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer out of bounds
|
||||
TEST_F(QueueWriteBufferValidationTest, OutOfBounds) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint32_t foo[2] = {0, 0};
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, foo, 8));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer out of bounds with an overflow
|
||||
TEST_F(QueueWriteBufferValidationTest, OutOfBoundsOverflow) {
|
||||
wgpu::Buffer buf = CreateBuffer(1024);
|
||||
|
||||
uint32_t foo[2] = {0, 0};
|
||||
|
||||
// An offset that when added to "4" would overflow to be zero and pass validation without
|
||||
// overflow checks.
|
||||
uint64_t offset = uint64_t(int64_t(0) - int64_t(4));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, offset, foo, 4));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer with the wrong usage
|
||||
TEST_F(QueueWriteBufferValidationTest, WrongUsage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::Vertex;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
|
||||
|
||||
uint32_t foo = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &foo, sizeof(foo)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with unaligned size
|
||||
TEST_F(QueueWriteBufferValidationTest, UnalignedSize) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint16_t value = 123;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with unaligned offset
|
||||
TEST_F(QueueWriteBufferValidationTest, UnalignedOffset) {
|
||||
wgpu::Buffer buf = CreateBuffer(8);
|
||||
|
||||
uint32_t value = 0x01020304;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 2, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with destroyed buffer
|
||||
TEST_F(QueueWriteBufferValidationTest, DestroyedBuffer) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
buf.Destroy();
|
||||
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with mapped buffer
|
||||
TEST_F(QueueWriteBufferValidationTest, MappedBuffer) {
|
||||
// CreateBufferMapped
|
||||
{
|
||||
// Test submitting with a mapped buffer is disallowed
|
||||
TEST_F(QueueSubmitValidationTest, SubmitWithMappedBuffer) {
|
||||
// Create a map-write buffer.
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(result.buffer, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// mappedAtCreation
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
descriptor.mappedAtCreation = true;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &value, sizeof(value)));
|
||||
// Create a fake copy destination buffer
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
wgpu::Buffer targetBuffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
// Create a command buffer that reads from the mappable buffer.
|
||||
wgpu::CommandBuffer commands;
|
||||
{
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToBuffer(buffer, 0, targetBuffer, 0, 4);
|
||||
commands = encoder.Finish();
|
||||
}
|
||||
|
||||
wgpu::Queue queue = device.GetDefaultQueue();
|
||||
|
||||
// Submitting when the buffer has never been mapped should succeed
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
// Map the buffer, submitting when the buffer is mapped should fail
|
||||
buffer.MapWriteAsync(nullptr, nullptr);
|
||||
|
||||
// Try submitting before the callback is fired.
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
|
||||
WaitForAllOperations(device);
|
||||
|
||||
// Try submitting after the callback is fired.
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
|
||||
// Unmap the buffer, queue submit should succeed
|
||||
buffer.Unmap();
|
||||
queue.Submit(1, &commands);
|
||||
}
|
||||
|
||||
// MapReadAsync
|
||||
{
|
||||
class QueueWriteBufferValidationTest : public ValidationTest {
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
|
||||
protected:
|
||||
wgpu::Buffer CreateBuffer(uint64_t size) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
};
|
||||
|
||||
// Test the success case for WriteBuffer
|
||||
TEST_F(QueueWriteBufferValidationTest, Success) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint32_t foo = 0x01020304;
|
||||
queue.WriteBuffer(buf, 0, &foo, sizeof(foo));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer out of bounds
|
||||
TEST_F(QueueWriteBufferValidationTest, OutOfBounds) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint32_t foo[2] = {0, 0};
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, foo, 8));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer out of bounds with an overflow
|
||||
TEST_F(QueueWriteBufferValidationTest, OutOfBoundsOverflow) {
|
||||
wgpu::Buffer buf = CreateBuffer(1024);
|
||||
|
||||
uint32_t foo[2] = {0, 0};
|
||||
|
||||
// An offset that when added to "4" would overflow to be zero and pass validation without
|
||||
// overflow checks.
|
||||
uint64_t offset = uint64_t(int64_t(0) - int64_t(4));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, offset, foo, 4));
|
||||
}
|
||||
|
||||
// Test error case for WriteBuffer with the wrong usage
|
||||
TEST_F(QueueWriteBufferValidationTest, WrongUsage) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
|
||||
descriptor.usage = wgpu::BufferUsage::Vertex;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
|
||||
|
||||
buf.MapReadAsync(nullptr, nullptr);
|
||||
uint32_t foo = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &foo, sizeof(foo)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with unaligned size
|
||||
TEST_F(QueueWriteBufferValidationTest, UnalignedSize) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
|
||||
uint16_t value = 123;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with unaligned offset
|
||||
TEST_F(QueueWriteBufferValidationTest, UnalignedOffset) {
|
||||
wgpu::Buffer buf = CreateBuffer(8);
|
||||
|
||||
uint32_t value = 0x01020304;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 2, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// Test WriteBuffer with destroyed buffer
|
||||
TEST_F(QueueWriteBufferValidationTest, DestroyedBuffer) {
|
||||
wgpu::Buffer buf = CreateBuffer(4);
|
||||
buf.Destroy();
|
||||
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// MapWriteAsync
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
|
||||
// Test WriteBuffer with mapped buffer
|
||||
TEST_F(QueueWriteBufferValidationTest, MappedBuffer) {
|
||||
// CreateBufferMapped
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
|
||||
buf.MapWriteAsync(nullptr, nullptr);
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(result.buffer, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// mappedAtCreation
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
descriptor.mappedAtCreation = true;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// MapReadAsync
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
|
||||
|
||||
buf.MapReadAsync(nullptr, nullptr);
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
|
||||
// MapWriteAsync
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
|
||||
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
|
||||
|
||||
buf.MapWriteAsync(nullptr, nullptr);
|
||||
uint32_t value = 0;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buf, 0, &value, sizeof(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -636,4 +636,4 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // anonymous namespace
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,26 +22,26 @@
|
||||
#include <sstream>
|
||||
|
||||
class RenderPipelineValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
|
||||
vsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
vsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
void main() {
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
})");
|
||||
|
||||
fsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
fsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
})");
|
||||
}
|
||||
}
|
||||
|
||||
wgpu::ShaderModule vsModule;
|
||||
wgpu::ShaderModule fsModule;
|
||||
wgpu::ShaderModule vsModule;
|
||||
wgpu::ShaderModule fsModule;
|
||||
};
|
||||
|
||||
// Test cases where creation should succeed
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class ShaderModuleValidationTest : public ValidationTest {
|
||||
};
|
||||
class ShaderModuleValidationTest : public ValidationTest {};
|
||||
|
||||
// Test case with a simpler shader that should successfully be created
|
||||
TEST_F(ShaderModuleValidationTest, CreationSuccess) {
|
||||
@@ -112,8 +111,8 @@ TEST_F(ShaderModuleValidationTest, FragmentOutputLocationExceedsMaxColorAttachme
|
||||
// Test that it is invalid to create a shader module with no chained descriptor. (It must be
|
||||
// WGSL or SPIRV, not empty)
|
||||
TEST_F(ShaderModuleValidationTest, NoChainedDescriptor) {
|
||||
wgpu::ShaderModuleDescriptor desc = {};
|
||||
ASSERT_DEVICE_ERROR(device.CreateShaderModule(&desc));
|
||||
wgpu::ShaderModuleDescriptor desc = {};
|
||||
ASSERT_DEVICE_ERROR(device.CreateShaderModule(&desc));
|
||||
}
|
||||
|
||||
// Test that it is not allowed to use combined texture and sampler.
|
||||
|
||||
@@ -21,474 +21,476 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class TextureValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
class TextureValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
queue = device.GetDefaultQueue();
|
||||
}
|
||||
|
||||
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size.width = kWidth;
|
||||
descriptor.size.height = kHeight;
|
||||
descriptor.size.depth = kDefaultDepth;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
descriptor.sampleCount = kDefaultSampleCount;
|
||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::Sampled;
|
||||
return descriptor;
|
||||
}
|
||||
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size.width = kWidth;
|
||||
descriptor.size.height = kHeight;
|
||||
descriptor.size.depth = kDefaultDepth;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
descriptor.sampleCount = kDefaultSampleCount;
|
||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::Sampled;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
wgpu::Queue queue;
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kWidth = 32;
|
||||
static constexpr uint32_t kHeight = 32;
|
||||
static constexpr uint32_t kDefaultDepth = 1;
|
||||
static constexpr uint32_t kDefaultMipLevels = 1;
|
||||
static constexpr uint32_t kDefaultSampleCount = 1;
|
||||
private:
|
||||
static constexpr uint32_t kWidth = 32;
|
||||
static constexpr uint32_t kHeight = 32;
|
||||
static constexpr uint32_t kDefaultDepth = 1;
|
||||
static constexpr uint32_t kDefaultMipLevels = 1;
|
||||
static constexpr uint32_t kDefaultSampleCount = 1;
|
||||
|
||||
static constexpr wgpu::TextureFormat kDefaultTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||
};
|
||||
|
||||
// Test the validation of sample count
|
||||
TEST_F(TextureValidationTest, SampleCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// sampleCount == 1 is allowed.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// sampleCount == 4 is allowed.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to create a texture with an invalid sampleCount.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 3;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a multisampled texture with mipLevelCount > 1.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.mipLevelCount = 2;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Currently we do not support multisampled 2D array textures.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.size.depth = 2;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to set TextureUsage::Storage when sampleCount > 1.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.usage |= wgpu::TextureUsage::Storage;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of the mip level count
|
||||
TEST_F(TextureValidationTest, MipLevelCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// mipLevelCount == 1 is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// mipLevelCount == 0 is an error
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 0;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Full mip chains are allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
// Mip level sizes: 32, 16, 8, 4, 2, 1
|
||||
descriptor.mipLevelCount = 6;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Too big mip chains on width are disallowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 31;
|
||||
descriptor.size.height = 32;
|
||||
// Mip level width: 31, 15, 7, 3, 1, 1
|
||||
descriptor.mipLevelCount = 7;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Too big mip chains on height are disallowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 31;
|
||||
// Mip level height: 31, 15, 7, 3, 1, 1
|
||||
descriptor.mipLevelCount = 7;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Undefined shift check if miplevel is bigger than the integer bit width.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 100;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Non square mip map halves the resolution until a 1x1 dimension.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 8;
|
||||
// Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1
|
||||
descriptor.mipLevelCount = 6;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Mip level exceeding kMaxTexture2DMipLevels not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 1 >> kMaxTexture2DMipLevels;
|
||||
descriptor.size.height = 1 >> kMaxTexture2DMipLevels;
|
||||
descriptor.mipLevelCount = kMaxTexture2DMipLevels + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
// Test the validation of array layer count
|
||||
TEST_F(TextureValidationTest, ArrayLayerCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// Array layer count exceeding kMaxTexture2DArrayLayers is not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Array layer count less than kMaxTexture2DArrayLayers is allowed;
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers >> 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Array layer count equal to kMaxTexture2DArrayLayers is allowed;
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of texture size
|
||||
TEST_F(TextureValidationTest, TextureSize) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// Texture size exceeding kMaxTextureSize is not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize + 1u;
|
||||
descriptor.size.height = kMaxTextureSize + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Texture size less than kMaxTextureSize is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize >> 1;
|
||||
descriptor.size.height = kMaxTextureSize >> 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Texture equal to kMaxTextureSize is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize;
|
||||
descriptor.size.height = kMaxTextureSize;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that it is valid to destroy a texture
|
||||
TEST_F(TextureValidationTest, DestroyTexture) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
texture.Destroy();
|
||||
}
|
||||
|
||||
// Test that it's valid to destroy a destroyed texture
|
||||
TEST_F(TextureValidationTest, DestroyDestroyedTexture) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
texture.Destroy();
|
||||
texture.Destroy();
|
||||
}
|
||||
|
||||
// Test that it's invalid to submit a destroyed texture in a queue
|
||||
// in the case of destroy, encode, submit
|
||||
TEST_F(TextureValidationTest, DestroyEncodeSubmit) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
wgpu::TextureView textureView = texture.CreateView();
|
||||
|
||||
utils::ComboRenderPassDescriptor renderPass({textureView});
|
||||
|
||||
// Destroy the texture
|
||||
texture.Destroy();
|
||||
|
||||
wgpu::CommandEncoder encoder_post_destroy = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder_post_destroy.BeginRenderPass(&renderPass);
|
||||
pass.EndPass();
|
||||
}
|
||||
wgpu::CommandBuffer commands = encoder_post_destroy.Finish();
|
||||
|
||||
// Submit should fail due to destroyed texture
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
}
|
||||
|
||||
// Test that it's invalid to submit a destroyed texture in a queue
|
||||
// in the case of encode, destroy, submit
|
||||
TEST_F(TextureValidationTest, EncodeDestroySubmit) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
wgpu::TextureView textureView = texture.CreateView();
|
||||
|
||||
utils::ComboRenderPassDescriptor renderPass({textureView});
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.EndPass();
|
||||
}
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
|
||||
// Destroy the texture
|
||||
texture.Destroy();
|
||||
|
||||
// Submit should fail due to destroyed texture
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
}
|
||||
|
||||
// Test it is an error to create an OutputAttachment texture with a non-renderable format.
|
||||
TEST_F(TextureValidationTest, NonRenderableAndOutputAttachment) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment;
|
||||
|
||||
// Succeeds because RGBA8Unorm is renderable
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
device.CreateTexture(&descriptor);
|
||||
|
||||
wgpu::TextureFormat nonRenderableFormats[] = {
|
||||
wgpu::TextureFormat::RG11B10Float,
|
||||
wgpu::TextureFormat::R8Snorm,
|
||||
wgpu::TextureFormat::RG8Snorm,
|
||||
wgpu::TextureFormat::RGBA8Snorm,
|
||||
static constexpr wgpu::TextureFormat kDefaultTextureFormat =
|
||||
wgpu::TextureFormat::RGBA8Unorm;
|
||||
};
|
||||
|
||||
for (wgpu::TextureFormat format : nonRenderableFormats) {
|
||||
// Fails because `format` is non-renderable
|
||||
descriptor.format = format;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
// Test the validation of sample count
|
||||
TEST_F(TextureValidationTest, SampleCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// Test it is an error to create a Storage texture with any format that doesn't support
|
||||
// TextureUsage::Storage texture usages.
|
||||
TEST_F(TextureValidationTest, TextureFormatNotSupportTextureUsageStorage) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.usage = wgpu::TextureUsage::Storage;
|
||||
|
||||
for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
|
||||
descriptor.format = format;
|
||||
if (utils::TextureFormatSupportsStorageTexture(format)) {
|
||||
device.CreateTexture(&descriptor);
|
||||
} else {
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test it is an error to create a texture with format "Undefined".
|
||||
TEST_F(TextureValidationTest, TextureFormatUndefined) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with
|
||||
// compressed texture formats.
|
||||
class CompressedTextureFormatsValidationTests : public TextureValidationTest {
|
||||
public:
|
||||
CompressedTextureFormatsValidationTests() : TextureValidationTest() {
|
||||
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"});
|
||||
}
|
||||
|
||||
protected:
|
||||
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
|
||||
wgpu::TextureDescriptor descriptor =
|
||||
TextureValidationTest::CreateDefaultTextureDescriptor();
|
||||
descriptor.usage =
|
||||
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
const std::array<wgpu::TextureFormat, 14> kBCFormats = {
|
||||
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
|
||||
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
|
||||
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBSfloat,
|
||||
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
|
||||
};
|
||||
|
||||
// Test the validation of texture size when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
|
||||
// Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
|
||||
// width and height of all BC formats) as the width or height of textures in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
// sampleCount == 1 is allowed.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// sampleCount == 4 is allowed.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.width = 31;
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to create a texture with an invalid sampleCount.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 3;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a multisampled texture with mipLevelCount > 1.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.height = 31;
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.mipLevelCount = 2;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Currently we do not support multisampled 2D array textures.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.width = 12;
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.size.depth = 2;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to set TextureUsage::Storage when sampleCount > 1.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.usage |= wgpu::TextureUsage::Storage;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of the mip level count
|
||||
TEST_F(TextureValidationTest, MipLevelCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// mipLevelCount == 1 is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// mipLevelCount == 0 is an error
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 0;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Full mip chains are allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
// Mip level sizes: 32, 16, 8, 4, 2, 1
|
||||
descriptor.mipLevelCount = 6;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Too big mip chains on width are disallowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 31;
|
||||
descriptor.size.height = 32;
|
||||
// Mip level width: 31, 15, 7, 3, 1, 1
|
||||
descriptor.mipLevelCount = 7;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Too big mip chains on height are disallowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 31;
|
||||
// Mip level height: 31, 15, 7, 3, 1, 1
|
||||
descriptor.mipLevelCount = 7;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Undefined shift check if miplevel is bigger than the integer bit width.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 32;
|
||||
descriptor.mipLevelCount = 100;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Non square mip map halves the resolution until a 1x1 dimension.
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 32;
|
||||
descriptor.size.height = 8;
|
||||
// Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1
|
||||
descriptor.mipLevelCount = 6;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Mip level exceeding kMaxTexture2DMipLevels not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = 1 >> kMaxTexture2DMipLevels;
|
||||
descriptor.size.height = 1 >> kMaxTexture2DMipLevels;
|
||||
descriptor.mipLevelCount = kMaxTexture2DMipLevels + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
// Test the validation of array layer count
|
||||
TEST_F(TextureValidationTest, ArrayLayerCount) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// Array layer count exceeding kMaxTexture2DArrayLayers is not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Array layer count less than kMaxTexture2DArrayLayers is allowed;
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers >> 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Array layer count equal to kMaxTexture2DArrayLayers is allowed;
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.depth = kMaxTexture2DArrayLayers;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the creation of a texture with BC format will fail when the extension textureCompressionBC
|
||||
// is not enabled.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, UseBCFormatWithoutEnablingExtension) {
|
||||
const std::vector<const char*> kEmptyVector;
|
||||
wgpu::Device deviceWithoutExtension = CreateDeviceFromAdapter(adapter, kEmptyVector);
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
ASSERT_DEVICE_ERROR(deviceWithoutExtension.CreateTexture(&descriptor));
|
||||
// Test the validation of texture size
|
||||
TEST_F(TextureValidationTest, TextureSize) {
|
||||
wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
|
||||
|
||||
// Texture size exceeding kMaxTextureSize is not allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize + 1u;
|
||||
descriptor.size.height = kMaxTextureSize + 1u;
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
// Texture size less than kMaxTextureSize is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize >> 1;
|
||||
descriptor.size.height = kMaxTextureSize >> 1;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// Texture equal to kMaxTextureSize is allowed
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = defaultDescriptor;
|
||||
descriptor.size.width = kMaxTextureSize;
|
||||
descriptor.size.height = kMaxTextureSize;
|
||||
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of texture usages when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
|
||||
// Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the
|
||||
// textures in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
// Test that it is valid to destroy a texture
|
||||
TEST_F(TextureValidationTest, DestroyTexture) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
texture.Destroy();
|
||||
}
|
||||
|
||||
// Test that it's valid to destroy a destroyed texture
|
||||
TEST_F(TextureValidationTest, DestroyDestroyedTexture) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
texture.Destroy();
|
||||
texture.Destroy();
|
||||
}
|
||||
|
||||
// Test that it's invalid to submit a destroyed texture in a queue
|
||||
// in the case of destroy, encode, submit
|
||||
TEST_F(TextureValidationTest, DestroyEncodeSubmit) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
wgpu::TextureView textureView = texture.CreateView();
|
||||
|
||||
utils::ComboRenderPassDescriptor renderPass({textureView});
|
||||
|
||||
// Destroy the texture
|
||||
texture.Destroy();
|
||||
|
||||
wgpu::CommandEncoder encoder_post_destroy = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
wgpu::RenderPassEncoder pass = encoder_post_destroy.BeginRenderPass(&renderPass);
|
||||
pass.EndPass();
|
||||
}
|
||||
wgpu::CommandBuffer commands = encoder_post_destroy.Finish();
|
||||
|
||||
// Submit should fail due to destroyed texture
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
}
|
||||
|
||||
// Test that it's invalid to submit a destroyed texture in a queue
|
||||
// in the case of encode, destroy, submit
|
||||
TEST_F(TextureValidationTest, EncodeDestroySubmit) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
wgpu::TextureView textureView = texture.CreateView();
|
||||
|
||||
utils::ComboRenderPassDescriptor renderPass({textureView});
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::Storage;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.EndPass();
|
||||
}
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
// Destroy the texture
|
||||
texture.Destroy();
|
||||
|
||||
// Submit should fail due to destroyed texture
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||
}
|
||||
|
||||
// Test it is an error to create an OutputAttachment texture with a non-renderable format.
|
||||
TEST_F(TextureValidationTest, NonRenderableAndOutputAttachment) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment;
|
||||
|
||||
// Succeeds because RGBA8Unorm is renderable
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
device.CreateTexture(&descriptor);
|
||||
|
||||
wgpu::TextureFormat nonRenderableFormats[] = {
|
||||
wgpu::TextureFormat::RG11B10Float,
|
||||
wgpu::TextureFormat::R8Snorm,
|
||||
wgpu::TextureFormat::RG8Snorm,
|
||||
wgpu::TextureFormat::RGBA8Snorm,
|
||||
};
|
||||
|
||||
for (wgpu::TextureFormat format : nonRenderableFormats) {
|
||||
// Fails because `format` is non-renderable
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::Present;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of sample count when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
|
||||
// Test that it is invalid to specify SampleCount > 1 when we create a texture in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
// Test it is an error to create a Storage texture with any format that doesn't support
|
||||
// TextureUsage::Storage texture usages.
|
||||
TEST_F(TextureValidationTest, TextureFormatNotSupportTextureUsageStorage) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.usage = wgpu::TextureUsage::Storage;
|
||||
|
||||
for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
|
||||
descriptor.format = format;
|
||||
if (utils::TextureFormatSupportsStorageTexture(format)) {
|
||||
device.CreateTexture(&descriptor);
|
||||
} else {
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test it is an error to create a texture with format "Undefined".
|
||||
TEST_F(TextureValidationTest, TextureFormatUndefined) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.sampleCount = 4;
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of creating 2D array textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
|
||||
// Test that it is allowed to create a 2D array texture in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.depth = 6;
|
||||
device.CreateTexture(&descriptor);
|
||||
// TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with
|
||||
// compressed texture formats.
|
||||
class CompressedTextureFormatsValidationTests : public TextureValidationTest {
|
||||
public:
|
||||
CompressedTextureFormatsValidationTests() : TextureValidationTest() {
|
||||
device = CreateDeviceFromAdapter(adapter, {"texture_compression_bc"});
|
||||
}
|
||||
|
||||
protected:
|
||||
wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
|
||||
wgpu::TextureDescriptor descriptor =
|
||||
TextureValidationTest::CreateDefaultTextureDescriptor();
|
||||
descriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
||||
wgpu::TextureUsage::Sampled;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
const std::array<wgpu::TextureFormat, 14> kBCFormats = {
|
||||
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
|
||||
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
|
||||
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
|
||||
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBSfloat,
|
||||
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
|
||||
};
|
||||
|
||||
// Test the validation of texture size when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
|
||||
// Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
|
||||
// width and height of all BC formats) as the width or height of textures in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.width = 31;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.height = 31;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.width = 12;
|
||||
descriptor.size.height = 32;
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the creation of a texture with BC format will fail when the extension
|
||||
// textureCompressionBC is not enabled.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, UseBCFormatWithoutEnablingExtension) {
|
||||
const std::vector<const char*> kEmptyVector;
|
||||
wgpu::Device deviceWithoutExtension = CreateDeviceFromAdapter(adapter, kEmptyVector);
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
ASSERT_DEVICE_ERROR(deviceWithoutExtension.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of texture usages when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
|
||||
// Test that only CopySrc, CopyDst and Sampled are accepted as the texture usage of the
|
||||
// textures in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::OutputAttachment;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::Storage;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
|
||||
{
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::Present;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of sample count when creating textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
|
||||
// Test that it is invalid to specify SampleCount > 1 when we create a texture in BC
|
||||
// formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.sampleCount = 4;
|
||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the validation of creating 2D array textures in compressed texture formats.
|
||||
TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
|
||||
// Test that it is allowed to create a 2D array texture in BC formats.
|
||||
for (wgpu::TextureFormat format : kBCFormats) {
|
||||
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
|
||||
descriptor.format = format;
|
||||
descriptor.size.depth = 6;
|
||||
device.CreateTexture(&descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -16,349 +16,348 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class TextureViewValidationTest : public ValidationTest {
|
||||
};
|
||||
class TextureViewValidationTest : public ValidationTest {};
|
||||
|
||||
constexpr uint32_t kWidth = 32u;
|
||||
constexpr uint32_t kHeight = 32u;
|
||||
constexpr uint32_t kDefaultMipLevels = 6u;
|
||||
constexpr uint32_t kWidth = 32u;
|
||||
constexpr uint32_t kHeight = 32u;
|
||||
constexpr uint32_t kDefaultMipLevels = 6u;
|
||||
|
||||
constexpr wgpu::TextureFormat kDefaultTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||
constexpr wgpu::TextureFormat kDefaultTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||
|
||||
wgpu::Texture Create2DArrayTexture(wgpu::Device& device,
|
||||
uint32_t arrayLayerCount,
|
||||
uint32_t width = kWidth,
|
||||
uint32_t height = kHeight,
|
||||
uint32_t mipLevelCount = kDefaultMipLevels,
|
||||
uint32_t sampleCount = 1) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
descriptor.size.width = width;
|
||||
descriptor.size.height = height;
|
||||
descriptor.size.depth = arrayLayerCount;
|
||||
descriptor.sampleCount = sampleCount;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.mipLevelCount = mipLevelCount;
|
||||
descriptor.usage = wgpu::TextureUsage::Sampled;
|
||||
return device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::TextureViewDescriptor CreateDefaultViewDescriptor(wgpu::TextureViewDimension dimension) {
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.dimension = dimension;
|
||||
descriptor.baseMipLevel = 0;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
descriptor.baseArrayLayer = 0;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// Test creating texture view on a 2D non-array texture
|
||||
TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2D) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
|
||||
// It is OK to create a 2D texture view on a 2D texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
wgpu::Texture Create2DArrayTexture(wgpu::Device& device,
|
||||
uint32_t arrayLayerCount,
|
||||
uint32_t width = kWidth,
|
||||
uint32_t height = kHeight,
|
||||
uint32_t mipLevelCount = kDefaultMipLevels,
|
||||
uint32_t sampleCount = 1) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||
descriptor.size.width = width;
|
||||
descriptor.size.height = height;
|
||||
descriptor.size.depth = arrayLayerCount;
|
||||
descriptor.sampleCount = sampleCount;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.mipLevelCount = mipLevelCount;
|
||||
descriptor.usage = wgpu::TextureUsage::Sampled;
|
||||
return device.CreateTexture(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to view a layer past the end of the texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is OK to create a 1-layer 2D array texture view on a 2D texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// baseMipLevel == k && mipLevelCount == 0 means to use levels k..end.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.mipLevelCount = 0;
|
||||
|
||||
wgpu::TextureViewDescriptor CreateDefaultViewDescriptor(wgpu::TextureViewDimension dimension) {
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = kDefaultTextureFormat;
|
||||
descriptor.dimension = dimension;
|
||||
descriptor.baseMipLevel = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = kDefaultMipLevels - 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = kDefaultMipLevels;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to make the mip level out of range.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.baseMipLevel = 0;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels + 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = 1;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = kDefaultMipLevels - 1;
|
||||
descriptor.mipLevelCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = kDefaultMipLevels;
|
||||
descriptor.mipLevelCount = 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test creating texture view on a 2D array texture
|
||||
TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2DArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 6;
|
||||
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray);
|
||||
|
||||
// It is OK to create a 2D texture view on a 2D array texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// It is OK to create a 2D array texture view on a 2D array texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// baseArrayLayer == k && arrayLayerCount == 0 means to use layers k..end.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 0;
|
||||
|
||||
descriptor.baseArrayLayer = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers - 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error for the array layer range of the view to exceed that of the texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.baseArrayLayer = 0;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers + 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = 1;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers - 1;
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Using the "none" ("default") values validates the same as explicitly
|
||||
// specifying the values they're supposed to default to.
|
||||
// Variant for a texture with more than 1 array layer.
|
||||
TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaultsArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 6;
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
{ texture.CreateView(); }
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
|
||||
// Setting array layers to non-0 means the dimensionality will
|
||||
// default to 2D so by itself it causes an error.
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Using the "none" ("default") values validates the same as explicitly
|
||||
// specifying the values they're supposed to default to.
|
||||
// Variant for a texture with only 1 array layer.
|
||||
TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaultsNonArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 1;
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
{ texture.CreateView(); }
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.arrayLayerCount = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Test creating cube map texture view
|
||||
TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 16;
|
||||
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray);
|
||||
|
||||
// It is OK to create a cube map texture view with arrayLayerCount == 6.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 6;
|
||||
texture.CreateView(&descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// It is an error to create a cube map texture view with arrayLayerCount != 6.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 3;
|
||||
// Test creating texture view on a 2D non-array texture
|
||||
TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2D) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
|
||||
// It is OK to create a 2D texture view on a 2D texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to view a layer past the end of the texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is OK to create a 1-layer 2D array texture view on a 2D texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// baseMipLevel == k && mipLevelCount == 0 means to use levels k..end.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.mipLevelCount = 0;
|
||||
|
||||
descriptor.baseMipLevel = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = kDefaultMipLevels - 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseMipLevel = kDefaultMipLevels;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to make the mip level out of range.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.baseMipLevel = 0;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels + 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = 1;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = kDefaultMipLevels - 1;
|
||||
descriptor.mipLevelCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseMipLevel = kDefaultMipLevels;
|
||||
descriptor.mipLevelCount = 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test creating texture view on a 2D array texture
|
||||
TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2DArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 6;
|
||||
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray);
|
||||
|
||||
// It is OK to create a 2D texture view on a 2D array texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// It is OK to create a 2D array texture view on a 2D array texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// baseArrayLayer == k && arrayLayerCount == 0 means to use layers k..end.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.arrayLayerCount = 0;
|
||||
|
||||
descriptor.baseArrayLayer = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers - 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error for the array layer range of the view to exceed that of the texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.baseArrayLayer = 0;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers + 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = 1;
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers - 1;
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.baseArrayLayer = kDefaultArrayLayers;
|
||||
descriptor.arrayLayerCount = 1;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Using the "none" ("default") values validates the same as explicitly
|
||||
// specifying the values they're supposed to default to.
|
||||
// Variant for a texture with more than 1 array layer.
|
||||
TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaultsArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 6;
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
{ texture.CreateView(); }
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
|
||||
// Setting array layers to non-0 means the dimensionality will
|
||||
// default to 2D so by itself it causes an error.
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Using the "none" ("default") values validates the same as explicitly
|
||||
// specifying the values they're supposed to default to.
|
||||
// Variant for a texture with only 1 array layer.
|
||||
TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaultsNonArray) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 1;
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
{ texture.CreateView(); }
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Undefined;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2D;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.dimension = wgpu::TextureViewDimension::e2DArray;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.arrayLayerCount = 0;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = 1;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = 2;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor;
|
||||
descriptor.mipLevelCount = kDefaultMipLevels;
|
||||
texture.CreateView(&descriptor);
|
||||
descriptor.arrayLayerCount = kDefaultArrayLayers;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Test creating cube map texture view
|
||||
TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) {
|
||||
constexpr uint32_t kDefaultArrayLayers = 16;
|
||||
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray);
|
||||
|
||||
// It is OK to create a cube map texture view with arrayLayerCount == 6.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 6;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to create a cube map texture view with arrayLayerCount != 6.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 3;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is OK to create a cube map array texture view with arrayLayerCount % 6 == 0.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 12;
|
||||
texture.CreateView(&descriptor);
|
||||
}
|
||||
|
||||
// It is an error to create a cube map array texture view with arrayLayerCount % 6 != 0.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 11;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a cube map texture view with width != height.
|
||||
{
|
||||
wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5);
|
||||
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 6;
|
||||
ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a cube map array texture view with width != height.
|
||||
{
|
||||
wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5);
|
||||
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 12;
|
||||
ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the format compatibility rules when creating a texture view.
|
||||
// TODO(jiawei.shao@intel.com): add more tests when the rules are fully implemented.
|
||||
TEST_F(TextureViewValidationTest, TextureViewFormatCompatibility) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
|
||||
// It is an error to create a texture view in depth-stencil format on a RGBA texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that it's invalid to create a texture view from a destroyed texture
|
||||
TEST_F(TextureViewValidationTest, DestroyCreateTextureView) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
wgpu::TextureViewDescriptor descriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
texture.Destroy();
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is OK to create a cube map array texture view with arrayLayerCount % 6 == 0.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 12;
|
||||
texture.CreateView(&descriptor);
|
||||
// Test that only TextureAspect::All is supported
|
||||
TEST_F(TextureViewValidationTest, AspectMustBeAll) {
|
||||
wgpu::TextureDescriptor descriptor = {};
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.format = wgpu::TextureFormat::Depth32Float;
|
||||
descriptor.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment;
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
wgpu::TextureViewDescriptor viewDescriptor = {};
|
||||
viewDescriptor.aspect = wgpu::TextureAspect::All;
|
||||
texture.CreateView(&viewDescriptor);
|
||||
|
||||
viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDescriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a cube map array texture view with arrayLayerCount % 6 != 0.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 11;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a cube map texture view with width != height.
|
||||
{
|
||||
wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5);
|
||||
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::Cube;
|
||||
descriptor.arrayLayerCount = 6;
|
||||
ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// It is an error to create a cube map array texture view with width != height.
|
||||
{
|
||||
wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5);
|
||||
|
||||
wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
|
||||
descriptor.dimension = wgpu::TextureViewDimension::CubeArray;
|
||||
descriptor.arrayLayerCount = 12;
|
||||
ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test the format compatibility rules when creating a texture view.
|
||||
// TODO(jiawei.shao@intel.com): add more tests when the rules are fully implemented.
|
||||
TEST_F(TextureViewValidationTest, TextureViewFormatCompatibility) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
|
||||
wgpu::TextureViewDescriptor base2DTextureViewDescriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
|
||||
// It is an error to create a texture view in depth-stencil format on a RGBA texture.
|
||||
{
|
||||
wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
|
||||
descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that it's invalid to create a texture view from a destroyed texture
|
||||
TEST_F(TextureViewValidationTest, DestroyCreateTextureView) {
|
||||
wgpu::Texture texture = Create2DArrayTexture(device, 1);
|
||||
wgpu::TextureViewDescriptor descriptor =
|
||||
CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D);
|
||||
texture.Destroy();
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
|
||||
}
|
||||
|
||||
// Test that only TextureAspect::All is supported
|
||||
TEST_F(TextureViewValidationTest, AspectMustBeAll) {
|
||||
wgpu::TextureDescriptor descriptor = {};
|
||||
descriptor.size = {1, 1, 1};
|
||||
descriptor.format = wgpu::TextureFormat::Depth32Float;
|
||||
descriptor.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::OutputAttachment;
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
wgpu::TextureViewDescriptor viewDescriptor = {};
|
||||
viewDescriptor.aspect = wgpu::TextureAspect::All;
|
||||
texture.CreateView(&viewDescriptor);
|
||||
|
||||
viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly;
|
||||
ASSERT_DEVICE_ERROR(texture.CreateView(&viewDescriptor));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -16,34 +16,67 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class ToggleValidationTest : public ValidationTest {
|
||||
};
|
||||
class ToggleValidationTest : public ValidationTest {};
|
||||
|
||||
// Tests querying the detail of a toggle from dawn_native::InstanceBase works correctly.
|
||||
TEST_F(ToggleValidationTest, QueryToggleInfo) {
|
||||
// Query with a valid toggle name
|
||||
{
|
||||
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kValidToggleName);
|
||||
ASSERT_NE(nullptr, toggleInfo);
|
||||
ASSERT_NE(nullptr, toggleInfo->name);
|
||||
ASSERT_NE(nullptr, toggleInfo->description);
|
||||
ASSERT_NE(nullptr, toggleInfo->url);
|
||||
// Tests querying the detail of a toggle from dawn_native::InstanceBase works correctly.
|
||||
TEST_F(ToggleValidationTest, QueryToggleInfo) {
|
||||
// Query with a valid toggle name
|
||||
{
|
||||
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kValidToggleName);
|
||||
ASSERT_NE(nullptr, toggleInfo);
|
||||
ASSERT_NE(nullptr, toggleInfo->name);
|
||||
ASSERT_NE(nullptr, toggleInfo->description);
|
||||
ASSERT_NE(nullptr, toggleInfo->url);
|
||||
}
|
||||
|
||||
// Query with an invalid toggle name
|
||||
{
|
||||
const char* kInvalidToggleName = "!@#$%^&*";
|
||||
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kInvalidToggleName);
|
||||
ASSERT_EQ(nullptr, toggleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Query with an invalid toggle name
|
||||
{
|
||||
const char* kInvalidToggleName = "!@#$%^&*";
|
||||
const dawn_native::ToggleInfo* toggleInfo = instance->GetToggleInfo(kInvalidToggleName);
|
||||
ASSERT_EQ(nullptr, toggleInfo);
|
||||
}
|
||||
}
|
||||
// Tests overriding toggles when creating a device works correctly.
|
||||
TEST_F(ToggleValidationTest, OverrideToggleUsage) {
|
||||
// Create device with a valid name of a toggle
|
||||
{
|
||||
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||
dawn_native::DeviceDescriptor descriptor;
|
||||
descriptor.forceEnabledToggles.push_back(kValidToggleName);
|
||||
|
||||
// Tests overriding toggles when creating a device works correctly.
|
||||
TEST_F(ToggleValidationTest, OverrideToggleUsage) {
|
||||
// Create device with a valid name of a toggle
|
||||
{
|
||||
const char* kValidToggleName = "emulate_store_and_msaa_resolve";
|
||||
WGPUDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||
bool validToggleExists = false;
|
||||
for (const char* toggle : toggleNames) {
|
||||
if (strcmp(toggle, kValidToggleName) == 0) {
|
||||
validToggleExists = true;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(validToggleExists, true);
|
||||
}
|
||||
|
||||
// Create device with an invalid toggle name
|
||||
{
|
||||
const char* kInvalidToggleName = "!@#$%^&*";
|
||||
dawn_native::DeviceDescriptor descriptor;
|
||||
descriptor.forceEnabledToggles.push_back(kInvalidToggleName);
|
||||
|
||||
WGPUDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||
bool InvalidToggleExists = false;
|
||||
for (const char* toggle : toggleNames) {
|
||||
if (strcmp(toggle, kInvalidToggleName) == 0) {
|
||||
InvalidToggleExists = true;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(InvalidToggleExists, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ToggleValidationTest, TurnOffVsyncWithToggle) {
|
||||
const char* kValidToggleName = "turn_off_vsync";
|
||||
dawn_native::DeviceDescriptor descriptor;
|
||||
descriptor.forceEnabledToggles.push_back(kValidToggleName);
|
||||
|
||||
@@ -57,38 +90,4 @@ TEST_F(ToggleValidationTest, OverrideToggleUsage) {
|
||||
}
|
||||
ASSERT_EQ(validToggleExists, true);
|
||||
}
|
||||
|
||||
// Create device with an invalid toggle name
|
||||
{
|
||||
const char* kInvalidToggleName = "!@#$%^&*";
|
||||
dawn_native::DeviceDescriptor descriptor;
|
||||
descriptor.forceEnabledToggles.push_back(kInvalidToggleName);
|
||||
|
||||
WGPUDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||
bool InvalidToggleExists = false;
|
||||
for (const char* toggle : toggleNames) {
|
||||
if (strcmp(toggle, kInvalidToggleName) == 0) {
|
||||
InvalidToggleExists = true;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(InvalidToggleExists, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ToggleValidationTest, TurnOffVsyncWithToggle) {
|
||||
const char* kValidToggleName = "turn_off_vsync";
|
||||
dawn_native::DeviceDescriptor descriptor;
|
||||
descriptor.forceEnabledToggles.push_back(kValidToggleName);
|
||||
|
||||
WGPUDevice deviceWithToggle = adapter.CreateDevice(&descriptor);
|
||||
std::vector<const char*> toggleNames = dawn_native::GetTogglesUsed(deviceWithToggle);
|
||||
bool validToggleExists = false;
|
||||
for (const char* toggle : toggleNames) {
|
||||
if (strcmp(toggle, kValidToggleName) == 0) {
|
||||
validToggleExists = true;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(validToggleExists, true);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -27,7 +27,7 @@ ValidationTest::ValidationTest() {
|
||||
|
||||
// Validation tests run against the null backend, find the corresponding adapter
|
||||
bool foundNullAdapter = false;
|
||||
for (auto ¤tAdapter : adapters) {
|
||||
for (auto& currentAdapter : adapters) {
|
||||
wgpu::AdapterProperties adapterProperties;
|
||||
currentAdapter.GetProperties(&adapterProperties);
|
||||
|
||||
@@ -129,7 +129,7 @@ ValidationTest::DummyRenderPass::DummyRenderPass(const wgpu::Device& device)
|
||||
wgpu::TextureView view = attachment.CreateView();
|
||||
mColorAttachment.attachment = view;
|
||||
mColorAttachment.resolveTarget = nullptr;
|
||||
mColorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
mColorAttachment.clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
mColorAttachment.loadOp = wgpu::LoadOp::Clear;
|
||||
mColorAttachment.storeOp = wgpu::StoreOp::Store;
|
||||
|
||||
|
||||
@@ -70,4 +70,4 @@ class ValidationTest : public testing::Test {
|
||||
bool mError = false;
|
||||
};
|
||||
|
||||
#endif // TESTS_UNITTESTS_VALIDATIONTEST_H_
|
||||
#endif // TESTS_UNITTESTS_VALIDATIONTEST_H_
|
||||
|
||||
@@ -21,68 +21,68 @@
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
class VertexBufferValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
|
||||
fsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
fsModule = utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
|
||||
#version 450
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
})");
|
||||
}
|
||||
|
||||
wgpu::Buffer MakeVertexBuffer() {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 256;
|
||||
descriptor.usage = wgpu::BufferUsage::Vertex;
|
||||
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::ShaderModule MakeVertexShader(unsigned int bufferCount) {
|
||||
std::ostringstream vs;
|
||||
vs << "#version 450\n";
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
vs << "layout(location = " << i << ") in vec3 a_position" << i << ";\n";
|
||||
}
|
||||
vs << "void main() {\n";
|
||||
|
||||
wgpu::Buffer MakeVertexBuffer() {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 256;
|
||||
descriptor.usage = wgpu::BufferUsage::Vertex;
|
||||
|
||||
return device.CreateBuffer(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::ShaderModule MakeVertexShader(unsigned int bufferCount) {
|
||||
std::ostringstream vs;
|
||||
vs << "#version 450\n";
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
vs << "layout(location = " << i << ") in vec3 a_position" << i << ";\n";
|
||||
vs << "gl_Position = vec4(";
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
vs << "a_position" << i;
|
||||
if (i != bufferCount - 1) {
|
||||
vs << " + ";
|
||||
}
|
||||
vs << "void main() {\n";
|
||||
|
||||
vs << "gl_Position = vec4(";
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
vs << "a_position" << i;
|
||||
if (i != bufferCount - 1) {
|
||||
vs << " + ";
|
||||
}
|
||||
}
|
||||
vs << ", 1.0);";
|
||||
|
||||
vs << "}\n";
|
||||
|
||||
return utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex,
|
||||
vs.str().c_str());
|
||||
}
|
||||
vs << ", 1.0);";
|
||||
|
||||
wgpu::RenderPipeline MakeRenderPipeline(const wgpu::ShaderModule& vsModule,
|
||||
unsigned int bufferCount) {
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.vertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
vs << "}\n";
|
||||
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
descriptor.cVertexState.cVertexBuffers[i].attributeCount = 1;
|
||||
descriptor.cVertexState.cVertexBuffers[i].attributes =
|
||||
&descriptor.cVertexState.cAttributes[i];
|
||||
descriptor.cVertexState.cAttributes[i].shaderLocation = i;
|
||||
descriptor.cVertexState.cAttributes[i].format = wgpu::VertexFormat::Float3;
|
||||
}
|
||||
descriptor.cVertexState.vertexBufferCount = bufferCount;
|
||||
return utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex,
|
||||
vs.str().c_str());
|
||||
}
|
||||
|
||||
return device.CreateRenderPipeline(&descriptor);
|
||||
wgpu::RenderPipeline MakeRenderPipeline(const wgpu::ShaderModule& vsModule,
|
||||
unsigned int bufferCount) {
|
||||
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||
descriptor.vertexStage.module = vsModule;
|
||||
descriptor.cFragmentStage.module = fsModule;
|
||||
|
||||
for (unsigned int i = 0; i < bufferCount; ++i) {
|
||||
descriptor.cVertexState.cVertexBuffers[i].attributeCount = 1;
|
||||
descriptor.cVertexState.cVertexBuffers[i].attributes =
|
||||
&descriptor.cVertexState.cAttributes[i];
|
||||
descriptor.cVertexState.cAttributes[i].shaderLocation = i;
|
||||
descriptor.cVertexState.cAttributes[i].format = wgpu::VertexFormat::Float3;
|
||||
}
|
||||
descriptor.cVertexState.vertexBufferCount = bufferCount;
|
||||
|
||||
wgpu::ShaderModule fsModule;
|
||||
return device.CreateRenderPipeline(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::ShaderModule fsModule;
|
||||
};
|
||||
|
||||
TEST_F(VertexBufferValidationTest, VertexBuffersInheritedBetweenPipelines) {
|
||||
|
||||
@@ -185,7 +185,6 @@ TEST_F(WireArgumentTests, CStringArgument) {
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
|
||||
// Test that the wire is able to send objects as value arguments
|
||||
TEST_F(WireArgumentTests, ObjectAsValueArgument) {
|
||||
WGPUCommandEncoder cmdBufEncoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||
|
||||
@@ -613,4 +613,3 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ class WireErrorCallbackTests : public WireTest {
|
||||
WireTest::SetUp();
|
||||
|
||||
mockDeviceErrorCallback = std::make_unique<StrictMock<MockDeviceErrorCallback>>();
|
||||
mockDevicePopErrorScopeCallback = std::make_unique<StrictMock<MockDevicePopErrorScopeCallback>>();
|
||||
mockDevicePopErrorScopeCallback =
|
||||
std::make_unique<StrictMock<MockDevicePopErrorScopeCallback>>();
|
||||
mockDeviceLostCallback = std::make_unique<StrictMock<MockDeviceLostCallback>>();
|
||||
}
|
||||
|
||||
@@ -206,8 +207,7 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceDestroyed) {
|
||||
|
||||
EXPECT_TRUE(wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this));
|
||||
|
||||
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _)).WillOnce(Return(true));
|
||||
FlushClient();
|
||||
|
||||
// Incomplete callback called in Device destructor.
|
||||
|
||||
@@ -40,8 +40,9 @@ TEST_F(WireExtensionTests, ChainedStruct) {
|
||||
.WillOnce(Invoke([&](Unused, const WGPUSamplerDescriptor* serverDesc) -> WGPUSampler {
|
||||
EXPECT_STREQ(serverDesc->label, clientDesc.label);
|
||||
|
||||
const auto* ext = reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
const auto* ext =
|
||||
reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
EXPECT_EQ(ext->chain.sType, clientExt.chain.sType);
|
||||
EXPECT_EQ(ext->maxAnisotropy, clientExt.maxAnisotropy);
|
||||
|
||||
@@ -73,13 +74,15 @@ TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||
.WillOnce(Invoke([&](Unused, const WGPUSamplerDescriptor* serverDesc) -> WGPUSampler {
|
||||
EXPECT_STREQ(serverDesc->label, clientDesc.label);
|
||||
|
||||
const auto* ext1 = reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
const auto* ext1 =
|
||||
reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
|
||||
EXPECT_EQ(ext1->maxAnisotropy, clientExt1.maxAnisotropy);
|
||||
|
||||
const auto* ext2 = reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
ext1->chain.next);
|
||||
const auto* ext2 =
|
||||
reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
ext1->chain.next);
|
||||
EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
|
||||
EXPECT_EQ(ext2->maxAnisotropy, clientExt2.maxAnisotropy);
|
||||
|
||||
@@ -99,13 +102,15 @@ TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||
.WillOnce(Invoke([&](Unused, const WGPUSamplerDescriptor* serverDesc) -> WGPUSampler {
|
||||
EXPECT_STREQ(serverDesc->label, clientDesc.label);
|
||||
|
||||
const auto* ext2 = reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
const auto* ext2 =
|
||||
reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
serverDesc->nextInChain);
|
||||
EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
|
||||
EXPECT_EQ(ext2->maxAnisotropy, clientExt2.maxAnisotropy);
|
||||
|
||||
const auto* ext1 = reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
ext2->chain.next);
|
||||
const auto* ext1 =
|
||||
reinterpret_cast<const WGPUSamplerDescriptorDummyAnisotropicFiltering*>(
|
||||
ext2->chain.next);
|
||||
EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
|
||||
EXPECT_EQ(ext1->maxAnisotropy, clientExt1.maxAnisotropy);
|
||||
|
||||
|
||||
@@ -180,9 +180,7 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||
ClientReadHandle* handle = clientMemoryTransferService.NewReadHandle();
|
||||
|
||||
EXPECT_CALL(clientMemoryTransferService, OnCreateReadHandle(sizeof(mBufferContent)))
|
||||
.WillOnce(InvokeWithoutArgs([=]() {
|
||||
return handle;
|
||||
}));
|
||||
.WillOnce(InvokeWithoutArgs([=]() { return handle; }));
|
||||
|
||||
return handle;
|
||||
}
|
||||
@@ -259,9 +257,7 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||
ClientWriteHandle* handle = clientMemoryTransferService.NewWriteHandle();
|
||||
|
||||
EXPECT_CALL(clientMemoryTransferService, OnCreateWriteHandle(sizeof(mBufferContent)))
|
||||
.WillOnce(InvokeWithoutArgs([=]() {
|
||||
return handle;
|
||||
}));
|
||||
.WillOnce(InvokeWithoutArgs([=]() { return handle; }));
|
||||
|
||||
return handle;
|
||||
}
|
||||
@@ -300,22 +296,18 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||
EXPECT_CALL(serverMemoryTransferService,
|
||||
OnDeserializeWriteHandle(Pointee(Eq(mSerializeCreateInfo)),
|
||||
sizeof(mSerializeCreateInfo), _))
|
||||
.WillOnce(InvokeWithoutArgs([&]() {
|
||||
return false;
|
||||
}));
|
||||
.WillOnce(InvokeWithoutArgs([&]() { return false; }));
|
||||
}
|
||||
|
||||
void ExpectClientWriteHandleOpen(ClientWriteHandle* handle, uint32_t* mappedData) {
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleOpen(handle))
|
||||
.WillOnce(InvokeWithoutArgs([=]() {
|
||||
return std::make_pair(mappedData, sizeof(*mappedData));
|
||||
}));
|
||||
.WillOnce(InvokeWithoutArgs(
|
||||
[=]() { return std::make_pair(mappedData, sizeof(*mappedData)); }));
|
||||
}
|
||||
|
||||
void MockClientWriteHandleOpenFailure(ClientWriteHandle* handle) {
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleOpen(handle))
|
||||
.WillOnce(InvokeWithoutArgs(
|
||||
[&]() { return std::make_pair(nullptr, 0); }));
|
||||
.WillOnce(InvokeWithoutArgs([&]() { return std::make_pair(nullptr, 0); }));
|
||||
}
|
||||
|
||||
void ExpectClientWriteHandleSerializeFlush(ClientWriteHandle* handle) {
|
||||
@@ -348,8 +340,8 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||
|
||||
// Arbitrary values used within tests to check if serialized data is correctly passed
|
||||
// between the client and server. The static data changes between runs of the tests and
|
||||
// test expectations will check that serialized values are passed to the respective deserialization
|
||||
// function.
|
||||
// test expectations will check that serialized values are passed to the respective
|
||||
// deserialization function.
|
||||
static uint32_t mSerializeCreateInfo;
|
||||
static uint32_t mSerializeInitialDataInfo;
|
||||
static uint32_t mSerializeFlushInfo;
|
||||
@@ -360,8 +352,9 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||
// The client's zero-initialized buffer for writing.
|
||||
uint32_t mMappedBufferContent = 0;
|
||||
|
||||
// |mMappedBufferContent| should be set equal to |mUpdatedBufferContent| when the client performs a write.
|
||||
// Test expectations should check that |mBufferContent == mUpdatedBufferContent| after all writes are flushed.
|
||||
// |mMappedBufferContent| should be set equal to |mUpdatedBufferContent| when the client
|
||||
// performs a write. Test expectations should check that |mBufferContent ==
|
||||
// mUpdatedBufferContent| after all writes are flushed.
|
||||
static uint32_t mUpdatedBufferContent;
|
||||
|
||||
testing::StrictMock<dawn_wire::server::MockMemoryTransferService> serverMemoryTransferService;
|
||||
|
||||
@@ -68,9 +68,11 @@ inline testing::Matcher<MatcherLambdaArgument<Lambda>> MatchesLambda(Lambda lamb
|
||||
|
||||
class StringMessageMatcher : public testing::MatcherInterface<const char*> {
|
||||
public:
|
||||
explicit StringMessageMatcher() {}
|
||||
explicit StringMessageMatcher() {
|
||||
}
|
||||
|
||||
bool MatchAndExplain(const char* message, testing::MatchResultListener* listener) const override {
|
||||
bool MatchAndExplain(const char* message,
|
||||
testing::MatchResultListener* listener) const override {
|
||||
if (message == nullptr) {
|
||||
*listener << "missing error message";
|
||||
return false;
|
||||
@@ -83,11 +85,11 @@ class StringMessageMatcher : public testing::MatcherInterface<const char*> {
|
||||
}
|
||||
|
||||
void DescribeTo(std::ostream* os) const override {
|
||||
*os << "valid error message";
|
||||
*os << "valid error message";
|
||||
}
|
||||
|
||||
void DescribeNegationTo(std::ostream* os) const override {
|
||||
*os << "invalid error message";
|
||||
*os << "invalid error message";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user