Fix build/namespaces issues
This CL fixes up various build/namespaces lint errors and enables the lint check. Bug: dawn:1339 Change-Id: Ib2edd0019cb010e2c6226abce6cfee50a0b4b763 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87482 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
6cb57a9847
commit
b0acbd436d
|
@ -1,3 +1,2 @@
|
||||||
filter=-build/namespaces
|
|
||||||
filter=-readability/todo
|
filter=-readability/todo
|
||||||
filter=-runtime/indentation_namespace
|
filter=-runtime/indentation_namespace
|
||||||
|
|
|
@ -32,9 +32,7 @@
|
||||||
|
|
||||||
namespace dawn::native::metal {
|
namespace dawn::native::metal {
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct KalmanInfo;
|
struct KalmanInfo;
|
||||||
}
|
|
||||||
|
|
||||||
class Device final : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -42,11 +42,6 @@
|
||||||
|
|
||||||
namespace dawn::native::metal {
|
namespace dawn::native::metal {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// The time interval for each round of kalman filter
|
|
||||||
static constexpr uint64_t kFilterIntervalInMs = static_cast<uint64_t>(NSEC_PER_SEC / 10);
|
|
||||||
|
|
||||||
struct KalmanInfo {
|
struct KalmanInfo {
|
||||||
float filterValue; // The estimation value
|
float filterValue; // The estimation value
|
||||||
float kalmanGain; // The kalman gain
|
float kalmanGain; // The kalman gain
|
||||||
|
@ -54,6 +49,11 @@ namespace dawn::native::metal {
|
||||||
float P; // The a posteriori estimate covariance
|
float P; // The a posteriori estimate covariance
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// The time interval for each round of kalman filter
|
||||||
|
static constexpr uint64_t kFilterIntervalInMs = static_cast<uint64_t>(NSEC_PER_SEC / 10);
|
||||||
|
|
||||||
// A simplified kalman filter for estimating timestamp period based on measured values
|
// A simplified kalman filter for estimating timestamp period based on measured values
|
||||||
float KalmanFilter(KalmanInfo* info, float measuredValue) {
|
float KalmanFilter(KalmanInfo* info, float measuredValue) {
|
||||||
// Optimize kalman gain
|
// Optimize kalman gain
|
||||||
|
|
|
@ -45,7 +45,9 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::SaveArg;
|
||||||
|
|
||||||
class AdapterDiscoveryTests : public ::testing::Test {};
|
class AdapterDiscoveryTests : public ::testing::Test {};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
|
using testing::Exactly;
|
||||||
|
using testing::MockCallback;
|
||||||
|
|
||||||
class MockDeviceLostCallback {
|
class MockDeviceLostCallback {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include "dawn/tests/DawnTest.h"
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::InSequence;
|
||||||
|
|
||||||
class MockMapCallback {
|
class MockMapCallback {
|
||||||
public:
|
public:
|
||||||
|
@ -67,7 +67,7 @@ class QueueTimelineTests : public DawnTest {
|
||||||
// when queue.OnSubmittedWorkDone is called after mMapReadBuffer.MapAsync. The callback order should
|
// when queue.OnSubmittedWorkDone is called after mMapReadBuffer.MapAsync. The callback order should
|
||||||
// happen in the order the functions are called.
|
// happen in the order the functions are called.
|
||||||
TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
|
TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
|
||||||
testing::InSequence sequence;
|
InSequence sequence;
|
||||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
|
||||||
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
||||||
// happen in the order the functions are called.
|
// happen in the order the functions are called.
|
||||||
TEST_P(QueueTimelineTests, OnWorkDone_MapRead) {
|
TEST_P(QueueTimelineTests, OnWorkDone_MapRead) {
|
||||||
testing::InSequence sequence;
|
InSequence sequence;
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
|
||||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
#include "dawn/native/BuddyAllocator.h"
|
#include "dawn/native/BuddyAllocator.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
constexpr uint64_t BuddyAllocator::kInvalidOffset;
|
constexpr uint64_t BuddyAllocator::kInvalidOffset;
|
||||||
|
|
||||||
// Verify the buddy allocator with a basic test.
|
// Verify the buddy allocator with a basic test.
|
||||||
TEST(BuddyAllocatorTests, SingleBlock) {
|
TEST(BuddyAllocatorTests, SingleBlock) {
|
||||||
// After one 32 byte allocation:
|
// After one 32 byte allocation:
|
||||||
//
|
//
|
||||||
// Level --------------------------------
|
// Level --------------------------------
|
||||||
|
@ -49,10 +49,10 @@ TEST(BuddyAllocatorTests, SingleBlock) {
|
||||||
// Deallocate the block.
|
// Deallocate the block.
|
||||||
allocator.Deallocate(blockOffset);
|
allocator.Deallocate(blockOffset);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify multiple allocations succeeds using a buddy allocator.
|
// Verify multiple allocations succeeds using a buddy allocator.
|
||||||
TEST(BuddyAllocatorTests, MultipleBlocks) {
|
TEST(BuddyAllocatorTests, MultipleBlocks) {
|
||||||
// Fill every level in the allocator (order-n = 2^n)
|
// Fill every level in the allocator (order-n = 2^n)
|
||||||
const uint64_t maxBlockSize = (1ull << 16);
|
const uint64_t maxBlockSize = (1ull << 16);
|
||||||
for (uint64_t order = 1; (1ull << order) <= maxBlockSize; order++) {
|
for (uint64_t order = 1; (1ull << order) <= maxBlockSize; order++) {
|
||||||
|
@ -63,10 +63,10 @@ TEST(BuddyAllocatorTests, MultipleBlocks) {
|
||||||
ASSERT_EQ(allocator.Allocate(blockSize), blockSize * blocki);
|
ASSERT_EQ(allocator.Allocate(blockSize), blockSize * blocki);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that a single allocation succeeds using a buddy allocator.
|
// Verify that a single allocation succeeds using a buddy allocator.
|
||||||
TEST(BuddyAllocatorTests, SingleSplitBlock) {
|
TEST(BuddyAllocatorTests, SingleSplitBlock) {
|
||||||
// After one 8 byte allocation:
|
// After one 8 byte allocation:
|
||||||
//
|
//
|
||||||
// Level --------------------------------
|
// Level --------------------------------
|
||||||
|
@ -98,10 +98,10 @@ TEST(BuddyAllocatorTests, SingleSplitBlock) {
|
||||||
|
|
||||||
allocator.Deallocate(blockOffset);
|
allocator.Deallocate(blockOffset);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that a multiple allocated blocks can be removed in the free-list.
|
// Verify that a multiple allocated blocks can be removed in the free-list.
|
||||||
TEST(BuddyAllocatorTests, MultipleSplitBlocks) {
|
TEST(BuddyAllocatorTests, MultipleSplitBlocks) {
|
||||||
// After four 16 byte allocations:
|
// After four 16 byte allocations:
|
||||||
//
|
//
|
||||||
// Level --------------------------------
|
// Level --------------------------------
|
||||||
|
@ -158,10 +158,10 @@ TEST(BuddyAllocatorTests, MultipleSplitBlocks) {
|
||||||
// FreeList[Level0] = [BlockABCD] -> x
|
// FreeList[Level0] = [BlockABCD] -> x
|
||||||
allocator.Deallocate(blockOffsetA);
|
allocator.Deallocate(blockOffsetA);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the buddy allocator can handle allocations of various sizes.
|
// Verify the buddy allocator can handle allocations of various sizes.
|
||||||
TEST(BuddyAllocatorTests, MultipleSplitBlockIncreasingSize) {
|
TEST(BuddyAllocatorTests, MultipleSplitBlockIncreasingSize) {
|
||||||
// After four Level4-to-Level1 byte then one L4 block allocations:
|
// After four Level4-to-Level1 byte then one L4 block allocations:
|
||||||
//
|
//
|
||||||
// Level -----------------------------------------------------------------
|
// Level -----------------------------------------------------------------
|
||||||
|
@ -193,10 +193,10 @@ TEST(BuddyAllocatorTests, MultipleSplitBlockIncreasingSize) {
|
||||||
|
|
||||||
// Check if we're full.
|
// Check if we're full.
|
||||||
ASSERT_EQ(allocator.Allocate(32), BuddyAllocator::kInvalidOffset);
|
ASSERT_EQ(allocator.Allocate(32), BuddyAllocator::kInvalidOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify very small allocations using a larger allocator works correctly.
|
// Verify very small allocations using a larger allocator works correctly.
|
||||||
TEST(BuddyAllocatorTests, MultipleSplitBlocksVariableSizes) {
|
TEST(BuddyAllocatorTests, MultipleSplitBlocksVariableSizes) {
|
||||||
// After allocating four pairs of one 64 byte block and one 32 byte block.
|
// After allocating four pairs of one 64 byte block and one 32 byte block.
|
||||||
//
|
//
|
||||||
// Level -----------------------------------------------------------------
|
// Level -----------------------------------------------------------------
|
||||||
|
@ -227,10 +227,10 @@ TEST(BuddyAllocatorTests, MultipleSplitBlocksVariableSizes) {
|
||||||
ASSERT_EQ(allocator.Allocate(32), 288ull);
|
ASSERT_EQ(allocator.Allocate(32), 288ull);
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the buddy allocator can deal with bad fragmentation.
|
// Verify the buddy allocator can deal with bad fragmentation.
|
||||||
TEST(BuddyAllocatorTests, MultipleSplitBlocksInterleaved) {
|
TEST(BuddyAllocatorTests, MultipleSplitBlocksInterleaved) {
|
||||||
// Allocate every leaf then de-allocate every other of those allocations.
|
// Allocate every leaf then de-allocate every other of those allocations.
|
||||||
//
|
//
|
||||||
// Level -----------------------------------------------------------------
|
// Level -----------------------------------------------------------------
|
||||||
|
@ -261,12 +261,12 @@ TEST(BuddyAllocatorTests, MultipleSplitBlocksInterleaved) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 8u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 8u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the buddy allocator can deal with multiple allocations with mixed alignments.
|
// Verify the buddy allocator can deal with multiple allocations with mixed alignments.
|
||||||
TEST(BuddyAllocatorTests, SameSizeVariousAlignment) {
|
TEST(BuddyAllocatorTests, SameSizeVariousAlignment) {
|
||||||
// After two 8 byte allocations with 16 byte alignment then one 8 byte allocation with 8 byte
|
// After two 8 byte allocations with 16 byte alignment then one 8 byte allocation with 8
|
||||||
// alignment.
|
// byte alignment.
|
||||||
//
|
//
|
||||||
// Level --------------------------------
|
// Level --------------------------------
|
||||||
// 0 32 | S |
|
// 0 32 | S |
|
||||||
|
@ -294,12 +294,12 @@ TEST(BuddyAllocatorTests, SameSizeVariousAlignment) {
|
||||||
ASSERT_EQ(allocator.Allocate(8, 8), 24u);
|
ASSERT_EQ(allocator.Allocate(8, 8), 24u);
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the buddy allocator can deal with multiple allocations with equal alignments.
|
// Verify the buddy allocator can deal with multiple allocations with equal alignments.
|
||||||
TEST(BuddyAllocatorTests, VariousSizeSameAlignment) {
|
TEST(BuddyAllocatorTests, VariousSizeSameAlignment) {
|
||||||
// After two 8 byte allocations with 4 byte alignment then one 16 byte allocation with 4 byte
|
// After two 8 byte allocations with 4 byte alignment then one 16 byte allocation with 4
|
||||||
// alignment.
|
// byte alignment.
|
||||||
//
|
//
|
||||||
// Level --------------------------------
|
// Level --------------------------------
|
||||||
// 0 32 | S |
|
// 0 32 | S |
|
||||||
|
@ -326,4 +326,6 @@ TEST(BuddyAllocatorTests, VariousSizeSameAlignment) {
|
||||||
ASSERT_EQ(allocator.Allocate(16, alignment), 16ull);
|
ASSERT_EQ(allocator.Allocate(16, alignment), 16ull);
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 0u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfFreeBlocksForTesting(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -22,18 +22,19 @@
|
||||||
#include "dawn/native/PooledResourceMemoryAllocator.h"
|
#include "dawn/native/PooledResourceMemoryAllocator.h"
|
||||||
#include "dawn/native/ResourceHeapAllocator.h"
|
#include "dawn/native/ResourceHeapAllocator.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
class PlaceholderResourceHeapAllocator : public ResourceHeapAllocator {
|
class PlaceholderResourceHeapAllocator : public ResourceHeapAllocator {
|
||||||
public:
|
public:
|
||||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> AllocateResourceHeap(uint64_t size) override {
|
ResultOrError<std::unique_ptr<ResourceHeapBase>> AllocateResourceHeap(
|
||||||
|
uint64_t size) override {
|
||||||
return std::make_unique<ResourceHeapBase>();
|
return std::make_unique<ResourceHeapBase>();
|
||||||
}
|
}
|
||||||
void DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> allocation) override {
|
void DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> allocation) override {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlaceholderBuddyResourceAllocator {
|
class PlaceholderBuddyResourceAllocator {
|
||||||
public:
|
public:
|
||||||
PlaceholderBuddyResourceAllocator(uint64_t maxBlockSize, uint64_t memorySize)
|
PlaceholderBuddyResourceAllocator(uint64_t maxBlockSize, uint64_t memorySize)
|
||||||
: mAllocator(maxBlockSize, memorySize, &mHeapAllocator) {
|
: mAllocator(maxBlockSize, memorySize, &mHeapAllocator) {
|
||||||
|
@ -62,10 +63,10 @@ class PlaceholderBuddyResourceAllocator {
|
||||||
private:
|
private:
|
||||||
PlaceholderResourceHeapAllocator mHeapAllocator;
|
PlaceholderResourceHeapAllocator mHeapAllocator;
|
||||||
BuddyMemoryAllocator mAllocator;
|
BuddyMemoryAllocator mAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify a single resource allocation in a single heap.
|
// Verify a single resource allocation in a single heap.
|
||||||
TEST(BuddyMemoryAllocatorTests, SingleHeap) {
|
TEST(BuddyMemoryAllocatorTests, SingleHeap) {
|
||||||
// After one 128 byte resource allocation:
|
// After one 128 byte resource allocation:
|
||||||
//
|
//
|
||||||
// max block size -> ---------------------------
|
// max block size -> ---------------------------
|
||||||
|
@ -93,10 +94,10 @@ TEST(BuddyMemoryAllocatorTests, SingleHeap) {
|
||||||
|
|
||||||
allocator.Deallocate(allocation1);
|
allocator.Deallocate(allocation1);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that multiple allocation are created in separate heaps.
|
// Verify that multiple allocation are created in separate heaps.
|
||||||
TEST(BuddyMemoryAllocatorTests, MultipleHeaps) {
|
TEST(BuddyMemoryAllocatorTests, MultipleHeaps) {
|
||||||
// After two 128 byte resource allocations:
|
// After two 128 byte resource allocations:
|
||||||
//
|
//
|
||||||
// max block size -> ---------------------------
|
// max block size -> ---------------------------
|
||||||
|
@ -139,10 +140,10 @@ TEST(BuddyMemoryAllocatorTests, MultipleHeaps) {
|
||||||
|
|
||||||
allocator.Deallocate(allocation2);
|
allocator.Deallocate(allocation2);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify multiple sub-allocations can re-use heaps.
|
// Verify multiple sub-allocations can re-use heaps.
|
||||||
TEST(BuddyMemoryAllocatorTests, MultipleSplitHeaps) {
|
TEST(BuddyMemoryAllocatorTests, MultipleSplitHeaps) {
|
||||||
// After two 64 byte allocations with 128 byte heaps.
|
// After two 64 byte allocations with 128 byte heaps.
|
||||||
//
|
//
|
||||||
// max block size -> ---------------------------
|
// max block size -> ---------------------------
|
||||||
|
@ -191,10 +192,10 @@ TEST(BuddyMemoryAllocatorTests, MultipleSplitHeaps) {
|
||||||
|
|
||||||
allocator.Deallocate(allocation3);
|
allocator.Deallocate(allocation3);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify resource sub-allocation of various sizes over multiple heaps.
|
// Verify resource sub-allocation of various sizes over multiple heaps.
|
||||||
TEST(BuddyMemoryAllocatorTests, MultiplSplitHeapsVariableSizes) {
|
TEST(BuddyMemoryAllocatorTests, MultiplSplitHeapsVariableSizes) {
|
||||||
// After three 64 byte allocations and two 128 byte allocations.
|
// After three 64 byte allocations and two 128 byte allocations.
|
||||||
//
|
//
|
||||||
// max block size -> -------------------------------------------------------
|
// max block size -> -------------------------------------------------------
|
||||||
|
@ -267,10 +268,10 @@ TEST(BuddyMemoryAllocatorTests, MultiplSplitHeapsVariableSizes) {
|
||||||
|
|
||||||
allocator.Deallocate(allocation3);
|
allocator.Deallocate(allocation3);
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 0u); // Released H1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify resource sub-allocation of same sizes with various alignments.
|
// Verify resource sub-allocation of same sizes with various alignments.
|
||||||
TEST(BuddyMemoryAllocatorTests, SameSizeVariousAlignment) {
|
TEST(BuddyMemoryAllocatorTests, SameSizeVariousAlignment) {
|
||||||
// After three 64 byte and one 128 byte resource allocations.
|
// After three 64 byte and one 128 byte resource allocations.
|
||||||
//
|
//
|
||||||
// max block size -> -------------------------------------------------------
|
// max block size -> -------------------------------------------------------
|
||||||
|
@ -317,10 +318,10 @@ TEST(BuddyMemoryAllocatorTests, SameSizeVariousAlignment) {
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 3u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 3u);
|
||||||
ASSERT_EQ(allocation3.GetResourceHeap(), allocation4.GetResourceHeap());
|
ASSERT_EQ(allocation3.GetResourceHeap(), allocation4.GetResourceHeap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify resource sub-allocation of various sizes with same alignments.
|
// Verify resource sub-allocation of various sizes with same alignments.
|
||||||
TEST(BuddyMemoryAllocatorTests, VariousSizeSameAlignment) {
|
TEST(BuddyMemoryAllocatorTests, VariousSizeSameAlignment) {
|
||||||
// After two 64 byte and two 128 byte resource allocations:
|
// After two 64 byte and two 128 byte resource allocations:
|
||||||
//
|
//
|
||||||
// max block size -> -------------------------------------------------------
|
// max block size -> -------------------------------------------------------
|
||||||
|
@ -368,10 +369,10 @@ TEST(BuddyMemoryAllocatorTests, VariousSizeSameAlignment) {
|
||||||
|
|
||||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 3u);
|
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 3u);
|
||||||
ASSERT_NE(allocation3.GetResourceHeap(), allocation4.GetResourceHeap());
|
ASSERT_NE(allocation3.GetResourceHeap(), allocation4.GetResourceHeap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify allocating a very large resource does not overflow.
|
// Verify allocating a very large resource does not overflow.
|
||||||
TEST(BuddyMemoryAllocatorTests, AllocationOverflow) {
|
TEST(BuddyMemoryAllocatorTests, AllocationOverflow) {
|
||||||
constexpr uint64_t heapSize = 128;
|
constexpr uint64_t heapSize = 128;
|
||||||
constexpr uint64_t maxBlockSize = 512;
|
constexpr uint64_t maxBlockSize = 512;
|
||||||
PlaceholderBuddyResourceAllocator allocator(maxBlockSize, heapSize);
|
PlaceholderBuddyResourceAllocator allocator(maxBlockSize, heapSize);
|
||||||
|
@ -379,10 +380,10 @@ TEST(BuddyMemoryAllocatorTests, AllocationOverflow) {
|
||||||
constexpr uint64_t largeBlock = (1ull << 63) + 1;
|
constexpr uint64_t largeBlock = (1ull << 63) + 1;
|
||||||
ResourceMemoryAllocation invalidAllocation = allocator.Allocate(largeBlock);
|
ResourceMemoryAllocation invalidAllocation = allocator.Allocate(largeBlock);
|
||||||
ASSERT_EQ(invalidAllocation.GetInfo().mMethod, AllocationMethod::kInvalid);
|
ASSERT_EQ(invalidAllocation.GetInfo().mMethod, AllocationMethod::kInvalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify resource heaps will be reused from a pool.
|
// Verify resource heaps will be reused from a pool.
|
||||||
TEST(BuddyMemoryAllocatorTests, ReuseFreedHeaps) {
|
TEST(BuddyMemoryAllocatorTests, ReuseFreedHeaps) {
|
||||||
constexpr uint64_t kHeapSize = 128;
|
constexpr uint64_t kHeapSize = 128;
|
||||||
constexpr uint64_t kMaxBlockSize = 4096;
|
constexpr uint64_t kMaxBlockSize = 4096;
|
||||||
|
|
||||||
|
@ -420,10 +421,10 @@ TEST(BuddyMemoryAllocatorTests, ReuseFreedHeaps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(poolAllocator.GetPoolSizeForTesting(), 0u);
|
ASSERT_EQ(poolAllocator.GetPoolSizeForTesting(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify resource heaps that were reused from a pool can be destroyed.
|
// Verify resource heaps that were reused from a pool can be destroyed.
|
||||||
TEST(BuddyMemoryAllocatorTests, DestroyHeaps) {
|
TEST(BuddyMemoryAllocatorTests, DestroyHeaps) {
|
||||||
constexpr uint64_t kHeapSize = 128;
|
constexpr uint64_t kHeapSize = 128;
|
||||||
constexpr uint64_t kMaxBlockSize = 4096;
|
constexpr uint64_t kMaxBlockSize = 4096;
|
||||||
|
|
||||||
|
@ -434,8 +435,8 @@ TEST(BuddyMemoryAllocatorTests, DestroyHeaps) {
|
||||||
std::set<ResourceHeapBase*> heaps = {};
|
std::set<ResourceHeapBase*> heaps = {};
|
||||||
std::vector<ResourceMemoryAllocation> allocations = {};
|
std::vector<ResourceMemoryAllocation> allocations = {};
|
||||||
|
|
||||||
// Count by heap (vs number of allocations) to ensure there are exactly |kNumOfHeaps| worth of
|
// Count by heap (vs number of allocations) to ensure there are exactly |kNumOfHeaps| worth
|
||||||
// buffers. Otherwise, the heap may be reused if not full.
|
// of buffers. Otherwise, the heap may be reused if not full.
|
||||||
constexpr uint32_t kNumOfHeaps = 10;
|
constexpr uint32_t kNumOfHeaps = 10;
|
||||||
|
|
||||||
// Allocate |kNumOfHeaps| worth.
|
// Allocate |kNumOfHeaps| worth.
|
||||||
|
@ -458,4 +459,6 @@ TEST(BuddyMemoryAllocatorTests, DestroyHeaps) {
|
||||||
// Make sure we can destroy the remaining heaps.
|
// Make sure we can destroy the remaining heaps.
|
||||||
poolAllocator.DestroyPool();
|
poolAllocator.DestroyPool();
|
||||||
ASSERT_EQ(poolAllocator.GetPoolSizeForTesting(), 0u);
|
ASSERT_EQ(poolAllocator.GetPoolSizeForTesting(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -19,56 +19,56 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "dawn/native/CommandAllocator.h"
|
#include "dawn/native/CommandAllocator.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
// Definition of the command types used in the tests
|
// Definition of the command types used in the tests
|
||||||
enum class CommandType {
|
enum class CommandType {
|
||||||
Draw,
|
Draw,
|
||||||
Pipeline,
|
Pipeline,
|
||||||
PushConstants,
|
PushConstants,
|
||||||
Big,
|
Big,
|
||||||
Small,
|
Small,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandDraw {
|
struct CommandDraw {
|
||||||
uint32_t first;
|
uint32_t first;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandPipeline {
|
struct CommandPipeline {
|
||||||
uint64_t pipeline;
|
uint64_t pipeline;
|
||||||
uint32_t attachmentPoint;
|
uint32_t attachmentPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandPushConstants {
|
struct CommandPushConstants {
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t offset;
|
uint8_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int kBigBufferSize = 65536;
|
constexpr int kBigBufferSize = 65536;
|
||||||
|
|
||||||
struct CommandBig {
|
struct CommandBig {
|
||||||
uint32_t buffer[kBigBufferSize];
|
uint32_t buffer[kBigBufferSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandSmall {
|
struct CommandSmall {
|
||||||
uint16_t data;
|
uint16_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test allocating nothing works
|
// Test allocating nothing works
|
||||||
TEST(CommandAllocator, DoNothingAllocator) {
|
TEST(CommandAllocator, DoNothingAllocator) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test iterating over nothing works
|
// Test iterating over nothing works
|
||||||
TEST(CommandAllocator, DoNothingAllocatorWithIterator) {
|
TEST(CommandAllocator, DoNothingAllocatorWithIterator) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
CommandIterator iterator(std::move(allocator));
|
CommandIterator iterator(std::move(allocator));
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test basic usage of allocator + iterator
|
// Test basic usage of allocator + iterator
|
||||||
TEST(CommandAllocator, Basic) {
|
TEST(CommandAllocator, Basic) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
||||||
|
@ -111,10 +111,10 @@ TEST(CommandAllocator, Basic) {
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test basic usage of allocator + iterator with data
|
// Test basic usage of allocator + iterator with data
|
||||||
TEST(CommandAllocator, BasicWithData) {
|
TEST(CommandAllocator, BasicWithData) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
uint8_t mySize = 8;
|
uint8_t mySize = 8;
|
||||||
|
@ -155,10 +155,10 @@ TEST(CommandAllocator, BasicWithData) {
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test basic iterating several times
|
// Test basic iterating several times
|
||||||
TEST(CommandAllocator, MultipleIterations) {
|
TEST(CommandAllocator, MultipleIterations) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
uint32_t myFirst = 42;
|
uint32_t myFirst = 42;
|
||||||
|
@ -200,9 +200,9 @@ TEST(CommandAllocator, MultipleIterations) {
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Test large commands work
|
// Test large commands work
|
||||||
TEST(CommandAllocator, LargeCommands) {
|
TEST(CommandAllocator, LargeCommands) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
const int kCommandCount = 5;
|
const int kCommandCount = 5;
|
||||||
|
@ -232,10 +232,10 @@ TEST(CommandAllocator, LargeCommands) {
|
||||||
ASSERT_EQ(numCommands, kCommandCount);
|
ASSERT_EQ(numCommands, kCommandCount);
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test many small commands work
|
// Test many small commands work
|
||||||
TEST(CommandAllocator, ManySmallCommands) {
|
TEST(CommandAllocator, ManySmallCommands) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
// Stay under max representable uint16_t
|
// Stay under max representable uint16_t
|
||||||
|
@ -262,9 +262,9 @@ TEST(CommandAllocator, ManySmallCommands) {
|
||||||
ASSERT_EQ(numCommands, kCommandCount);
|
ASSERT_EQ(numCommands, kCommandCount);
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ________
|
/* ________
|
||||||
* / \
|
* / \
|
||||||
* | POUIC! |
|
* | POUIC! |
|
||||||
* \_ ______/
|
* \_ ______/
|
||||||
|
@ -274,8 +274,8 @@ TEST(CommandAllocator, ManySmallCommands) {
|
||||||
* (> <)o
|
* (> <)o
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Test usage of iterator.Reset
|
// Test usage of iterator.Reset
|
||||||
TEST(CommandAllocator, IteratorReset) {
|
TEST(CommandAllocator, IteratorReset) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
uint64_t myPipeline = 0xDEADBEEFBEEFDEAD;
|
||||||
|
@ -328,10 +328,10 @@ TEST(CommandAllocator, IteratorReset) {
|
||||||
|
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test iterating empty iterators
|
// Test iterating empty iterators
|
||||||
TEST(CommandAllocator, EmptyIterator) {
|
TEST(CommandAllocator, EmptyIterator) {
|
||||||
{
|
{
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
CommandIterator iterator(std::move(allocator));
|
CommandIterator iterator(std::move(allocator));
|
||||||
|
@ -365,55 +365,55 @@ TEST(CommandAllocator, EmptyIterator) {
|
||||||
iterator1.MakeEmptyAsDataWasDestroyed();
|
iterator1.MakeEmptyAsDataWasDestroyed();
|
||||||
iterator2.MakeEmptyAsDataWasDestroyed();
|
iterator2.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t A>
|
template <size_t A>
|
||||||
struct alignas(A) AlignedStruct {
|
struct alignas(A) AlignedStruct {
|
||||||
char placeholder;
|
char placeholder;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test for overflows in Allocate's computations, size 1 variant
|
// Test for overflows in Allocate's computations, size 1 variant
|
||||||
TEST(CommandAllocator, AllocationOverflow_1) {
|
TEST(CommandAllocator, AllocationOverflow_1) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
AlignedStruct<1>* data =
|
AlignedStruct<1>* data =
|
||||||
allocator.AllocateData<AlignedStruct<1>>(std::numeric_limits<size_t>::max() / 1);
|
allocator.AllocateData<AlignedStruct<1>>(std::numeric_limits<size_t>::max() / 1);
|
||||||
ASSERT_EQ(data, nullptr);
|
ASSERT_EQ(data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for overflows in Allocate's computations, size 2 variant
|
// Test for overflows in Allocate's computations, size 2 variant
|
||||||
TEST(CommandAllocator, AllocationOverflow_2) {
|
TEST(CommandAllocator, AllocationOverflow_2) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
AlignedStruct<2>* data =
|
AlignedStruct<2>* data =
|
||||||
allocator.AllocateData<AlignedStruct<2>>(std::numeric_limits<size_t>::max() / 2);
|
allocator.AllocateData<AlignedStruct<2>>(std::numeric_limits<size_t>::max() / 2);
|
||||||
ASSERT_EQ(data, nullptr);
|
ASSERT_EQ(data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for overflows in Allocate's computations, size 4 variant
|
// Test for overflows in Allocate's computations, size 4 variant
|
||||||
TEST(CommandAllocator, AllocationOverflow_4) {
|
TEST(CommandAllocator, AllocationOverflow_4) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
AlignedStruct<4>* data =
|
AlignedStruct<4>* data =
|
||||||
allocator.AllocateData<AlignedStruct<4>>(std::numeric_limits<size_t>::max() / 4);
|
allocator.AllocateData<AlignedStruct<4>>(std::numeric_limits<size_t>::max() / 4);
|
||||||
ASSERT_EQ(data, nullptr);
|
ASSERT_EQ(data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for overflows in Allocate's computations, size 8 variant
|
// Test for overflows in Allocate's computations, size 8 variant
|
||||||
TEST(CommandAllocator, AllocationOverflow_8) {
|
TEST(CommandAllocator, AllocationOverflow_8) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
AlignedStruct<8>* data =
|
AlignedStruct<8>* data =
|
||||||
allocator.AllocateData<AlignedStruct<8>>(std::numeric_limits<size_t>::max() / 8);
|
allocator.AllocateData<AlignedStruct<8>>(std::numeric_limits<size_t>::max() / 8);
|
||||||
ASSERT_EQ(data, nullptr);
|
ASSERT_EQ(data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int DefaultValue>
|
template <int DefaultValue>
|
||||||
struct IntWithDefault {
|
struct IntWithDefault {
|
||||||
IntWithDefault() : value(DefaultValue) {
|
IntWithDefault() : value(DefaultValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that the allcator correctly defaults initalizes data for Allocate
|
// Test that the allcator correctly defaults initalizes data for Allocate
|
||||||
TEST(CommandAllocator, AllocateDefaultInitializes) {
|
TEST(CommandAllocator, AllocateDefaultInitializes) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
IntWithDefault<42>* int42 = allocator.Allocate<IntWithDefault<42>>(CommandType::Draw);
|
IntWithDefault<42>* int42 = allocator.Allocate<IntWithDefault<42>>(CommandType::Draw);
|
||||||
|
@ -427,10 +427,10 @@ TEST(CommandAllocator, AllocateDefaultInitializes) {
|
||||||
|
|
||||||
CommandIterator iterator(std::move(allocator));
|
CommandIterator iterator(std::move(allocator));
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the allocator correctly default-initalizes data for AllocateData
|
// Test that the allocator correctly default-initalizes data for AllocateData
|
||||||
TEST(CommandAllocator, AllocateDataDefaultInitializes) {
|
TEST(CommandAllocator, AllocateDataDefaultInitializes) {
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
|
|
||||||
IntWithDefault<33>* int33 = allocator.AllocateData<IntWithDefault<33>>(1);
|
IntWithDefault<33>* int33 = allocator.AllocateData<IntWithDefault<33>>(1);
|
||||||
|
@ -447,18 +447,19 @@ TEST(CommandAllocator, AllocateDataDefaultInitializes) {
|
||||||
|
|
||||||
CommandIterator iterator(std::move(allocator));
|
CommandIterator iterator(std::move(allocator));
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests flattening of multiple CommandAllocators into a single CommandIterator using
|
// Tests flattening of multiple CommandAllocators into a single CommandIterator using
|
||||||
// AcquireCommandBlocks.
|
// AcquireCommandBlocks.
|
||||||
TEST(CommandAllocator, AcquireCommandBlocks) {
|
TEST(CommandAllocator, AcquireCommandBlocks) {
|
||||||
constexpr size_t kNumAllocators = 2;
|
constexpr size_t kNumAllocators = 2;
|
||||||
constexpr size_t kNumCommandsPerAllocator = 2;
|
constexpr size_t kNumCommandsPerAllocator = 2;
|
||||||
const uint64_t pipelines[kNumAllocators][kNumCommandsPerAllocator] = {
|
const uint64_t pipelines[kNumAllocators][kNumCommandsPerAllocator] = {
|
||||||
{0xDEADBEEFBEEFDEAD, 0xC0FFEEF00DC0FFEE},
|
{0xDEADBEEFBEEFDEAD, 0xC0FFEEF00DC0FFEE},
|
||||||
{0x1337C0DE1337C0DE, 0xCAFEFACEFACECAFE},
|
{0x1337C0DE1337C0DE, 0xCAFEFACEFACECAFE},
|
||||||
};
|
};
|
||||||
const uint32_t attachmentPoints[kNumAllocators][kNumCommandsPerAllocator] = {{1, 2}, {3, 4}};
|
const uint32_t attachmentPoints[kNumAllocators][kNumCommandsPerAllocator] = {{1, 2},
|
||||||
|
{3, 4}};
|
||||||
const uint32_t firsts[kNumAllocators][kNumCommandsPerAllocator] = {{42, 43}, {5, 6}};
|
const uint32_t firsts[kNumAllocators][kNumCommandsPerAllocator] = {{42, 43}, {5, 6}};
|
||||||
const uint32_t counts[kNumAllocators][kNumCommandsPerAllocator] = {{16, 32}, {4, 8}};
|
const uint32_t counts[kNumAllocators][kNumCommandsPerAllocator] = {{16, 32}, {4, 8}};
|
||||||
|
|
||||||
|
@ -466,7 +467,8 @@ TEST(CommandAllocator, AcquireCommandBlocks) {
|
||||||
for (size_t j = 0; j < kNumAllocators; ++j) {
|
for (size_t j = 0; j < kNumAllocators; ++j) {
|
||||||
CommandAllocator& allocator = allocators[j];
|
CommandAllocator& allocator = allocators[j];
|
||||||
for (size_t i = 0; i < kNumCommandsPerAllocator; ++i) {
|
for (size_t i = 0; i < kNumCommandsPerAllocator; ++i) {
|
||||||
CommandPipeline* pipeline = allocator.Allocate<CommandPipeline>(CommandType::Pipeline);
|
CommandPipeline* pipeline =
|
||||||
|
allocator.Allocate<CommandPipeline>(CommandType::Pipeline);
|
||||||
pipeline->pipeline = pipelines[j][i];
|
pipeline->pipeline = pipelines[j][i];
|
||||||
pipeline->attachmentPoint = attachmentPoints[j][i];
|
pipeline->attachmentPoint = attachmentPoints[j][i];
|
||||||
|
|
||||||
|
@ -501,4 +503,6 @@ TEST(CommandAllocator, AcquireCommandBlocks) {
|
||||||
CommandType type;
|
CommandType type;
|
||||||
ASSERT_FALSE(iterator.NextCommandId(&type));
|
ASSERT_FALSE(iterator.NextCommandId(&type));
|
||||||
iterator.MakeEmptyAsDataWasDestroyed();
|
iterator.MakeEmptyAsDataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -18,9 +18,7 @@
|
||||||
#include "dawn/native/ErrorData.h"
|
#include "dawn/native/ErrorData.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native { namespace {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
int placeholderSuccess = 0xbeef;
|
int placeholderSuccess = 0xbeef;
|
||||||
const char* placeholderErrorMessage = "I am an error message :3";
|
const char* placeholderErrorMessage = "I am an error message :3";
|
||||||
|
@ -360,4 +358,6 @@ namespace {
|
||||||
ASSERT_EQ(errorData->GetMessage(), placeholderErrorMessage);
|
ASSERT_EQ(errorData->GetMessage(), placeholderErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
// TODO(https://crbug.com/dawn/1381) Remove when namespaces are not indented.
|
||||||
|
// NOLINTNEXTLINE(readability/namespace)
|
||||||
|
}} // namespace dawn::native::
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
|
|
||||||
#include "dawn/native/PerStage.h"
|
#include "dawn/native/PerStage.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
// Tests for StageBit
|
// Tests for StageBit
|
||||||
TEST(PerStage, StageBit) {
|
TEST(PerStage, StageBit) {
|
||||||
ASSERT_EQ(StageBit(SingleShaderStage::Vertex), wgpu::ShaderStage::Vertex);
|
ASSERT_EQ(StageBit(SingleShaderStage::Vertex), wgpu::ShaderStage::Vertex);
|
||||||
ASSERT_EQ(StageBit(SingleShaderStage::Fragment), wgpu::ShaderStage::Fragment);
|
ASSERT_EQ(StageBit(SingleShaderStage::Fragment), wgpu::ShaderStage::Fragment);
|
||||||
ASSERT_EQ(StageBit(SingleShaderStage::Compute), wgpu::ShaderStage::Compute);
|
ASSERT_EQ(StageBit(SingleShaderStage::Compute), wgpu::ShaderStage::Compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic test for the PerStage container
|
// Basic test for the PerStage container
|
||||||
TEST(PerStage, PerStage) {
|
TEST(PerStage, PerStage) {
|
||||||
PerStage<int> data;
|
PerStage<int> data;
|
||||||
|
|
||||||
// Store data using wgpu::ShaderStage
|
// Store data using wgpu::ShaderStage
|
||||||
|
@ -38,10 +38,10 @@ TEST(PerStage, PerStage) {
|
||||||
ASSERT_EQ(data[wgpu::ShaderStage::Vertex], 42);
|
ASSERT_EQ(data[wgpu::ShaderStage::Vertex], 42);
|
||||||
ASSERT_EQ(data[wgpu::ShaderStage::Fragment], 3);
|
ASSERT_EQ(data[wgpu::ShaderStage::Fragment], 3);
|
||||||
ASSERT_EQ(data[wgpu::ShaderStage::Compute], -1);
|
ASSERT_EQ(data[wgpu::ShaderStage::Compute], -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test IterateStages with kAllStages
|
// Test IterateStages with kAllStages
|
||||||
TEST(PerStage, IterateAllStages) {
|
TEST(PerStage, IterateAllStages) {
|
||||||
PerStage<int> counts;
|
PerStage<int> counts;
|
||||||
counts[SingleShaderStage::Vertex] = 0;
|
counts[SingleShaderStage::Vertex] = 0;
|
||||||
counts[SingleShaderStage::Fragment] = 0;
|
counts[SingleShaderStage::Fragment] = 0;
|
||||||
|
@ -54,10 +54,10 @@ TEST(PerStage, IterateAllStages) {
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 1);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 1);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 1);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 1);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 1);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test IterateStages with one stage
|
// Test IterateStages with one stage
|
||||||
TEST(PerStage, IterateOneStage) {
|
TEST(PerStage, IterateOneStage) {
|
||||||
PerStage<int> counts;
|
PerStage<int> counts;
|
||||||
counts[SingleShaderStage::Vertex] = 0;
|
counts[SingleShaderStage::Vertex] = 0;
|
||||||
counts[SingleShaderStage::Fragment] = 0;
|
counts[SingleShaderStage::Fragment] = 0;
|
||||||
|
@ -70,10 +70,10 @@ TEST(PerStage, IterateOneStage) {
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 1);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 1);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 0);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test IterateStages with no stage
|
// Test IterateStages with no stage
|
||||||
TEST(PerStage, IterateNoStages) {
|
TEST(PerStage, IterateNoStages) {
|
||||||
PerStage<int> counts;
|
PerStage<int> counts;
|
||||||
counts[SingleShaderStage::Vertex] = 0;
|
counts[SingleShaderStage::Vertex] = 0;
|
||||||
counts[SingleShaderStage::Fragment] = 0;
|
counts[SingleShaderStage::Fragment] = 0;
|
||||||
|
@ -86,4 +86,6 @@ TEST(PerStage, IterateNoStages) {
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Vertex], 0);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 0);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Fragment], 0);
|
||||||
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 0);
|
ASSERT_EQ(counts[wgpu::ShaderStage::Compute], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::InSequence;
|
||||||
|
using testing::StrictMock;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ namespace {
|
||||||
|
|
||||||
std::unique_ptr<StrictMock<MockDestructor>> mockDestructor;
|
std::unique_ptr<StrictMock<MockDestructor>> mockDestructor;
|
||||||
|
|
||||||
class PlacementAllocatedTests : public Test {
|
class PlacementAllocatedTests : public testing::Test {
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
mockDestructor = std::make_unique<StrictMock<MockDestructor>>();
|
mockDestructor = std::make_unique<StrictMock<MockDestructor>>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
#include "dawn/native/RingBufferAllocator.h"
|
#include "dawn/native/RingBufferAllocator.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
constexpr uint64_t RingBufferAllocator::kInvalidOffset;
|
constexpr uint64_t RingBufferAllocator::kInvalidOffset;
|
||||||
|
|
||||||
// Number of basic tests for Ringbuffer
|
// Number of basic tests for Ringbuffer
|
||||||
TEST(RingBufferAllocatorTests, BasicTest) {
|
TEST(RingBufferAllocatorTests, BasicTest) {
|
||||||
constexpr uint64_t sizeInBytes = 64000;
|
constexpr uint64_t sizeInBytes = 64000;
|
||||||
RingBufferAllocator allocator(sizeInBytes);
|
RingBufferAllocator allocator(sizeInBytes);
|
||||||
|
|
||||||
|
@ -41,10 +41,10 @@ TEST(RingBufferAllocatorTests, BasicTest) {
|
||||||
|
|
||||||
// Ensure the buffer is full.
|
// Ensure the buffer is full.
|
||||||
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(3)), RingBufferAllocator::kInvalidOffset);
|
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(3)), RingBufferAllocator::kInvalidOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that several ringbuffer allocations do not fail.
|
// Tests that several ringbuffer allocations do not fail.
|
||||||
TEST(RingBufferAllocatorTests, RingBufferManyAlloc) {
|
TEST(RingBufferAllocatorTests, RingBufferManyAlloc) {
|
||||||
constexpr uint64_t maxNumOfFrames = 64000;
|
constexpr uint64_t maxNumOfFrames = 64000;
|
||||||
constexpr uint64_t frameSizeInBytes = 4;
|
constexpr uint64_t frameSizeInBytes = 4;
|
||||||
|
|
||||||
|
@ -55,10 +55,10 @@ TEST(RingBufferAllocatorTests, RingBufferManyAlloc) {
|
||||||
offset = allocator.Allocate(frameSizeInBytes, i);
|
offset = allocator.Allocate(frameSizeInBytes, i);
|
||||||
ASSERT_EQ(offset, uint64_t(i) * frameSizeInBytes);
|
ASSERT_EQ(offset, uint64_t(i) * frameSizeInBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests ringbuffer sub-allocations of the same serial are correctly tracked.
|
// Tests ringbuffer sub-allocations of the same serial are correctly tracked.
|
||||||
TEST(RingBufferAllocatorTests, AllocInSameFrame) {
|
TEST(RingBufferAllocatorTests, AllocInSameFrame) {
|
||||||
constexpr uint64_t maxNumOfFrames = 3;
|
constexpr uint64_t maxNumOfFrames = 3;
|
||||||
constexpr uint64_t frameSizeInBytes = 4;
|
constexpr uint64_t frameSizeInBytes = 4;
|
||||||
|
|
||||||
|
@ -85,10 +85,10 @@ TEST(RingBufferAllocatorTests, AllocInSameFrame) {
|
||||||
|
|
||||||
ASSERT_EQ(allocator.GetUsedSize(), 0u);
|
ASSERT_EQ(allocator.GetUsedSize(), 0u);
|
||||||
EXPECT_TRUE(allocator.Empty());
|
EXPECT_TRUE(allocator.Empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests ringbuffer sub-allocation at various offsets.
|
// Tests ringbuffer sub-allocation at various offsets.
|
||||||
TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
||||||
constexpr uint64_t maxNumOfFrames = 10;
|
constexpr uint64_t maxNumOfFrames = 10;
|
||||||
constexpr uint64_t frameSizeInBytes = 4;
|
constexpr uint64_t frameSizeInBytes = 4;
|
||||||
|
|
||||||
|
@ -135,7 +135,8 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
||||||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * maxNumOfFrames);
|
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * maxNumOfFrames);
|
||||||
|
|
||||||
// Ensure we are full.
|
// Ensure we are full.
|
||||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial), RingBufferAllocator::kInvalidOffset);
|
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial),
|
||||||
|
RingBufferAllocator::kInvalidOffset);
|
||||||
|
|
||||||
// Reclaim the next two frames.
|
// Reclaim the next two frames.
|
||||||
allocator.Deallocate(ExecutionSerial(4));
|
allocator.Deallocate(ExecutionSerial(4));
|
||||||
|
@ -157,19 +158,22 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
||||||
//
|
//
|
||||||
|
|
||||||
// Ensure we are full.
|
// Ensure we are full.
|
||||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial), RingBufferAllocator::kInvalidOffset);
|
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial),
|
||||||
|
RingBufferAllocator::kInvalidOffset);
|
||||||
|
|
||||||
// Reclaim all.
|
// Reclaim all.
|
||||||
allocator.Deallocate(kMaxExecutionSerial);
|
allocator.Deallocate(kMaxExecutionSerial);
|
||||||
|
|
||||||
EXPECT_TRUE(allocator.Empty());
|
EXPECT_TRUE(allocator.Empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if ringbuffer sub-allocation does not overflow.
|
// Checks if ringbuffer sub-allocation does not overflow.
|
||||||
TEST(RingBufferAllocatorTests, RingBufferOverflow) {
|
TEST(RingBufferAllocatorTests, RingBufferOverflow) {
|
||||||
RingBufferAllocator allocator(std::numeric_limits<uint64_t>::max());
|
RingBufferAllocator allocator(std::numeric_limits<uint64_t>::max());
|
||||||
|
|
||||||
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(1)), 0u);
|
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(1)), 0u);
|
||||||
ASSERT_EQ(allocator.Allocate(std::numeric_limits<uint64_t>::max(), ExecutionSerial(1)),
|
ASSERT_EQ(allocator.Allocate(std::numeric_limits<uint64_t>::max(), ExecutionSerial(1)),
|
||||||
RingBufferAllocator::kInvalidOffset);
|
RingBufferAllocator::kInvalidOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -18,13 +18,13 @@
|
||||||
#include "dawn/native/SubresourceStorage.h"
|
#include "dawn/native/SubresourceStorage.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace dawn::native;
|
namespace dawn::native {
|
||||||
|
|
||||||
// A fake class that replicates the behavior of SubresourceStorage but without any compression and
|
// A fake class that replicates the behavior of SubresourceStorage but without any compression
|
||||||
// is used to compare the results of operations on SubresourceStorage against the "ground truth" of
|
// and is used to compare the results of operations on SubresourceStorage against the "ground
|
||||||
// FakeStorage.
|
// truth" of FakeStorage.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct FakeStorage {
|
struct FakeStorage {
|
||||||
FakeStorage(Aspect aspects,
|
FakeStorage(Aspect aspects,
|
||||||
uint32_t arrayLayerCount,
|
uint32_t arrayLayerCount,
|
||||||
uint32_t mipLevelCount,
|
uint32_t mipLevelCount,
|
||||||
|
@ -71,12 +71,11 @@ struct FakeStorage {
|
||||||
return level + mMipLevelCount * (layer + mArrayLayerCount * aspectIndex);
|
return level + mMipLevelCount * (layer + mArrayLayerCount * aspectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method that checks that this and real have exactly the same content. It does so via looping
|
// Method that checks that this and real have exactly the same content. It does so via
|
||||||
// on all subresources and calling Get() (hence testing Get()). It also calls Iterate()
|
// looping on all subresources and calling Get() (hence testing Get()). It also calls
|
||||||
// checking that every subresource is mentioned exactly once and that its content is correct
|
// Iterate() checking that every subresource is mentioned exactly once and that its content
|
||||||
// (hence testing Iterate()).
|
// is correct (hence testing Iterate()). Its implementation requires the RangeTracker below
|
||||||
// Its implementation requires the RangeTracker below that itself needs FakeStorage<int> so it
|
// that itself needs FakeStorage<int> so it cannot be define inline with the other methods.
|
||||||
// cannot be define inline with the other methods.
|
|
||||||
void CheckSameAs(const SubresourceStorage<T>& real);
|
void CheckSameAs(const SubresourceStorage<T>& real);
|
||||||
|
|
||||||
Aspect mAspects;
|
Aspect mAspects;
|
||||||
|
@ -84,11 +83,11 @@ struct FakeStorage {
|
||||||
uint32_t mMipLevelCount;
|
uint32_t mMipLevelCount;
|
||||||
|
|
||||||
std::vector<T> mData;
|
std::vector<T> mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Track a set of ranges that have been seen and can assert that in aggregate they make exactly
|
// Track a set of ranges that have been seen and can assert that in aggregate they make exactly
|
||||||
// a single range (and that each subresource was seen only once).
|
// a single range (and that each subresource was seen only once).
|
||||||
struct RangeTracker {
|
struct RangeTracker {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
explicit RangeTracker(const SubresourceStorage<T>& s)
|
explicit RangeTracker(const SubresourceStorage<T>& s)
|
||||||
: mTracked(s.GetAspectsForTesting(),
|
: mTracked(s.GetAspectsForTesting(),
|
||||||
|
@ -106,7 +105,8 @@ struct RangeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckTrackedExactly(const SubresourceRange& range) {
|
void CheckTrackedExactly(const SubresourceRange& range) {
|
||||||
// Check that all subresources in the range were tracked once and set the counter back to 0.
|
// Check that all subresources in the range were tracked once and set the counter back
|
||||||
|
// to 0.
|
||||||
mTracked.Update(range, [](const SubresourceRange&, uint32_t* counter) {
|
mTracked.Update(range, [](const SubresourceRange&, uint32_t* counter) {
|
||||||
ASSERT_EQ(*counter, 1u);
|
ASSERT_EQ(*counter, 1u);
|
||||||
*counter = 0;
|
*counter = 0;
|
||||||
|
@ -119,10 +119,10 @@ struct RangeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeStorage<uint32_t> mTracked;
|
FakeStorage<uint32_t> mTracked;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void FakeStorage<T>::CheckSameAs(const SubresourceStorage<T>& real) {
|
void FakeStorage<T>::CheckSameAs(const SubresourceStorage<T>& real) {
|
||||||
EXPECT_EQ(real.GetAspectsForTesting(), mAspects);
|
EXPECT_EQ(real.GetAspectsForTesting(), mAspects);
|
||||||
EXPECT_EQ(real.GetArrayLayerCountForTesting(), mArrayLayerCount);
|
EXPECT_EQ(real.GetArrayLayerCountForTesting(), mArrayLayerCount);
|
||||||
EXPECT_EQ(real.GetMipLevelCountForTesting(), mMipLevelCount);
|
EXPECT_EQ(real.GetMipLevelCountForTesting(), mMipLevelCount);
|
||||||
|
@ -154,10 +154,10 @@ void FakeStorage<T>::CheckSameAs(const SubresourceStorage<T>& real) {
|
||||||
|
|
||||||
tracker.CheckTrackedExactly(
|
tracker.CheckTrackedExactly(
|
||||||
SubresourceRange::MakeFull(mAspects, mArrayLayerCount, mMipLevelCount));
|
SubresourceRange::MakeFull(mAspects, mArrayLayerCount, mMipLevelCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void CheckAspectCompressed(const SubresourceStorage<T>& s, Aspect aspect, bool expected) {
|
void CheckAspectCompressed(const SubresourceStorage<T>& s, Aspect aspect, bool expected) {
|
||||||
ASSERT(HasOneBit(aspect));
|
ASSERT(HasOneBit(aspect));
|
||||||
|
|
||||||
uint32_t levelCount = s.GetMipLevelCountForTesting();
|
uint32_t levelCount = s.GetMipLevelCountForTesting();
|
||||||
|
@ -182,10 +182,10 @@ void CheckAspectCompressed(const SubresourceStorage<T>& s, Aspect aspect, bool e
|
||||||
ASSERT_TRUE(s.IsLayerCompressedForTesting(aspect, layer));
|
ASSERT_TRUE(s.IsLayerCompressedForTesting(aspect, layer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void CheckLayerCompressed(const SubresourceStorage<T>& s,
|
void CheckLayerCompressed(const SubresourceStorage<T>& s,
|
||||||
Aspect aspect,
|
Aspect aspect,
|
||||||
uint32_t layer,
|
uint32_t layer,
|
||||||
bool expected) {
|
bool expected) {
|
||||||
|
@ -195,26 +195,27 @@ void CheckLayerCompressed(const SubresourceStorage<T>& s,
|
||||||
|
|
||||||
bool seen = false;
|
bool seen = false;
|
||||||
s.Iterate([&](const SubresourceRange& range, const T&) {
|
s.Iterate([&](const SubresourceRange& range, const T&) {
|
||||||
if (range.aspects == aspect && range.layerCount == 1 && range.levelCount == levelCount &&
|
if (range.aspects == aspect && range.layerCount == 1 &&
|
||||||
range.baseArrayLayer == layer && range.baseMipLevel == 0) {
|
range.levelCount == levelCount && range.baseArrayLayer == layer &&
|
||||||
|
range.baseMipLevel == 0) {
|
||||||
seen = true;
|
seen = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ASSERT_EQ(seen, expected);
|
ASSERT_EQ(seen, expected);
|
||||||
ASSERT_EQ(s.IsLayerCompressedForTesting(aspect, layer), expected);
|
ASSERT_EQ(s.IsLayerCompressedForTesting(aspect, layer), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SmallData {
|
struct SmallData {
|
||||||
uint32_t value = 0xF00;
|
uint32_t value = 0xF00;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const SmallData& a, const SmallData& b) {
|
bool operator==(const SmallData& a, const SmallData& b) {
|
||||||
return a.value == b.value;
|
return a.value == b.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the default value is correctly set.
|
// Test that the default value is correctly set.
|
||||||
TEST(SubresourceStorageTest, DefaultValue) {
|
TEST(SubresourceStorageTest, DefaultValue) {
|
||||||
// Test setting no default value for a primitive type.
|
// Test setting no default value for a primitive type.
|
||||||
{
|
{
|
||||||
SubresourceStorage<int> s(Aspect::Color, 3, 5);
|
SubresourceStorage<int> s(Aspect::Color, 3, 5);
|
||||||
|
@ -249,18 +250,19 @@ TEST(SubresourceStorageTest, DefaultValue) {
|
||||||
FakeStorage<SmallData> f(Aspect::Color, 3, 5, {007u});
|
FakeStorage<SmallData> f(Aspect::Color, 3, 5, {007u});
|
||||||
f.CheckSameAs(s);
|
f.CheckSameAs(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tests for Update() all follow the same pattern of setting up a real and a fake storage then
|
// The tests for Update() all follow the same pattern of setting up a real and a fake storage
|
||||||
// performing one or multiple Update()s on them and checking:
|
// then performing one or multiple Update()s on them and checking:
|
||||||
// - They have the same content.
|
// - They have the same content.
|
||||||
// - The Update() range was correct.
|
// - The Update() range was correct.
|
||||||
// - The aspects and layers have the expected "compressed" status.
|
// - The aspects and layers have the expected "compressed" status.
|
||||||
|
|
||||||
// Calls Update both on the read storage and the fake storage but intercepts the call to updateFunc
|
// Calls Update both on the read storage and the fake storage but intercepts the call to
|
||||||
// done by the real storage to check their ranges argument aggregate to exactly the update range.
|
// updateFunc done by the real storage to check their ranges argument aggregate to exactly the
|
||||||
template <typename T, typename F>
|
// update range.
|
||||||
void CallUpdateOnBoth(SubresourceStorage<T>* s,
|
template <typename T, typename F>
|
||||||
|
void CallUpdateOnBoth(SubresourceStorage<T>* s,
|
||||||
FakeStorage<T>* f,
|
FakeStorage<T>* f,
|
||||||
const SubresourceRange& range,
|
const SubresourceRange& range,
|
||||||
F&& updateFunc) {
|
F&& updateFunc) {
|
||||||
|
@ -274,10 +276,10 @@ void CallUpdateOnBoth(SubresourceStorage<T>* s,
|
||||||
|
|
||||||
tracker.CheckTrackedExactly(range);
|
tracker.CheckTrackedExactly(range);
|
||||||
f->CheckSameAs(*s);
|
f->CheckSameAs(*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating a single subresource on a single-aspect storage.
|
// Test updating a single subresource on a single-aspect storage.
|
||||||
TEST(SubresourceStorageTest, SingleSubresourceUpdateSingleAspect) {
|
TEST(SubresourceStorageTest, SingleSubresourceUpdateSingleAspect) {
|
||||||
SubresourceStorage<int> s(Aspect::Color, 5, 7);
|
SubresourceStorage<int> s(Aspect::Color, 5, 7);
|
||||||
FakeStorage<int> f(Aspect::Color, 5, 7);
|
FakeStorage<int> f(Aspect::Color, 5, 7);
|
||||||
|
|
||||||
|
@ -289,10 +291,10 @@ TEST(SubresourceStorageTest, SingleSubresourceUpdateSingleAspect) {
|
||||||
CheckLayerCompressed(s, Aspect::Color, 2, true);
|
CheckLayerCompressed(s, Aspect::Color, 2, true);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 3, false);
|
CheckLayerCompressed(s, Aspect::Color, 3, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 4, true);
|
CheckLayerCompressed(s, Aspect::Color, 4, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating a single subresource on a multi-aspect storage.
|
// Test updating a single subresource on a multi-aspect storage.
|
||||||
TEST(SubresourceStorageTest, SingleSubresourceUpdateMultiAspect) {
|
TEST(SubresourceStorageTest, SingleSubresourceUpdateMultiAspect) {
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, 5, 3);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, 5, 3);
|
||||||
FakeStorage<int> f(Aspect::Depth | Aspect::Stencil, 5, 3);
|
FakeStorage<int> f(Aspect::Depth | Aspect::Stencil, 5, 3);
|
||||||
|
|
||||||
|
@ -304,10 +306,10 @@ TEST(SubresourceStorageTest, SingleSubresourceUpdateMultiAspect) {
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 0, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 0, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 1, false);
|
CheckLayerCompressed(s, Aspect::Stencil, 1, false);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating as a stipple pattern on one of two aspects then updating it completely.
|
// Test updating as a stipple pattern on one of two aspects then updating it completely.
|
||||||
TEST(SubresourceStorageTest, UpdateStipple) {
|
TEST(SubresourceStorageTest, UpdateStipple) {
|
||||||
const uint32_t kLayers = 10;
|
const uint32_t kLayers = 10;
|
||||||
const uint32_t kLevels = 7;
|
const uint32_t kLevels = 7;
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
||||||
|
@ -317,7 +319,8 @@ TEST(SubresourceStorageTest, UpdateStipple) {
|
||||||
for (uint32_t layer = 0; layer < kLayers; layer++) {
|
for (uint32_t layer = 0; layer < kLayers; layer++) {
|
||||||
for (uint32_t level = 0; level < kLevels; level++) {
|
for (uint32_t level = 0; level < kLevels; level++) {
|
||||||
if ((layer + level) % 2 == 0) {
|
if ((layer + level) % 2 == 0) {
|
||||||
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Depth, layer, level);
|
SubresourceRange range =
|
||||||
|
SubresourceRange::MakeSingle(Aspect::Depth, layer, level);
|
||||||
CallUpdateOnBoth(&s, &f, range,
|
CallUpdateOnBoth(&s, &f, range,
|
||||||
[](const SubresourceRange&, int* data) { *data += 17; });
|
[](const SubresourceRange&, int* data) { *data += 17; });
|
||||||
}
|
}
|
||||||
|
@ -335,18 +338,19 @@ TEST(SubresourceStorageTest, UpdateStipple) {
|
||||||
{
|
{
|
||||||
SubresourceRange fullRange =
|
SubresourceRange fullRange =
|
||||||
SubresourceRange::MakeFull(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
SubresourceRange::MakeFull(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
||||||
CallUpdateOnBoth(&s, &f, fullRange, [](const SubresourceRange&, int* data) { *data = 31; });
|
CallUpdateOnBoth(&s, &f, fullRange,
|
||||||
|
[](const SubresourceRange&, int* data) { *data = 31; });
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckAspectCompressed(s, Aspect::Depth, true);
|
CheckAspectCompressed(s, Aspect::Depth, true);
|
||||||
CheckAspectCompressed(s, Aspect::Stencil, true);
|
CheckAspectCompressed(s, Aspect::Stencil, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating as a crossing band pattern:
|
// Test updating as a crossing band pattern:
|
||||||
// - The first band is full layers [2, 3] on both aspects
|
// - The first band is full layers [2, 3] on both aspects
|
||||||
// - The second band is full mips [5, 6] on one aspect.
|
// - The second band is full mips [5, 6] on one aspect.
|
||||||
// Then updating completely.
|
// Then updating completely.
|
||||||
TEST(SubresourceStorageTest, UpdateTwoBand) {
|
TEST(SubresourceStorageTest, UpdateTwoBand) {
|
||||||
const uint32_t kLayers = 5;
|
const uint32_t kLayers = 5;
|
||||||
const uint32_t kLevels = 9;
|
const uint32_t kLevels = 9;
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
||||||
|
@ -385,12 +389,12 @@ TEST(SubresourceStorageTest, UpdateTwoBand) {
|
||||||
|
|
||||||
CheckAspectCompressed(s, Aspect::Depth, false);
|
CheckAspectCompressed(s, Aspect::Depth, false);
|
||||||
CheckAspectCompressed(s, Aspect::Stencil, false);
|
CheckAspectCompressed(s, Aspect::Stencil, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test updating with extremal subresources
|
// Test updating with extremal subresources
|
||||||
// - Then half of the array layers in full.
|
// - Then half of the array layers in full.
|
||||||
// - Then updating completely.
|
// - Then updating completely.
|
||||||
TEST(SubresourceStorageTest, UpdateExtremas) {
|
TEST(SubresourceStorageTest, UpdateExtremas) {
|
||||||
const uint32_t kLayers = 6;
|
const uint32_t kLayers = 6;
|
||||||
const uint32_t kLevels = 4;
|
const uint32_t kLevels = 4;
|
||||||
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels);
|
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels);
|
||||||
|
@ -414,7 +418,8 @@ TEST(SubresourceStorageTest, UpdateExtremas) {
|
||||||
// Update half of the layers in full with constant values. Some recompression should happen.
|
// Update half of the layers in full with constant values. Some recompression should happen.
|
||||||
{
|
{
|
||||||
SubresourceRange range(Aspect::Color, {0, kLayers / 2}, {0, kLevels});
|
SubresourceRange range(Aspect::Color, {0, kLayers / 2}, {0, kLevels});
|
||||||
CallUpdateOnBoth(&s, &f, range, [](const SubresourceRange&, int* data) { *data = 123; });
|
CallUpdateOnBoth(&s, &f, range,
|
||||||
|
[](const SubresourceRange&, int* data) { *data = 123; });
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckLayerCompressed(s, Aspect::Color, 0, true);
|
CheckLayerCompressed(s, Aspect::Color, 0, true);
|
||||||
|
@ -423,17 +428,19 @@ TEST(SubresourceStorageTest, UpdateExtremas) {
|
||||||
|
|
||||||
// Update completely. Recompression should happen!
|
// Update completely. Recompression should happen!
|
||||||
{
|
{
|
||||||
SubresourceRange fullRange = SubresourceRange::MakeFull(Aspect::Color, kLayers, kLevels);
|
SubresourceRange fullRange =
|
||||||
CallUpdateOnBoth(&s, &f, fullRange, [](const SubresourceRange&, int* data) { *data = 35; });
|
SubresourceRange::MakeFull(Aspect::Color, kLayers, kLevels);
|
||||||
|
CallUpdateOnBoth(&s, &f, fullRange,
|
||||||
|
[](const SubresourceRange&, int* data) { *data = 35; });
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckAspectCompressed(s, Aspect::Color, true);
|
CheckAspectCompressed(s, Aspect::Color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A regression test for an issue found while reworking the implementation where RecompressAspect
|
// A regression test for an issue found while reworking the implementation where
|
||||||
// didn't correctly check that each each layer was compressed but only that their 0th value was
|
// RecompressAspect didn't correctly check that each each layer was compressed but only that
|
||||||
// the same.
|
// their 0th value was the same.
|
||||||
TEST(SubresourceStorageTest, UpdateLevel0sHappenToMatch) {
|
TEST(SubresourceStorageTest, UpdateLevel0sHappenToMatch) {
|
||||||
SubresourceStorage<int> s(Aspect::Color, 2, 2);
|
SubresourceStorage<int> s(Aspect::Color, 2, 2);
|
||||||
FakeStorage<int> f(Aspect::Color, 2, 2);
|
FakeStorage<int> f(Aspect::Color, 2, 2);
|
||||||
|
|
||||||
|
@ -456,14 +463,14 @@ TEST(SubresourceStorageTest, UpdateLevel0sHappenToMatch) {
|
||||||
CheckAspectCompressed(s, Aspect::Color, false);
|
CheckAspectCompressed(s, Aspect::Color, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 1, false);
|
CheckLayerCompressed(s, Aspect::Color, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tests for Merge() all follow the same as the Update() tests except that they use Update()
|
// The tests for Merge() all follow the same as the Update() tests except that they use Update()
|
||||||
// to set up the test storages.
|
// to set up the test storages.
|
||||||
|
|
||||||
// Similar to CallUpdateOnBoth but for Merge
|
// Similar to CallUpdateOnBoth but for Merge
|
||||||
template <typename T, typename U, typename F>
|
template <typename T, typename U, typename F>
|
||||||
void CallMergeOnBoth(SubresourceStorage<T>* s,
|
void CallMergeOnBoth(SubresourceStorage<T>* s,
|
||||||
FakeStorage<T>* f,
|
FakeStorage<T>* f,
|
||||||
const SubresourceStorage<U>& other,
|
const SubresourceStorage<U>& other,
|
||||||
F&& mergeFunc) {
|
F&& mergeFunc) {
|
||||||
|
@ -478,10 +485,10 @@ void CallMergeOnBoth(SubresourceStorage<T>* s,
|
||||||
tracker.CheckTrackedExactly(
|
tracker.CheckTrackedExactly(
|
||||||
SubresourceRange::MakeFull(f->mAspects, f->mArrayLayerCount, f->mMipLevelCount));
|
SubresourceRange::MakeFull(f->mAspects, f->mArrayLayerCount, f->mMipLevelCount));
|
||||||
f->CheckSameAs(*s);
|
f->CheckSameAs(*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test merging two fully compressed single-aspect resources.
|
// Test merging two fully compressed single-aspect resources.
|
||||||
TEST(SubresourceStorageTest, MergeFullWithFullSingleAspect) {
|
TEST(SubresourceStorageTest, MergeFullWithFullSingleAspect) {
|
||||||
SubresourceStorage<int> s(Aspect::Color, 4, 6);
|
SubresourceStorage<int> s(Aspect::Color, 4, 6);
|
||||||
FakeStorage<int> f(Aspect::Color, 4, 6);
|
FakeStorage<int> f(Aspect::Color, 4, 6);
|
||||||
|
|
||||||
|
@ -494,10 +501,10 @@ TEST(SubresourceStorageTest, MergeFullWithFullSingleAspect) {
|
||||||
});
|
});
|
||||||
|
|
||||||
CheckAspectCompressed(s, Aspect::Color, true);
|
CheckAspectCompressed(s, Aspect::Color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test merging two fully compressed multi-aspect resources.
|
// Test merging two fully compressed multi-aspect resources.
|
||||||
TEST(SubresourceStorageTest, MergeFullWithFullMultiAspect) {
|
TEST(SubresourceStorageTest, MergeFullWithFullMultiAspect) {
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, 6, 7);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, 6, 7);
|
||||||
FakeStorage<int> f(Aspect::Depth | Aspect::Stencil, 6, 7);
|
FakeStorage<int> f(Aspect::Depth | Aspect::Stencil, 6, 7);
|
||||||
|
|
||||||
|
@ -511,13 +518,13 @@ TEST(SubresourceStorageTest, MergeFullWithFullMultiAspect) {
|
||||||
|
|
||||||
CheckAspectCompressed(s, Aspect::Depth, true);
|
CheckAspectCompressed(s, Aspect::Depth, true);
|
||||||
CheckAspectCompressed(s, Aspect::Stencil, true);
|
CheckAspectCompressed(s, Aspect::Stencil, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test merging a fully compressed resource in a resource with the "cross band" pattern.
|
// Test merging a fully compressed resource in a resource with the "cross band" pattern.
|
||||||
// - The first band is full layers [2, 3] on both aspects
|
// - The first band is full layers [2, 3] on both aspects
|
||||||
// - The second band is full mips [5, 6] on one aspect.
|
// - The second band is full mips [5, 6] on one aspect.
|
||||||
// This provides coverage of using a single piece of data from `other` to update all of `s`
|
// This provides coverage of using a single piece of data from `other` to update all of `s`
|
||||||
TEST(SubresourceStorageTest, MergeFullInTwoBand) {
|
TEST(SubresourceStorageTest, MergeFullInTwoBand) {
|
||||||
const uint32_t kLayers = 5;
|
const uint32_t kLayers = 5;
|
||||||
const uint32_t kLevels = 9;
|
const uint32_t kLevels = 9;
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels);
|
||||||
|
@ -544,17 +551,17 @@ TEST(SubresourceStorageTest, MergeFullInTwoBand) {
|
||||||
CheckLayerCompressed(s, Aspect::Depth, 3, false);
|
CheckLayerCompressed(s, Aspect::Depth, 3, false);
|
||||||
CheckLayerCompressed(s, Aspect::Depth, 4, false);
|
CheckLayerCompressed(s, Aspect::Depth, 4, false);
|
||||||
|
|
||||||
// Stencil is decompressed but all its layers are still compressed because there wasn't the mip
|
// Stencil is decompressed but all its layers are still compressed because there wasn't the
|
||||||
// band.
|
// mip band.
|
||||||
CheckAspectCompressed(s, Aspect::Stencil, false);
|
CheckAspectCompressed(s, Aspect::Stencil, false);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 1, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 1, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 3, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 3, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 4, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 4, true);
|
||||||
}
|
}
|
||||||
// Test the reverse, mergign two-bands in a full resource. This provides coverage for decompressing
|
// Test the reverse, mergign two-bands in a full resource. This provides coverage for
|
||||||
// aspects / and partilly layers to match the compression of `other`
|
// decompressing aspects / and partilly layers to match the compression of `other`
|
||||||
TEST(SubresourceStorageTest, MergeTwoBandInFull) {
|
TEST(SubresourceStorageTest, MergeTwoBandInFull) {
|
||||||
const uint32_t kLayers = 5;
|
const uint32_t kLayers = 5;
|
||||||
const uint32_t kLevels = 9;
|
const uint32_t kLevels = 9;
|
||||||
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels, 75);
|
SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels, 75);
|
||||||
|
@ -581,18 +588,18 @@ TEST(SubresourceStorageTest, MergeTwoBandInFull) {
|
||||||
CheckLayerCompressed(s, Aspect::Depth, 3, false);
|
CheckLayerCompressed(s, Aspect::Depth, 3, false);
|
||||||
CheckLayerCompressed(s, Aspect::Depth, 4, false);
|
CheckLayerCompressed(s, Aspect::Depth, 4, false);
|
||||||
|
|
||||||
// Stencil is decompressed but all its layers are still compressed because there wasn't the mip
|
// Stencil is decompressed but all its layers are still compressed because there wasn't the
|
||||||
// band.
|
// mip band.
|
||||||
CheckAspectCompressed(s, Aspect::Stencil, false);
|
CheckAspectCompressed(s, Aspect::Stencil, false);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 1, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 1, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 2, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 3, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 3, true);
|
||||||
CheckLayerCompressed(s, Aspect::Stencil, 4, true);
|
CheckLayerCompressed(s, Aspect::Stencil, 4, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test merging storage with a layer band in a stipple patterned storage. This provide coverage
|
// Test merging storage with a layer band in a stipple patterned storage. This provide coverage
|
||||||
// for the code path that uses the same layer data for other multiple times.
|
// for the code path that uses the same layer data for other multiple times.
|
||||||
TEST(SubresourceStorageTest, MergeLayerBandInStipple) {
|
TEST(SubresourceStorageTest, MergeLayerBandInStipple) {
|
||||||
const uint32_t kLayers = 3;
|
const uint32_t kLayers = 3;
|
||||||
const uint32_t kLevels = 5;
|
const uint32_t kLevels = 5;
|
||||||
|
|
||||||
|
@ -603,7 +610,8 @@ TEST(SubresourceStorageTest, MergeLayerBandInStipple) {
|
||||||
for (uint32_t layer = 0; layer < kLayers; layer++) {
|
for (uint32_t layer = 0; layer < kLayers; layer++) {
|
||||||
for (uint32_t level = 0; level < kLevels; level++) {
|
for (uint32_t level = 0; level < kLevels; level++) {
|
||||||
if ((layer + level) % 2 == 0) {
|
if ((layer + level) % 2 == 0) {
|
||||||
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Color, layer, level);
|
SubresourceRange range =
|
||||||
|
SubresourceRange::MakeSingle(Aspect::Color, layer, level);
|
||||||
CallUpdateOnBoth(&s, &f, range,
|
CallUpdateOnBoth(&s, &f, range,
|
||||||
[](const SubresourceRange&, int* data) { *data += 17; });
|
[](const SubresourceRange&, int* data) { *data += 17; });
|
||||||
}
|
}
|
||||||
|
@ -622,10 +630,10 @@ TEST(SubresourceStorageTest, MergeLayerBandInStipple) {
|
||||||
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 1, false);
|
CheckLayerCompressed(s, Aspect::Color, 1, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 2, false);
|
CheckLayerCompressed(s, Aspect::Color, 2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test for a missing check that layer 0 is compressed when recompressing.
|
// Regression test for a missing check that layer 0 is compressed when recompressing.
|
||||||
TEST(SubresourceStorageTest, Layer0NotCompressedBlocksAspectRecompression) {
|
TEST(SubresourceStorageTest, Layer0NotCompressedBlocksAspectRecompression) {
|
||||||
const uint32_t kLayers = 2;
|
const uint32_t kLayers = 2;
|
||||||
const uint32_t kLevels = 2;
|
const uint32_t kLevels = 2;
|
||||||
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels);
|
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels);
|
||||||
|
@ -634,7 +642,8 @@ TEST(SubresourceStorageTest, Layer0NotCompressedBlocksAspectRecompression) {
|
||||||
// Set up s with zeros except (0, 1) which is garbage.
|
// Set up s with zeros except (0, 1) which is garbage.
|
||||||
{
|
{
|
||||||
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Color, 0, 1);
|
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Color, 0, 1);
|
||||||
CallUpdateOnBoth(&s, &f, range, [](const SubresourceRange&, int* data) { *data += 0xABC; });
|
CallUpdateOnBoth(&s, &f, range,
|
||||||
|
[](const SubresourceRange&, int* data) { *data += 0xABC; });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other is 2x2 of zeroes
|
// Other is 2x2 of zeroes
|
||||||
|
@ -646,10 +655,10 @@ TEST(SubresourceStorageTest, Layer0NotCompressedBlocksAspectRecompression) {
|
||||||
// The Color aspect should not have been recompressed.
|
// The Color aspect should not have been recompressed.
|
||||||
CheckAspectCompressed(s, Aspect::Color, false);
|
CheckAspectCompressed(s, Aspect::Color, false);
|
||||||
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
CheckLayerCompressed(s, Aspect::Color, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test for aspect decompression not copying to layer 0
|
// Regression test for aspect decompression not copying to layer 0
|
||||||
TEST(SubresourceStorageTest, AspectDecompressionUpdatesLayer0) {
|
TEST(SubresourceStorageTest, AspectDecompressionUpdatesLayer0) {
|
||||||
const uint32_t kLayers = 2;
|
const uint32_t kLayers = 2;
|
||||||
const uint32_t kLevels = 2;
|
const uint32_t kLevels = 2;
|
||||||
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels, 3);
|
SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels, 3);
|
||||||
|
@ -658,20 +667,23 @@ TEST(SubresourceStorageTest, AspectDecompressionUpdatesLayer0) {
|
||||||
// Cause decompression by writing to a single subresource.
|
// Cause decompression by writing to a single subresource.
|
||||||
{
|
{
|
||||||
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Color, 1, 1);
|
SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Color, 1, 1);
|
||||||
CallUpdateOnBoth(&s, &f, range, [](const SubresourceRange&, int* data) { *data += 0xABC; });
|
CallUpdateOnBoth(&s, &f, range,
|
||||||
|
[](const SubresourceRange&, int* data) { *data += 0xABC; });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the aspect's value of 3 was correctly decompressed in layer 0.
|
// Check that the aspect's value of 3 was correctly decompressed in layer 0.
|
||||||
CheckLayerCompressed(s, Aspect::Color, 0, true);
|
CheckLayerCompressed(s, Aspect::Color, 0, true);
|
||||||
EXPECT_EQ(3, s.Get(Aspect::Color, 0, 0));
|
EXPECT_EQ(3, s.Get(Aspect::Color, 0, 0));
|
||||||
EXPECT_EQ(3, s.Get(Aspect::Color, 0, 1));
|
EXPECT_EQ(3, s.Get(Aspect::Color, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bugs found while testing:
|
// Bugs found while testing:
|
||||||
// - mLayersCompressed not initialized to true.
|
// - mLayersCompressed not initialized to true.
|
||||||
// - DecompressLayer setting Compressed to true instead of false.
|
// - DecompressLayer setting Compressed to true instead of false.
|
||||||
// - Get() checking for !compressed instead of compressed for the early exit.
|
// - Get() checking for !compressed instead of compressed for the early exit.
|
||||||
// - ASSERT in RecompressLayers was inverted.
|
// - ASSERT in RecompressLayers was inverted.
|
||||||
// - Two != being converted to == during a rework.
|
// - Two != being converted to == during a rework.
|
||||||
// - (with ASSERT) that RecompressAspect didn't check that aspect 0 was compressed.
|
// - (with ASSERT) that RecompressAspect didn't check that aspect 0 was compressed.
|
||||||
// - Missing decompression of layer 0 after introducing mInlineAspectData.
|
// - Missing decompression of layer 0 after introducing mInlineAspectData.
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
// Make our own Base - Backend object pair, reusing the AdapterBase name
|
// Make our own Base - Backend object pair, reusing the AdapterBase name
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
class AdapterBase : public RefCounted {};
|
class AdapterBase : public RefCounted {};
|
||||||
} // namespace dawn::native
|
|
||||||
|
|
||||||
using namespace dawn::native;
|
|
||||||
|
|
||||||
class MyAdapter : public AdapterBase {};
|
class MyAdapter : public AdapterBase {};
|
||||||
|
|
||||||
|
@ -85,3 +82,5 @@ TEST(ToBackend, Ref) {
|
||||||
adapter->Release();
|
adapter->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -24,9 +24,8 @@
|
||||||
#include "dawn/webgpu_cpp_print.h"
|
#include "dawn/webgpu_cpp_print.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace dawn::native::d3d12;
|
namespace dawn::native::d3d12 {
|
||||||
|
namespace {
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct TextureSpec {
|
struct TextureSpec {
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
|
@ -61,11 +60,12 @@ namespace {
|
||||||
// If there are multiple layers, 2D texture splitter actually splits each layer
|
// If there are multiple layers, 2D texture splitter actually splits each layer
|
||||||
// independently. See the details in Compute2DTextureCopySplits(). As a result,
|
// independently. See the details in Compute2DTextureCopySplits(). As a result,
|
||||||
// if we simply expand a copy region generated by 2D texture splitter to all
|
// if we simply expand a copy region generated by 2D texture splitter to all
|
||||||
// layers, the copy region might be OOB. But that is not the approach that the current
|
// layers, the copy region might be OOB. But that is not the approach that the
|
||||||
// 2D texture splitter is doing, although Compute2DTextureCopySubresource forwards
|
// current 2D texture splitter is doing, although Compute2DTextureCopySubresource
|
||||||
// "copySize.depthOrArrayLayers" to the copy region it generated. So skip the test
|
// forwards "copySize.depthOrArrayLayers" to the copy region it generated. So skip
|
||||||
// below for 2D textures with multiple layers.
|
// the test below for 2D textures with multiple layers.
|
||||||
if (textureSpec.depthOrArrayLayers <= 1 || dimension == wgpu::TextureDimension::e3D) {
|
if (textureSpec.depthOrArrayLayers <= 1 ||
|
||||||
|
dimension == wgpu::TextureDimension::e3D) {
|
||||||
uint32_t widthInBlocks = textureSpec.width / textureSpec.blockWidth;
|
uint32_t widthInBlocks = textureSpec.width / textureSpec.blockWidth;
|
||||||
uint32_t heightInBlocks = textureSpec.height / textureSpec.blockHeight;
|
uint32_t heightInBlocks = textureSpec.height / textureSpec.blockHeight;
|
||||||
uint64_t minimumRequiredBufferSize =
|
uint64_t minimumRequiredBufferSize =
|
||||||
|
@ -75,8 +75,9 @@ namespace {
|
||||||
textureSpec.depthOrArrayLayers,
|
textureSpec.depthOrArrayLayers,
|
||||||
textureSpec.texelBlockSizeInBytes);
|
textureSpec.texelBlockSizeInBytes);
|
||||||
|
|
||||||
// The last pixel (buffer footprint) of each copy region depends on its bufferOffset
|
// The last pixel (buffer footprint) of each copy region depends on its
|
||||||
// and copySize. It is not the last pixel where the bufferSize ends.
|
// bufferOffset and copySize. It is not the last pixel where the bufferSize
|
||||||
|
// ends.
|
||||||
ASSERT_EQ(copy.bufferOffset.x % textureSpec.blockWidth, 0u);
|
ASSERT_EQ(copy.bufferOffset.x % textureSpec.blockWidth, 0u);
|
||||||
ASSERT_EQ(copy.copySize.width % textureSpec.blockWidth, 0u);
|
ASSERT_EQ(copy.copySize.width % textureSpec.blockWidth, 0u);
|
||||||
uint32_t footprintWidth = copy.bufferOffset.x + copy.copySize.width;
|
uint32_t footprintWidth = copy.bufferOffset.x + copy.copySize.width;
|
||||||
|
@ -96,8 +97,8 @@ namespace {
|
||||||
copy.bufferSize.depthOrArrayLayers,
|
copy.bufferSize.depthOrArrayLayers,
|
||||||
textureSpec.texelBlockSizeInBytes);
|
textureSpec.texelBlockSizeInBytes);
|
||||||
|
|
||||||
// The buffer footprint of each copy region should not exceed the minimum required
|
// The buffer footprint of each copy region should not exceed the minimum
|
||||||
// buffer size. Otherwise, pixels accessed by copy may be OOB.
|
// required buffer size. Otherwise, pixels accessed by copy may be OOB.
|
||||||
ASSERT_LE(bufferSizeForFootprint, minimumRequiredBufferSize);
|
ASSERT_LE(bufferSizeForFootprint, minimumRequiredBufferSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,8 +107,8 @@ namespace {
|
||||||
// Check that the offset is aligned
|
// Check that the offset is aligned
|
||||||
void ValidateOffset(const TextureCopySubresource& copySplit) {
|
void ValidateOffset(const TextureCopySubresource& copySplit) {
|
||||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(Align(copySplit.copies[i].alignedOffset,
|
||||||
Align(copySplit.copies[i].alignedOffset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
|
D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
|
||||||
copySplit.copies[i].alignedOffset);
|
copySplit.copies[i].alignedOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,11 +128,11 @@ namespace {
|
||||||
// [textureOffset.x, textureOffset.x + copySize.width - 1] and both ends are
|
// [textureOffset.x, textureOffset.x + copySize.width - 1] and both ends are
|
||||||
// included.
|
// included.
|
||||||
bool overlapX = InclusiveRangesOverlap(
|
bool overlapX = InclusiveRangesOverlap(
|
||||||
a.textureOffset.x, a.textureOffset.x + a.copySize.width - 1, b.textureOffset.x,
|
a.textureOffset.x, a.textureOffset.x + a.copySize.width - 1,
|
||||||
b.textureOffset.x + b.copySize.width - 1);
|
b.textureOffset.x, b.textureOffset.x + b.copySize.width - 1);
|
||||||
bool overlapY = InclusiveRangesOverlap(
|
bool overlapY = InclusiveRangesOverlap(
|
||||||
a.textureOffset.y, a.textureOffset.y + a.copySize.height - 1, b.textureOffset.y,
|
a.textureOffset.y, a.textureOffset.y + a.copySize.height - 1,
|
||||||
b.textureOffset.y + b.copySize.height - 1);
|
b.textureOffset.y, b.textureOffset.y + b.copySize.height - 1);
|
||||||
bool overlapZ = InclusiveRangesOverlap(
|
bool overlapZ = InclusiveRangesOverlap(
|
||||||
a.textureOffset.z, a.textureOffset.z + a.copySize.depthOrArrayLayers - 1,
|
a.textureOffset.z, a.textureOffset.z + a.copySize.depthOrArrayLayers - 1,
|
||||||
b.textureOffset.z, b.textureOffset.z + b.copySize.depthOrArrayLayers - 1);
|
b.textureOffset.z, b.textureOffset.z + b.copySize.depthOrArrayLayers - 1);
|
||||||
|
@ -148,10 +149,12 @@ namespace {
|
||||||
uint32_t minX = copySplit.copies[0].textureOffset.x;
|
uint32_t minX = copySplit.copies[0].textureOffset.x;
|
||||||
uint32_t minY = copySplit.copies[0].textureOffset.y;
|
uint32_t minY = copySplit.copies[0].textureOffset.y;
|
||||||
uint32_t minZ = copySplit.copies[0].textureOffset.z;
|
uint32_t minZ = copySplit.copies[0].textureOffset.z;
|
||||||
uint32_t maxX = copySplit.copies[0].textureOffset.x + copySplit.copies[0].copySize.width;
|
uint32_t maxX =
|
||||||
uint32_t maxY = copySplit.copies[0].textureOffset.y + copySplit.copies[0].copySize.height;
|
copySplit.copies[0].textureOffset.x + copySplit.copies[0].copySize.width;
|
||||||
uint32_t maxZ =
|
uint32_t maxY =
|
||||||
copySplit.copies[0].textureOffset.z + copySplit.copies[0].copySize.depthOrArrayLayers;
|
copySplit.copies[0].textureOffset.y + copySplit.copies[0].copySize.height;
|
||||||
|
uint32_t maxZ = copySplit.copies[0].textureOffset.z +
|
||||||
|
copySplit.copies[0].copySize.depthOrArrayLayers;
|
||||||
|
|
||||||
for (uint32_t i = 1; i < copySplit.count; ++i) {
|
for (uint32_t i = 1; i < copySplit.count; ++i) {
|
||||||
const auto& copy = copySplit.copies[i];
|
const auto& copy = copySplit.copies[i];
|
||||||
|
@ -183,7 +186,8 @@ namespace {
|
||||||
ASSERT_GT(copiedPixels, 0u);
|
ASSERT_GT(copiedPixels, 0u);
|
||||||
count += copiedPixels;
|
count += copiedPixels;
|
||||||
}
|
}
|
||||||
ASSERT_EQ(count, textureSpec.width * textureSpec.height * textureSpec.depthOrArrayLayers);
|
ASSERT_EQ(count,
|
||||||
|
textureSpec.width * textureSpec.height * textureSpec.depthOrArrayLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that every buffer offset is at the correct pixel location
|
// Check that every buffer offset is at the correct pixel location
|
||||||
|
@ -246,7 +250,8 @@ namespace {
|
||||||
os << "TextureSpec("
|
os << "TextureSpec("
|
||||||
<< "[(" << textureSpec.x << ", " << textureSpec.y << ", " << textureSpec.z << "), ("
|
<< "[(" << textureSpec.x << ", " << textureSpec.y << ", " << textureSpec.z << "), ("
|
||||||
<< textureSpec.width << ", " << textureSpec.height << ", "
|
<< textureSpec.width << ", " << textureSpec.height << ", "
|
||||||
<< textureSpec.depthOrArrayLayers << ")], " << textureSpec.texelBlockSizeInBytes << ")";
|
<< textureSpec.depthOrArrayLayers << ")], " << textureSpec.texelBlockSizeInBytes
|
||||||
|
<< ")";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,10 +269,10 @@ namespace {
|
||||||
<< copy.textureOffset.y << ", " << copy.textureOffset.z << "), size ("
|
<< copy.textureOffset.y << ", " << copy.textureOffset.z << "), size ("
|
||||||
<< copy.copySize.width << ", " << copy.copySize.height << ", "
|
<< copy.copySize.width << ", " << copy.copySize.height << ", "
|
||||||
<< copy.copySize.depthOrArrayLayers << ")" << std::endl;
|
<< copy.copySize.depthOrArrayLayers << ")" << std::endl;
|
||||||
os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", " << copy.bufferOffset.y
|
os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", "
|
||||||
<< ", " << copy.bufferOffset.z << "), footprint (" << copy.bufferSize.width << ", "
|
<< copy.bufferOffset.y << ", " << copy.bufferOffset.z << "), footprint ("
|
||||||
<< copy.bufferSize.height << ", " << copy.bufferSize.depthOrArrayLayers << ")"
|
<< copy.bufferSize.width << ", " << copy.bufferSize.height << ", "
|
||||||
<< std::endl;
|
<< copy.bufferSize.depthOrArrayLayers << ")" << std::endl;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@ -320,8 +325,8 @@ namespace {
|
||||||
{64, 48, 16, 1024, 1024, 1, 16, 4, 4},
|
{64, 48, 16, 1024, 1024, 1, 16, 4, 4},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define base buffer sizes to work with: some offsets aligned, some unaligned. bytesPerRow is
|
// Define base buffer sizes to work with: some offsets aligned, some unaligned. bytesPerRow
|
||||||
// the minimum required
|
// is the minimum required
|
||||||
std::array<BufferSpec, 15> BaseBufferSpecs(const TextureSpec& textureSpec) {
|
std::array<BufferSpec, 15> BaseBufferSpecs(const TextureSpec& textureSpec) {
|
||||||
uint32_t bytesPerRow = Align(textureSpec.texelBlockSizeInBytes * textureSpec.width,
|
uint32_t bytesPerRow = Align(textureSpec.texelBlockSizeInBytes * textureSpec.width,
|
||||||
kTextureBytesPerRowAlignment);
|
kTextureBytesPerRowAlignment);
|
||||||
|
@ -367,14 +372,15 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a list of values to set properties in the spec structs
|
// 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
|
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
|
16, 32, 64, 128, 256, 512, 1024, 2048, // powers of 2
|
||||||
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
|
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
|
||||||
17, 33, 65, 129, 257, 513, 1025, 2049};
|
17, 33, 65, 129, 257, 513, 1025, 2049};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class CopySplitTest : public testing::TestWithParam<wgpu::TextureDimension> {
|
class CopySplitTest : public testing::TestWithParam<wgpu::TextureDimension> {
|
||||||
protected:
|
protected:
|
||||||
void DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
|
void DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
|
||||||
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
||||||
|
@ -416,17 +422,17 @@ class CopySplitTest : public testing::TestWithParam<wgpu::TextureDimension> {
|
||||||
FAIL() << message.str();
|
FAIL() << message.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_P(CopySplitTest, General) {
|
TEST_P(CopySplitTest, General) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||||
DoTest(textureSpec, bufferSpec);
|
DoTest(textureSpec, bufferSpec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, TextureWidth) {
|
TEST_P(CopySplitTest, TextureWidth) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (uint32_t val : kCheckValues) {
|
for (uint32_t val : kCheckValues) {
|
||||||
if (val % textureSpec.blockWidth != 0) {
|
if (val % textureSpec.blockWidth != 0) {
|
||||||
|
@ -438,9 +444,9 @@ TEST_P(CopySplitTest, TextureWidth) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, TextureHeight) {
|
TEST_P(CopySplitTest, TextureHeight) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (uint32_t val : kCheckValues) {
|
for (uint32_t val : kCheckValues) {
|
||||||
if (val % textureSpec.blockHeight != 0) {
|
if (val % textureSpec.blockHeight != 0) {
|
||||||
|
@ -452,9 +458,9 @@ TEST_P(CopySplitTest, TextureHeight) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, TextureX) {
|
TEST_P(CopySplitTest, TextureX) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (uint32_t val : kCheckValues) {
|
for (uint32_t val : kCheckValues) {
|
||||||
textureSpec.x = val;
|
textureSpec.x = val;
|
||||||
|
@ -463,9 +469,9 @@ TEST_P(CopySplitTest, TextureX) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, TextureY) {
|
TEST_P(CopySplitTest, TextureY) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (uint32_t val : kCheckValues) {
|
for (uint32_t val : kCheckValues) {
|
||||||
textureSpec.y = val;
|
textureSpec.y = val;
|
||||||
|
@ -474,9 +480,9 @@ TEST_P(CopySplitTest, TextureY) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, TexelSize) {
|
TEST_P(CopySplitTest, TexelSize) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (uint32_t texelSize : {4, 8, 16, 32, 64}) {
|
for (uint32_t texelSize : {4, 8, 16, 32, 64}) {
|
||||||
textureSpec.texelBlockSizeInBytes = texelSize;
|
textureSpec.texelBlockSizeInBytes = texelSize;
|
||||||
|
@ -485,9 +491,9 @@ TEST_P(CopySplitTest, TexelSize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, BufferOffset) {
|
TEST_P(CopySplitTest, BufferOffset) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||||
for (uint32_t val : kCheckValues) {
|
for (uint32_t val : kCheckValues) {
|
||||||
|
@ -497,9 +503,9 @@ TEST_P(CopySplitTest, BufferOffset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, RowPitch) {
|
TEST_P(CopySplitTest, RowPitch) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||||
uint32_t baseRowPitch = bufferSpec.bytesPerRow;
|
uint32_t baseRowPitch = bufferSpec.bytesPerRow;
|
||||||
|
@ -510,9 +516,9 @@ TEST_P(CopySplitTest, RowPitch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(CopySplitTest, ImageHeight) {
|
TEST_P(CopySplitTest, ImageHeight) {
|
||||||
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
||||||
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
||||||
uint32_t baseImageHeight = bufferSpec.rowsPerImage;
|
uint32_t baseImageHeight = bufferSpec.rowsPerImage;
|
||||||
|
@ -523,8 +529,11 @@ TEST_P(CopySplitTest, ImageHeight) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(,
|
INSTANTIATE_TEST_SUITE_P(,
|
||||||
CopySplitTest,
|
CopySplitTest,
|
||||||
testing::Values(wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D));
|
testing::Values(wgpu::TextureDimension::e2D,
|
||||||
|
wgpu::TextureDimension::e3D));
|
||||||
|
|
||||||
|
} // namespace dawn::native::d3d12
|
||||||
|
|
|
@ -21,9 +21,12 @@
|
||||||
#include "dawn/tests/DawnNativeTest.h"
|
#include "dawn/tests/DawnNativeTest.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
class CommandBufferEncodingTests : public DawnNativeTest {
|
namespace dawn::native {
|
||||||
|
|
||||||
|
class CommandBufferEncodingTests : public DawnNativeTest {
|
||||||
protected:
|
protected:
|
||||||
void ExpectCommands(dawn::native::CommandIterator* commands,
|
void ExpectCommands(
|
||||||
|
dawn::native::CommandIterator* commands,
|
||||||
std::vector<std::pair<dawn::native::Command,
|
std::vector<std::pair<dawn::native::Command,
|
||||||
std::function<void(dawn::native::CommandIterator*)>>>
|
std::function<void(dawn::native::CommandIterator*)>>>
|
||||||
expectedCommands) {
|
expectedCommands) {
|
||||||
|
@ -35,13 +38,11 @@ class CommandBufferEncodingTests : public DawnNativeTest {
|
||||||
expectedCommands[commandIndex].second(commands);
|
expectedCommands[commandIndex].second(commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Indirect dispatch validation changes the bind groups in the middle
|
|
||||||
// of a pass. Test that bindings are restored after the validation runs.
|
|
||||||
TEST_F(CommandBufferEncodingTests, ComputePassEncoderIndirectDispatchStateRestoration) {
|
|
||||||
using namespace dawn::native;
|
|
||||||
|
|
||||||
|
// Indirect dispatch validation changes the bind groups in the middle
|
||||||
|
// of a pass. Test that bindings are restored after the validation runs.
|
||||||
|
TEST_F(CommandBufferEncodingTests, ComputePassEncoderIndirectDispatchStateRestoration) {
|
||||||
wgpu::BindGroupLayout staticLayout =
|
wgpu::BindGroupLayout staticLayout =
|
||||||
utils::MakeBindGroupLayout(device, {{
|
utils::MakeBindGroupLayout(device, {{
|
||||||
0,
|
0,
|
||||||
|
@ -74,8 +75,8 @@ TEST_F(CommandBufferEncodingTests, ComputePassEncoderIndirectDispatchStateRestor
|
||||||
wgpu::ComputePipeline pipeline1 = device.CreateComputePipeline(&csDesc);
|
wgpu::ComputePipeline pipeline1 = device.CreateComputePipeline(&csDesc);
|
||||||
|
|
||||||
// Create buffers to use for both the indirect buffer and the bind groups.
|
// Create buffers to use for both the indirect buffer and the bind groups.
|
||||||
wgpu::Buffer indirectBuffer =
|
wgpu::Buffer indirectBuffer = utils::CreateBufferFromData<uint32_t>(
|
||||||
utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Indirect, {1, 2, 3, 4});
|
device, wgpu::BufferUsage::Indirect, {1, 2, 3, 4});
|
||||||
|
|
||||||
wgpu::BufferDescriptor uniformBufferDesc = {};
|
wgpu::BufferDescriptor uniformBufferDesc = {};
|
||||||
uniformBufferDesc.size = 512;
|
uniformBufferDesc.size = 512;
|
||||||
|
@ -217,7 +218,9 @@ TEST_F(CommandBufferEncodingTests, ComputePassEncoderIndirectDispatchStateRestor
|
||||||
FromAPI(commandBuffer.Get())->GetCommandIteratorForTesting(),
|
FromAPI(commandBuffer.Get())->GetCommandIteratorForTesting(),
|
||||||
{
|
{
|
||||||
{Command::BeginComputePass,
|
{Command::BeginComputePass,
|
||||||
[&](CommandIterator* commands) { SkipCommand(commands, Command::BeginComputePass); }},
|
[&](CommandIterator* commands) {
|
||||||
|
SkipCommand(commands, Command::BeginComputePass);
|
||||||
|
}},
|
||||||
// Expect the state to be set.
|
// Expect the state to be set.
|
||||||
{Command::SetComputePipeline, ExpectSetPipeline(pipeline0)},
|
{Command::SetComputePipeline, ExpectSetPipeline(pipeline0)},
|
||||||
{Command::SetBindGroup, ExpectSetBindGroup(0, staticBG)},
|
{Command::SetBindGroup, ExpectSetBindGroup(0, staticBG)},
|
||||||
|
@ -270,14 +273,12 @@ TEST_F(CommandBufferEncodingTests, ComputePassEncoderIndirectDispatchStateRestor
|
||||||
{Command::EndComputePass,
|
{Command::EndComputePass,
|
||||||
[&](CommandIterator* commands) { commands->NextCommand<EndComputePassCmd>(); }},
|
[&](CommandIterator* commands) { commands->NextCommand<EndComputePassCmd>(); }},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that after restoring state, it is fully applied to the state tracker
|
|
||||||
// and does not leak state changes that occured between a snapshot and the
|
|
||||||
// state restoration.
|
|
||||||
TEST_F(CommandBufferEncodingTests, StateNotLeakedAfterRestore) {
|
|
||||||
using namespace dawn::native;
|
|
||||||
|
|
||||||
|
// Test that after restoring state, it is fully applied to the state tracker
|
||||||
|
// and does not leak state changes that occured between a snapshot and the
|
||||||
|
// state restoration.
|
||||||
|
TEST_F(CommandBufferEncodingTests, StateNotLeakedAfterRestore) {
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
|
||||||
|
@ -309,4 +310,6 @@ TEST_F(CommandBufferEncodingTests, StateNotLeakedAfterRestore) {
|
||||||
|
|
||||||
// Expect no pipeline
|
// Expect no pipeline
|
||||||
EXPECT_FALSE(stateTracker->HasPipeline());
|
EXPECT_FALSE(stateTracker->HasPipeline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::native
|
||||||
|
|
|
@ -25,9 +25,13 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace testing;
|
using testing::Contains;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::SaveArg;
|
||||||
|
using testing::StrEq;
|
||||||
|
|
||||||
class DeviceCreationTest : public Test {
|
class DeviceCreationTest : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
dawnProcSetProcs(&dawn::native::GetProcs());
|
dawnProcSetProcs(&dawn::native::GetProcs());
|
||||||
|
@ -83,7 +87,7 @@ namespace {
|
||||||
EXPECT_NE(device, nullptr);
|
EXPECT_NE(device, nullptr);
|
||||||
|
|
||||||
auto toggles = dawn::native::GetTogglesUsed(device.Get());
|
auto toggles = dawn::native::GetTogglesUsed(device.Get());
|
||||||
EXPECT_THAT(toggles, testing::Contains(testing::StrEq(toggle)));
|
EXPECT_THAT(toggles, Contains(StrEq(toggle)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DeviceCreationTest, CreateDeviceWithCacheSuccess) {
|
TEST_F(DeviceCreationTest, CreateDeviceWithCacheSuccess) {
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
|
||||||
class MockBufferMapAsyncCallback {
|
class MockBufferMapAsyncCallback {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::Sequence;
|
||||||
|
|
||||||
class MockDevicePopErrorScopeCallback {
|
class MockDevicePopErrorScopeCallback {
|
||||||
public:
|
public:
|
||||||
|
@ -170,7 +172,7 @@ TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
||||||
queue.Submit(0, nullptr);
|
queue.Submit(0, nullptr);
|
||||||
queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
|
queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
|
||||||
|
|
||||||
testing::Sequence seq;
|
Sequence seq;
|
||||||
|
|
||||||
MockCallback<WGPUErrorCallback> errorScopeCallback2;
|
MockCallback<WGPUErrorCallback> errorScopeCallback2;
|
||||||
EXPECT_CALL(errorScopeCallback2, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
EXPECT_CALL(errorScopeCallback2, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
||||||
|
|
|
@ -16,7 +16,12 @@
|
||||||
|
|
||||||
#include "dawn/tests/MockCallback.h"
|
#include "dawn/tests/MockCallback.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
|
using testing::Invoke;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::StrictMock;
|
||||||
|
using testing::WithArg;
|
||||||
|
|
||||||
class MultipleDeviceTest : public ValidationTest {};
|
class MultipleDeviceTest : public ValidationTest {};
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
#include "dawn/tests/unittests/validation/ValidationTest.h"
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
using namespace testing;
|
|
||||||
|
|
||||||
class MockQueueWorkDoneCallback {
|
class MockQueueWorkDoneCallback {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||||
|
|
|
@ -23,10 +23,17 @@
|
||||||
|
|
||||||
#include "webgpu/webgpu_cpp.h"
|
#include "webgpu/webgpu_cpp.h"
|
||||||
|
|
||||||
namespace {
|
namespace dawn::wire { namespace {
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
using namespace dawn::wire;
|
using testing::Invoke;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::SaveArg;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::WithArg;
|
||||||
|
|
||||||
class WireAdapterTests : public WireTest {
|
class WireAdapterTests : public WireTest {
|
||||||
protected:
|
protected:
|
||||||
|
@ -328,4 +335,6 @@ namespace {
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
// TODO(https://crbug.com/dawn/1381) Remove when namespaces are not indented.
|
||||||
|
// NOLINTNEXTLINE(readability/namespace)
|
||||||
|
}} // namespace dawn::wire::
|
||||||
|
|
|
@ -18,35 +18,40 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/common/Constants.h"
|
#include "dawn/common/Constants.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireArgumentTests : public WireTest {
|
using testing::_;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::Sequence;
|
||||||
|
|
||||||
|
class WireArgumentTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireArgumentTests() {
|
WireArgumentTests() {
|
||||||
}
|
}
|
||||||
~WireArgumentTests() override = default;
|
~WireArgumentTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that the wire is able to send numerical values
|
// Test that the wire is able to send numerical values
|
||||||
TEST_F(WireArgumentTests, ValueArgument) {
|
TEST_F(WireArgumentTests, ValueArgument) {
|
||||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
||||||
wgpuComputePassEncoderDispatch(pass, 1, 2, 3);
|
wgpuComputePassEncoderDispatch(pass, 1, 2, 3);
|
||||||
|
|
||||||
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
||||||
|
.WillOnce(Return(apiEncoder));
|
||||||
|
|
||||||
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
||||||
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr)).WillOnce(Return(apiPass));
|
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr))
|
||||||
|
.WillOnce(Return(apiPass));
|
||||||
|
|
||||||
EXPECT_CALL(api, ComputePassEncoderDispatch(apiPass, 1, 2, 3)).Times(1);
|
EXPECT_CALL(api, ComputePassEncoderDispatch(apiPass, 1, 2, 3)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send arrays of numerical values
|
// Test that the wire is able to send arrays of numerical values
|
||||||
TEST_F(WireArgumentTests, ValueArrayArgument) {
|
TEST_F(WireArgumentTests, ValueArrayArgument) {
|
||||||
// Create a bindgroup.
|
// Create a bindgroup.
|
||||||
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
||||||
bglDescriptor.entryCount = 0;
|
bglDescriptor.entryCount = 0;
|
||||||
|
@ -70,13 +75,16 @@ TEST_F(WireArgumentTests, ValueArrayArgument) {
|
||||||
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
|
||||||
|
|
||||||
std::array<uint32_t, 4> testOffsets = {0, 42, 0xDEAD'BEEFu, 0xFFFF'FFFFu};
|
std::array<uint32_t, 4> testOffsets = {0, 42, 0xDEAD'BEEFu, 0xFFFF'FFFFu};
|
||||||
wgpuComputePassEncoderSetBindGroup(pass, 0, bindGroup, testOffsets.size(), testOffsets.data());
|
wgpuComputePassEncoderSetBindGroup(pass, 0, bindGroup, testOffsets.size(),
|
||||||
|
testOffsets.data());
|
||||||
|
|
||||||
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
||||||
|
.WillOnce(Return(apiEncoder));
|
||||||
|
|
||||||
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
WGPUComputePassEncoder apiPass = api.GetNewComputePassEncoder();
|
||||||
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr)).WillOnce(Return(apiPass));
|
EXPECT_CALL(api, CommandEncoderBeginComputePass(apiEncoder, nullptr))
|
||||||
|
.WillOnce(Return(apiPass));
|
||||||
|
|
||||||
EXPECT_CALL(api, ComputePassEncoderSetBindGroup(
|
EXPECT_CALL(api, ComputePassEncoderSetBindGroup(
|
||||||
apiPass, 0, apiBindGroup, testOffsets.size(),
|
apiPass, 0, apiBindGroup, testOffsets.size(),
|
||||||
|
@ -90,10 +98,10 @@ TEST_F(WireArgumentTests, ValueArrayArgument) {
|
||||||
})));
|
})));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send C strings
|
// Test that the wire is able to send C strings
|
||||||
TEST_F(WireArgumentTests, CStringArgument) {
|
TEST_F(WireArgumentTests, CStringArgument) {
|
||||||
// Create shader module
|
// Create shader module
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
|
@ -167,21 +175,22 @@ TEST_F(WireArgumentTests, CStringArgument) {
|
||||||
wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||||
|
|
||||||
WGPURenderPipeline apiPlaceholderPipeline = api.GetNewRenderPipeline();
|
WGPURenderPipeline apiPlaceholderPipeline = api.GetNewRenderPipeline();
|
||||||
EXPECT_CALL(api,
|
EXPECT_CALL(
|
||||||
DeviceCreateRenderPipeline(
|
api, DeviceCreateRenderPipeline(
|
||||||
apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
|
||||||
return desc->vertex.entryPoint == std::string("main");
|
return desc->vertex.entryPoint == std::string("main");
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(apiPlaceholderPipeline));
|
.WillOnce(Return(apiPlaceholderPipeline));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send objects as value arguments
|
// Test that the wire is able to send objects as value arguments
|
||||||
TEST_F(WireArgumentTests, ObjectAsValueArgument) {
|
TEST_F(WireArgumentTests, ObjectAsValueArgument) {
|
||||||
WGPUCommandEncoder cmdBufEncoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder cmdBufEncoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
||||||
|
.WillOnce(Return(apiEncoder));
|
||||||
|
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 8;
|
descriptor.size = 8;
|
||||||
|
@ -195,13 +204,14 @@ TEST_F(WireArgumentTests, ObjectAsValueArgument) {
|
||||||
.RetiresOnSaturation();
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
wgpuCommandEncoderCopyBufferToBuffer(cmdBufEncoder, buffer, 0, buffer, 4, 4);
|
wgpuCommandEncoderCopyBufferToBuffer(cmdBufEncoder, buffer, 0, buffer, 4, 4);
|
||||||
EXPECT_CALL(api, CommandEncoderCopyBufferToBuffer(apiEncoder, apiBuffer, 0, apiBuffer, 4, 4));
|
EXPECT_CALL(api,
|
||||||
|
CommandEncoderCopyBufferToBuffer(apiEncoder, apiBuffer, 0, apiBuffer, 4, 4));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send array of objects
|
// Test that the wire is able to send array of objects
|
||||||
TEST_F(WireArgumentTests, ObjectsAsPointerArgument) {
|
TEST_F(WireArgumentTests, ObjectsAsPointerArgument) {
|
||||||
WGPUCommandBuffer cmdBufs[2];
|
WGPUCommandBuffer cmdBufs[2];
|
||||||
WGPUCommandBuffer apiCmdBufs[2];
|
WGPUCommandBuffer apiCmdBufs[2];
|
||||||
|
|
||||||
|
@ -226,15 +236,16 @@ TEST_F(WireArgumentTests, ObjectsAsPointerArgument) {
|
||||||
wgpuQueueSubmit(queue, 2, cmdBufs);
|
wgpuQueueSubmit(queue, 2, cmdBufs);
|
||||||
|
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
api, QueueSubmit(apiQueue, 2, MatchesLambda([=](const WGPUCommandBuffer* cmdBufs) -> bool {
|
api,
|
||||||
|
QueueSubmit(apiQueue, 2, MatchesLambda([=](const WGPUCommandBuffer* cmdBufs) -> bool {
|
||||||
return cmdBufs[0] == apiCmdBufs[0] && cmdBufs[1] == apiCmdBufs[1];
|
return cmdBufs[0] == apiCmdBufs[0] && cmdBufs[1] == apiCmdBufs[1];
|
||||||
})));
|
})));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send structures that contain pure values (non-objects)
|
// Test that the wire is able to send structures that contain pure values (non-objects)
|
||||||
TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
||||||
WGPUSamplerDescriptor descriptor = {};
|
WGPUSamplerDescriptor descriptor = {};
|
||||||
descriptor.magFilter = WGPUFilterMode_Linear;
|
descriptor.magFilter = WGPUFilterMode_Linear;
|
||||||
descriptor.minFilter = WGPUFilterMode_Nearest;
|
descriptor.minFilter = WGPUFilterMode_Nearest;
|
||||||
|
@ -249,8 +260,11 @@ TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
||||||
wgpuDeviceCreateSampler(device, &descriptor);
|
wgpuDeviceCreateSampler(device, &descriptor);
|
||||||
|
|
||||||
WGPUSampler apiPlaceholderSampler = api.GetNewSampler();
|
WGPUSampler apiPlaceholderSampler = api.GetNewSampler();
|
||||||
EXPECT_CALL(api, DeviceCreateSampler(
|
EXPECT_CALL(
|
||||||
apiDevice, MatchesLambda([](const WGPUSamplerDescriptor* desc) -> bool {
|
api, DeviceCreateSampler(
|
||||||
|
apiDevice,
|
||||||
|
MatchesLambda(
|
||||||
|
[](const WGPUSamplerDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr &&
|
return desc->nextInChain == nullptr &&
|
||||||
desc->magFilter == WGPUFilterMode_Linear &&
|
desc->magFilter == WGPUFilterMode_Linear &&
|
||||||
desc->minFilter == WGPUFilterMode_Nearest &&
|
desc->minFilter == WGPUFilterMode_Nearest &&
|
||||||
|
@ -264,10 +278,10 @@ TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
||||||
.WillOnce(Return(apiPlaceholderSampler));
|
.WillOnce(Return(apiPlaceholderSampler));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send structures that contain objects
|
// Test that the wire is able to send structures that contain objects
|
||||||
TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
||||||
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
|
||||||
bglDescriptor.entryCount = 0;
|
bglDescriptor.entryCount = 0;
|
||||||
bglDescriptor.entries = nullptr;
|
bglDescriptor.entries = nullptr;
|
||||||
|
@ -283,20 +297,20 @@ TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
||||||
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
||||||
|
|
||||||
WGPUPipelineLayout apiPlaceholderLayout = api.GetNewPipelineLayout();
|
WGPUPipelineLayout apiPlaceholderLayout = api.GetNewPipelineLayout();
|
||||||
EXPECT_CALL(api, DeviceCreatePipelineLayout(
|
EXPECT_CALL(
|
||||||
|
api, DeviceCreatePipelineLayout(
|
||||||
apiDevice,
|
apiDevice,
|
||||||
MatchesLambda([apiBgl](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
MatchesLambda([apiBgl](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr &&
|
return desc->nextInChain == nullptr && desc->bindGroupLayoutCount == 1 &&
|
||||||
desc->bindGroupLayoutCount == 1 &&
|
|
||||||
desc->bindGroupLayouts[0] == apiBgl;
|
desc->bindGroupLayouts[0] == apiBgl;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(apiPlaceholderLayout));
|
.WillOnce(Return(apiPlaceholderLayout));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send structures that contain objects
|
// Test that the wire is able to send structures that contain objects
|
||||||
TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
|
TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
|
||||||
static constexpr int NUM_BINDINGS = 3;
|
static constexpr int NUM_BINDINGS = 3;
|
||||||
WGPUBindGroupLayoutEntry entries[NUM_BINDINGS]{
|
WGPUBindGroupLayoutEntry entries[NUM_BINDINGS]{
|
||||||
{nullptr,
|
{nullptr,
|
||||||
|
@ -327,15 +341,16 @@ TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
|
||||||
|
|
||||||
wgpuDeviceCreateBindGroupLayout(device, &bglDescriptor);
|
wgpuDeviceCreateBindGroupLayout(device, &bglDescriptor);
|
||||||
WGPUBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
|
WGPUBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(api,
|
||||||
api,
|
|
||||||
DeviceCreateBindGroupLayout(
|
DeviceCreateBindGroupLayout(
|
||||||
apiDevice, MatchesLambda([entries](const WGPUBindGroupLayoutDescriptor* desc) -> bool {
|
apiDevice,
|
||||||
|
MatchesLambda([entries](const WGPUBindGroupLayoutDescriptor* desc) -> bool {
|
||||||
for (int i = 0; i < NUM_BINDINGS; ++i) {
|
for (int i = 0; i < NUM_BINDINGS; ++i) {
|
||||||
const auto& a = desc->entries[i];
|
const auto& a = desc->entries[i];
|
||||||
const auto& b = entries[i];
|
const auto& b = entries[i];
|
||||||
if (a.binding != b.binding || a.visibility != b.visibility ||
|
if (a.binding != b.binding || a.visibility != b.visibility ||
|
||||||
a.buffer.type != b.buffer.type || a.sampler.type != b.sampler.type ||
|
a.buffer.type != b.buffer.type ||
|
||||||
|
a.sampler.type != b.sampler.type ||
|
||||||
a.texture.sampleType != b.texture.sampleType) {
|
a.texture.sampleType != b.texture.sampleType) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -345,10 +360,10 @@ TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
|
||||||
.WillOnce(Return(apiBgl));
|
.WillOnce(Return(apiBgl));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test passing nullptr instead of objects - array of objects version
|
// Test passing nullptr instead of objects - array of objects version
|
||||||
TEST_F(WireArgumentTests, DISABLED_NullptrInArray) {
|
TEST_F(WireArgumentTests, DISABLED_NullptrInArray) {
|
||||||
WGPUBindGroupLayout nullBGL = nullptr;
|
WGPUBindGroupLayout nullBGL = nullptr;
|
||||||
|
|
||||||
WGPUPipelineLayoutDescriptor descriptor = {};
|
WGPUPipelineLayoutDescriptor descriptor = {};
|
||||||
|
@ -356,8 +371,8 @@ TEST_F(WireArgumentTests, DISABLED_NullptrInArray) {
|
||||||
descriptor.bindGroupLayouts = &nullBGL;
|
descriptor.bindGroupLayouts = &nullBGL;
|
||||||
|
|
||||||
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
wgpuDeviceCreatePipelineLayout(device, &descriptor);
|
||||||
EXPECT_CALL(api,
|
EXPECT_CALL(
|
||||||
DeviceCreatePipelineLayout(
|
api, DeviceCreatePipelineLayout(
|
||||||
apiDevice, MatchesLambda([](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const WGPUPipelineLayoutDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr && desc->bindGroupLayoutCount == 1 &&
|
return desc->nextInChain == nullptr && desc->bindGroupLayoutCount == 1 &&
|
||||||
desc->bindGroupLayouts[0] == nullptr;
|
desc->bindGroupLayouts[0] == nullptr;
|
||||||
|
@ -365,4 +380,6 @@ TEST_F(WireArgumentTests, DISABLED_NullptrInArray) {
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(nullptr));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -14,18 +14,19 @@
|
||||||
|
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireBasicTests : public WireTest {
|
using testing::Return;
|
||||||
|
|
||||||
|
class WireBasicTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireBasicTests() {
|
WireBasicTests() {
|
||||||
}
|
}
|
||||||
~WireBasicTests() override = default;
|
~WireBasicTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// One call gets forwarded correctly.
|
// One call gets forwarded correctly.
|
||||||
TEST_F(WireBasicTests, CallForwarded) {
|
TEST_F(WireBasicTests, CallForwarded) {
|
||||||
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
WGPUCommandEncoder apiCmdBufEncoder = api.GetNewCommandEncoder();
|
WGPUCommandEncoder apiCmdBufEncoder = api.GetNewCommandEncoder();
|
||||||
|
@ -33,10 +34,10 @@ TEST_F(WireBasicTests, CallForwarded) {
|
||||||
.WillOnce(Return(apiCmdBufEncoder));
|
.WillOnce(Return(apiCmdBufEncoder));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that calling methods on a new object works as expected.
|
// Test that calling methods on a new object works as expected.
|
||||||
TEST_F(WireBasicTests, CreateThenCall) {
|
TEST_F(WireBasicTests, CreateThenCall) {
|
||||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
wgpuCommandEncoderFinish(encoder, nullptr);
|
wgpuCommandEncoderFinish(encoder, nullptr);
|
||||||
|
|
||||||
|
@ -45,13 +46,14 @@ TEST_F(WireBasicTests, CreateThenCall) {
|
||||||
.WillOnce(Return(apiCmdBufEncoder));
|
.WillOnce(Return(apiCmdBufEncoder));
|
||||||
|
|
||||||
WGPUCommandBuffer apiCmdBuf = api.GetNewCommandBuffer();
|
WGPUCommandBuffer apiCmdBuf = api.GetNewCommandBuffer();
|
||||||
EXPECT_CALL(api, CommandEncoderFinish(apiCmdBufEncoder, nullptr)).WillOnce(Return(apiCmdBuf));
|
EXPECT_CALL(api, CommandEncoderFinish(apiCmdBufEncoder, nullptr))
|
||||||
|
.WillOnce(Return(apiCmdBuf));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that client reference/release do not call the backend API.
|
// Test that client reference/release do not call the backend API.
|
||||||
TEST_F(WireBasicTests, RefCountKeptInClient) {
|
TEST_F(WireBasicTests, RefCountKeptInClient) {
|
||||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
wgpuCommandEncoderReference(encoder);
|
wgpuCommandEncoderReference(encoder);
|
||||||
|
@ -62,10 +64,10 @@ TEST_F(WireBasicTests, RefCountKeptInClient) {
|
||||||
.WillOnce(Return(apiCmdBufEncoder));
|
.WillOnce(Return(apiCmdBufEncoder));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that client reference/release do not call the backend API.
|
// Test that client reference/release do not call the backend API.
|
||||||
TEST_F(WireBasicTests, ReleaseCalledOnRefCount0) {
|
TEST_F(WireBasicTests, ReleaseCalledOnRefCount0) {
|
||||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
wgpuCommandEncoderRelease(encoder);
|
wgpuCommandEncoderRelease(encoder);
|
||||||
|
@ -77,4 +79,6 @@ TEST_F(WireBasicTests, ReleaseCalledOnRefCount0) {
|
||||||
EXPECT_CALL(api, CommandEncoderRelease(apiCmdBufEncoder));
|
EXPECT_CALL(api, CommandEncoderRelease(apiCmdBufEncoder));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -18,10 +18,15 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::StrictMock;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Mock class to add expectations on the wire calling callbacks
|
// Mock class to add expectations on the wire calling callbacks
|
||||||
class MockBufferMapCallback {
|
class MockBufferMapCallback {
|
||||||
|
@ -34,9 +39,9 @@ namespace {
|
||||||
mockBufferMapCallback->Call(status, userdata);
|
mockBufferMapCallback->Call(status, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireBufferMappingTests : public WireTest {
|
class WireBufferMappingTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireBufferMappingTests() {
|
WireBufferMappingTests() {
|
||||||
}
|
}
|
||||||
|
@ -84,10 +89,10 @@ class WireBufferMappingTests : public WireTest {
|
||||||
// A successfully created buffer
|
// A successfully created buffer
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tests specific to mapping for reading
|
// Tests specific to mapping for reading
|
||||||
class WireBufferMappingReadTests : public WireBufferMappingTests {
|
class WireBufferMappingReadTests : public WireBufferMappingTests {
|
||||||
public:
|
public:
|
||||||
WireBufferMappingReadTests() {
|
WireBufferMappingReadTests() {
|
||||||
}
|
}
|
||||||
|
@ -98,11 +103,12 @@ class WireBufferMappingReadTests : public WireBufferMappingTests {
|
||||||
|
|
||||||
SetupBuffer(WGPUBufferUsage_MapRead);
|
SetupBuffer(WGPUBufferUsage_MapRead);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check mapping for reading a succesfully created buffer
|
// Check mapping for reading a succesfully created buffer
|
||||||
TEST_F(WireBufferMappingReadTests, MappingForReadSuccessBuffer) {
|
TEST_F(WireBufferMappingReadTests, MappingForReadSuccessBuffer) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -118,23 +124,25 @@ TEST_F(WireBufferMappingReadTests, MappingForReadSuccessBuffer) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_EQ(bufferContent,
|
EXPECT_EQ(bufferContent, *static_cast<const uint32_t*>(
|
||||||
*static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that things work correctly when a validation error happens when mapping the buffer for
|
// Check that things work correctly when a validation error happens when mapping the buffer for
|
||||||
// reading
|
// reading
|
||||||
TEST_F(WireBufferMappingReadTests, ErrorWhileMappingForRead) {
|
TEST_F(WireBufferMappingReadTests, ErrorWhileMappingForRead) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -143,12 +151,13 @@ TEST_F(WireBufferMappingReadTests, ErrorWhileMappingForRead) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_EQ(nullptr, wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize));
|
EXPECT_EQ(nullptr, wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the map read callback is called with UNKNOWN when the buffer is destroyed before the
|
// Check that the map read callback is called with UNKNOWN when the buffer is destroyed before
|
||||||
// request is finished
|
// the request is finished
|
||||||
TEST_F(WireBufferMappingReadTests, DestroyBeforeReadRequestEnd) {
|
TEST_F(WireBufferMappingReadTests, DestroyBeforeReadRequestEnd) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
uint32_t bufferContent = 0;
|
uint32_t bufferContent = 0;
|
||||||
|
@ -161,19 +170,21 @@ TEST_F(WireBufferMappingReadTests, DestroyBeforeReadRequestEnd) {
|
||||||
|
|
||||||
// Destroy before the client gets the success, so the callback is called with
|
// Destroy before the client gets the success, so the callback is called with
|
||||||
// DestroyedBeforeCallback.
|
// DestroyedBeforeCallback.
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
EXPECT_CALL(*mockBufferMapCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuBufferRelease(buffer);
|
wgpuBufferRelease(buffer);
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the map read callback is called with "UnmappedBeforeCallback" when the map request would
|
// Check the map read callback is called with "UnmappedBeforeCallback" when the map request
|
||||||
// have worked, but Unmap was called
|
// would have worked, but Unmap was called
|
||||||
TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForRead) {
|
TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForRead) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -192,20 +203,23 @@ TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForRead) {
|
||||||
|
|
||||||
// The callback shouldn't get called with success, even when the request succeeded on the
|
// The callback shouldn't get called with success, even when the request succeeded on the
|
||||||
// server side
|
// server side
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
|
EXPECT_CALL(*mockBufferMapCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that even if Unmap() was called early client-side, we correctly surface server-side
|
// Check that even if Unmap() was called early client-side, we correctly surface server-side
|
||||||
// validation errors.
|
// validation errors.
|
||||||
TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForReadButServerSideError) {
|
TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForReadButServerSideError) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
// Oh no! We are calling Unmap too early! However the callback gets fired only after we get
|
// Oh no! We are calling Unmap too early! However the callback gets fired only after we get
|
||||||
// an answer from the server that the mapAsync call was an error.
|
// an answer from the server that the mapAsync call was an error.
|
||||||
|
@ -214,16 +228,18 @@ TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForReadButServerSideError)
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// The callback should be called with the server-side error and not the UnmappedBeforeCallback.
|
// The callback should be called with the server-side error and not the
|
||||||
|
// UnmappedBeforeCallback.
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the map read callback is called with "DestroyedBeforeCallback" when the map request would
|
// Check the map read callback is called with "DestroyedBeforeCallback" when the map request
|
||||||
// have worked, but Destroy was called
|
// would have worked, but Destroy was called
|
||||||
TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForRead) {
|
TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForRead) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -242,39 +258,44 @@ TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForRead) {
|
||||||
|
|
||||||
// The callback shouldn't get called with success, even when the request succeeded on the
|
// The callback shouldn't get called with success, even when the request succeeded on the
|
||||||
// server side
|
// server side
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
EXPECT_CALL(*mockBufferMapCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that even if Destroy() was called early client-side, we correctly surface server-side
|
// Check that even if Destroy() was called early client-side, we correctly surface server-side
|
||||||
// validation errors.
|
// validation errors.
|
||||||
TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForReadButServerSideError) {
|
TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForReadButServerSideError) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
// Oh no! We are calling Destroy too early! However the callback gets fired only after we get
|
// Oh no! We are calling Destroy too early! However the callback gets fired only after we
|
||||||
// an answer from the server that the mapAsync call was an error.
|
// get an answer from the server that the mapAsync call was an error.
|
||||||
wgpuBufferDestroy(buffer);
|
wgpuBufferDestroy(buffer);
|
||||||
EXPECT_CALL(api, BufferDestroy(apiBuffer));
|
EXPECT_CALL(api, BufferDestroy(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// The callback should be called with the server-side error and not the DestroyedBeforCallback..
|
// The callback should be called with the server-side error and not the
|
||||||
|
// DestroyedBeforCallback..
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that an error map read while a buffer is already mapped won't changed the result of get
|
// Check that an error map read while a buffer is already mapped won't changed the result of get
|
||||||
// mapped range
|
// mapped range
|
||||||
TEST_F(WireBufferMappingReadTests, MappingForReadingErrorWhileAlreadyMappedUnchangeMapData) {
|
TEST_F(WireBufferMappingReadTests, MappingForReadingErrorWhileAlreadyMappedUnchangeMapData) {
|
||||||
// Successful map
|
// Successful map
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -291,10 +312,12 @@ TEST_F(WireBufferMappingReadTests, MappingForReadingErrorWhileAlreadyMappedUncha
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
// Map failure while the buffer is already mapped
|
// Map failure while the buffer is already mapped
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -302,13 +325,14 @@ TEST_F(WireBufferMappingReadTests, MappingForReadingErrorWhileAlreadyMappedUncha
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_EQ(bufferContent,
|
EXPECT_EQ(bufferContent, *static_cast<const uint32_t*>(
|
||||||
*static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the MapReadCallback isn't fired twice when unmap() is called inside the callback
|
// Test that the MapReadCallback isn't fired twice when unmap() is called inside the callback
|
||||||
TEST_F(WireBufferMappingReadTests, UnmapInsideMapReadCallback) {
|
TEST_F(WireBufferMappingReadTests, UnmapInsideMapReadCallback) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -328,12 +352,13 @@ TEST_F(WireBufferMappingReadTests, UnmapInsideMapReadCallback) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
|
// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
|
||||||
// callback
|
// callback
|
||||||
TEST_F(WireBufferMappingReadTests, DestroyInsideMapReadCallback) {
|
TEST_F(WireBufferMappingReadTests, DestroyInsideMapReadCallback) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
|
@ -353,10 +378,10 @@ TEST_F(WireBufferMappingReadTests, DestroyInsideMapReadCallback) {
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests specific to mapping for writing
|
// Tests specific to mapping for writing
|
||||||
class WireBufferMappingWriteTests : public WireBufferMappingTests {
|
class WireBufferMappingWriteTests : public WireBufferMappingTests {
|
||||||
public:
|
public:
|
||||||
WireBufferMappingWriteTests() {
|
WireBufferMappingWriteTests() {
|
||||||
}
|
}
|
||||||
|
@ -367,11 +392,12 @@ class WireBufferMappingWriteTests : public WireBufferMappingTests {
|
||||||
|
|
||||||
SetupBuffer(WGPUBufferUsage_MapWrite);
|
SetupBuffer(WGPUBufferUsage_MapWrite);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check mapping for writing a succesfully created buffer
|
// Check mapping for writing a succesfully created buffer
|
||||||
TEST_F(WireBufferMappingWriteTests, MappingForWriteSuccessBuffer) {
|
TEST_F(WireBufferMappingWriteTests, MappingForWriteSuccessBuffer) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t serverBufferContent = 31337;
|
uint32_t serverBufferContent = 31337;
|
||||||
uint32_t updatedContent = 4242;
|
uint32_t updatedContent = 4242;
|
||||||
|
@ -404,16 +430,18 @@ TEST_F(WireBufferMappingWriteTests, MappingForWriteSuccessBuffer) {
|
||||||
|
|
||||||
// After the buffer is unmapped, the content of the buffer is updated on the server
|
// After the buffer is unmapped, the content of the buffer is updated on the server
|
||||||
ASSERT_EQ(serverBufferContent, updatedContent);
|
ASSERT_EQ(serverBufferContent, updatedContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that things work correctly when a validation error happens when mapping the buffer for
|
// Check that things work correctly when a validation error happens when mapping the buffer for
|
||||||
// writing
|
// writing
|
||||||
TEST_F(WireBufferMappingWriteTests, ErrorWhileMappingForWrite) {
|
TEST_F(WireBufferMappingWriteTests, ErrorWhileMappingForWrite) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -422,12 +450,13 @@ TEST_F(WireBufferMappingWriteTests, ErrorWhileMappingForWrite) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, kBufferSize));
|
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, kBufferSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the map write callback is called with "DestroyedBeforeCallback" when the buffer is
|
// Check that the map write callback is called with "DestroyedBeforeCallback" when the buffer is
|
||||||
// destroyed before the request is finished
|
// destroyed before the request is finished
|
||||||
TEST_F(WireBufferMappingWriteTests, DestroyBeforeWriteRequestEnd) {
|
TEST_F(WireBufferMappingWriteTests, DestroyBeforeWriteRequestEnd) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
|
@ -440,19 +469,21 @@ TEST_F(WireBufferMappingWriteTests, DestroyBeforeWriteRequestEnd) {
|
||||||
|
|
||||||
// Destroy before the client gets the success, so the callback is called with
|
// Destroy before the client gets the success, so the callback is called with
|
||||||
// DestroyedBeforeCallback.
|
// DestroyedBeforeCallback.
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
EXPECT_CALL(*mockBufferMapCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuBufferRelease(buffer);
|
wgpuBufferRelease(buffer);
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the map write callback is called with "UnmappedBeforeCallback" when the map request would
|
// Check the map write callback is called with "UnmappedBeforeCallback" when the map request
|
||||||
// have worked, but Unmap was called
|
// would have worked, but Unmap was called
|
||||||
TEST_F(WireBufferMappingWriteTests, UnmapCalledTooEarlyForWrite) {
|
TEST_F(WireBufferMappingWriteTests, UnmapCalledTooEarlyForWrite) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -465,18 +496,20 @@ TEST_F(WireBufferMappingWriteTests, UnmapCalledTooEarlyForWrite) {
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Oh no! We are calling Unmap too early!
|
// Oh no! We are calling Unmap too early!
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
|
EXPECT_CALL(*mockBufferMapCallback,
|
||||||
|
Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
|
|
||||||
// The callback shouldn't get called, even when the request succeeded on the server side
|
// The callback shouldn't get called, even when the request succeeded on the server side
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that an error map write while a buffer is already mapped
|
// Check that an error map write while a buffer is already mapped
|
||||||
TEST_F(WireBufferMappingWriteTests, MappingForWritingErrorWhileAlreadyMapped) {
|
TEST_F(WireBufferMappingWriteTests, MappingForWritingErrorWhileAlreadyMapped) {
|
||||||
// Successful map
|
// Successful map
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -493,10 +526,12 @@ TEST_F(WireBufferMappingWriteTests, MappingForWritingErrorWhileAlreadyMapped) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
// Map failure while the buffer is already mapped
|
// Map failure while the buffer is already mapped
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -504,13 +539,14 @@ TEST_F(WireBufferMappingWriteTests, MappingForWritingErrorWhileAlreadyMapped) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_NE(nullptr,
|
EXPECT_NE(nullptr, static_cast<const uint32_t*>(
|
||||||
static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the MapWriteCallback isn't fired twice when unmap() is called inside the callback
|
// Test that the MapWriteCallback isn't fired twice when unmap() is called inside the callback
|
||||||
TEST_F(WireBufferMappingWriteTests, UnmapInsideMapWriteCallback) {
|
TEST_F(WireBufferMappingWriteTests, UnmapInsideMapWriteCallback) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -530,12 +566,13 @@ TEST_F(WireBufferMappingWriteTests, UnmapInsideMapWriteCallback) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the
|
// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in
|
||||||
// callback
|
// the callback
|
||||||
TEST_F(WireBufferMappingWriteTests, DestroyInsideMapWriteCallback) {
|
TEST_F(WireBufferMappingWriteTests, DestroyInsideMapWriteCallback) {
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
uint32_t bufferContent = 31337;
|
uint32_t bufferContent = 31337;
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -555,10 +592,10 @@ TEST_F(WireBufferMappingWriteTests, DestroyInsideMapWriteCallback) {
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful buffer creation with mappedAtCreation=true
|
// Test successful buffer creation with mappedAtCreation=true
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
descriptor.mappedAtCreation = true;
|
||||||
|
@ -577,10 +614,10 @@ TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that releasing a buffer mapped at creation does not call Unmap
|
// Test that releasing a buffer mapped at creation does not call Unmap
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
descriptor.mappedAtCreation = true;
|
||||||
|
@ -599,10 +636,10 @@ TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.usage = WGPUMapMode_Write;
|
descriptor.usage = WGPUMapMode_Write;
|
||||||
|
@ -623,7 +660,8 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() {
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -637,10 +675,10 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
descriptor.mappedAtCreation = true;
|
||||||
|
@ -655,11 +693,13 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -667,18 +707,18 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
EXPECT_NE(nullptr,
|
EXPECT_NE(nullptr, static_cast<const uint32_t*>(
|
||||||
static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that trying to create a buffer of size MAX_SIZE_T is an error handling in the client and
|
// Check that trying to create a buffer of size MAX_SIZE_T is an error handling in the client
|
||||||
// never gets to the server-side.
|
// and never gets to the server-side.
|
||||||
TEST_F(WireBufferMappingTests, MaxSizeMappableBufferOOMDirectly) {
|
TEST_F(WireBufferMappingTests, MaxSizeMappableBufferOOMDirectly) {
|
||||||
size_t kOOMSize = std::numeric_limits<size_t>::max();
|
size_t kOOMSize = std::numeric_limits<size_t>::max();
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
|
|
||||||
|
@ -718,13 +758,14 @@ TEST_F(WireBufferMappingTests, MaxSizeMappableBufferOOMDirectly) {
|
||||||
EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice)).WillOnce(Return(apiBuffer));
|
EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice)).WillOnce(Return(apiBuffer));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback then wire disconnect calls the callback with
|
// Test that registering a callback then wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireBufferMappingTests, MapThenDisconnect) {
|
TEST_F(WireBufferMappingTests, MapThenDisconnect) {
|
||||||
SetupBuffer(WGPUMapMode_Write);
|
SetupBuffer(WGPUMapMode_Write);
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, this);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
this);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() {
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -734,29 +775,31 @@ TEST_F(WireBufferMappingTests, MapThenDisconnect) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1);
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
|
||||||
|
.Times(1);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback after wire disconnect calls the callback with
|
// Test that registering a callback after wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireBufferMappingTests, MapAfterDisconnect) {
|
TEST_F(WireBufferMappingTests, MapAfterDisconnect) {
|
||||||
SetupBuffer(WGPUMapMode_Read);
|
SetupBuffer(WGPUMapMode_Read);
|
||||||
|
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
|
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1);
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
|
||||||
|
.Times(1);
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack to pass in test context into user callback
|
// Hack to pass in test context into user callback
|
||||||
struct TestData {
|
struct TestData {
|
||||||
WireBufferMappingTests* pTest;
|
WireBufferMappingTests* pTest;
|
||||||
WGPUBuffer* pTestBuffer;
|
WGPUBuffer* pTestBuffer;
|
||||||
size_t numRequests;
|
size_t numRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus status,
|
static void ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus status,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
||||||
// Mimic the user callback is sending new requests
|
// Mimic the user callback is sending new requests
|
||||||
|
@ -771,10 +814,10 @@ static void ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus stat
|
||||||
wgpuBufferMapAsync(*(testData->pTestBuffer), WGPUMapMode_Write, 0, sizeof(uint32_t),
|
wgpuBufferMapAsync(*(testData->pTestBuffer), WGPUMapMode_Write, 0, sizeof(uint32_t),
|
||||||
ToMockBufferMapCallback, testData->pTest);
|
ToMockBufferMapCallback, testData->pTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that requests inside user callbacks before disconnect are called
|
// Test that requests inside user callbacks before disconnect are called
|
||||||
TEST_F(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
|
TEST_F(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
|
||||||
SetupBuffer(WGPUMapMode_Write);
|
SetupBuffer(WGPUMapMode_Write);
|
||||||
TestData testData = {this, &buffer, 10};
|
TestData testData = {this, &buffer, 10};
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
|
||||||
|
@ -791,10 +834,10 @@ TEST_F(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
|
||||||
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
|
||||||
.Times(1 + testData.numRequests);
|
.Times(1 + testData.numRequests);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that requests inside user callbacks before object destruction are called
|
// Test that requests inside user callbacks before object destruction are called
|
||||||
TEST_F(WireBufferMappingWriteTests, MapInsideCallbackBeforeDestruction) {
|
TEST_F(WireBufferMappingWriteTests, MapInsideCallbackBeforeDestruction) {
|
||||||
TestData testData = {this, &buffer, 10};
|
TestData testData = {this, &buffer, 10};
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
|
||||||
ToMockBufferMapCallbackWithNewRequests, &testData);
|
ToMockBufferMapCallbackWithNewRequests, &testData);
|
||||||
|
@ -811,4 +854,6 @@ TEST_F(WireBufferMappingWriteTests, MapInsideCallbackBeforeDestruction) {
|
||||||
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, this))
|
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, this))
|
||||||
.Times(1 + testData.numRequests);
|
.Times(1 + testData.numRequests);
|
||||||
wgpuBufferRelease(buffer);
|
wgpuBufferRelease(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,10 +17,16 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
namespace {
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::Sequence;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::StrictMock;
|
||||||
|
|
||||||
// Mock class to add expectations on the wire calling callbacks
|
// Mock class to add expectations on the wire calling callbacks
|
||||||
class MockCreateComputePipelineAsyncCallback {
|
class MockCreateComputePipelineAsyncCallback {
|
||||||
|
@ -61,9 +67,9 @@ namespace {
|
||||||
mockCreateRenderPipelineAsyncCallback->Call(status, pipeline, message, userdata);
|
mockCreateRenderPipelineAsyncCallback->Call(status, pipeline, message, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireCreatePipelineAsyncTest : public WireTest {
|
class WireCreatePipelineAsyncTest : public WireTest {
|
||||||
public:
|
public:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
WireTest::SetUp();
|
WireTest::SetUp();
|
||||||
|
@ -91,10 +97,10 @@ class WireCreatePipelineAsyncTest : public WireTest {
|
||||||
WireTest::FlushServer();
|
WireTest::FlushServer();
|
||||||
Mock::VerifyAndClearExpectations(&mockCreateComputePipelineAsyncCallback);
|
Mock::VerifyAndClearExpectations(&mockCreateComputePipelineAsyncCallback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test when creating a compute pipeline with CreateComputePipelineAsync() successfully.
|
// Test when creating a compute pipeline with CreateComputePipelineAsync() successfully.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncSuccess) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncSuccess) {
|
||||||
WGPUShaderModuleDescriptor csDescriptor{};
|
WGPUShaderModuleDescriptor csDescriptor{};
|
||||||
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
||||||
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
||||||
|
@ -120,10 +126,10 @@ TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncSuccess) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test when creating a compute pipeline with CreateComputePipelineAsync() results in an error.
|
// Test when creating a compute pipeline with CreateComputePipelineAsync() results in an error.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncError) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncError) {
|
||||||
WGPUShaderModuleDescriptor csDescriptor{};
|
WGPUShaderModuleDescriptor csDescriptor{};
|
||||||
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
||||||
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
||||||
|
@ -149,10 +155,10 @@ TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncError) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test when creating a render pipeline with CreateRenderPipelineAsync() successfully.
|
// Test when creating a render pipeline with CreateRenderPipelineAsync() successfully.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncSuccess) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncSuccess) {
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
||||||
|
@ -182,10 +188,10 @@ TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncSuccess) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test when creating a render pipeline with CreateRenderPipelineAsync() results in an error.
|
// Test when creating a render pipeline with CreateRenderPipelineAsync() results in an error.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncError) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncError) {
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
||||||
|
@ -215,11 +221,11 @@ TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncError) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback then wire disconnect calls the callback with
|
// Test that registering a callback then wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncThenDisconnect) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncThenDisconnect) {
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
||||||
|
@ -248,11 +254,11 @@ TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncThenDisconnect) {
|
||||||
Call(WGPUCreatePipelineAsyncStatus_DeviceLost, _, _, this))
|
Call(WGPUCreatePipelineAsyncStatus_DeviceLost, _, _, this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback then wire disconnect calls the callback with
|
// Test that registering a callback then wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncThenDisconnect) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncThenDisconnect) {
|
||||||
WGPUShaderModuleDescriptor csDescriptor{};
|
WGPUShaderModuleDescriptor csDescriptor{};
|
||||||
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
||||||
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
||||||
|
@ -276,11 +282,11 @@ TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncThenDisconnect) {
|
||||||
Call(WGPUCreatePipelineAsyncStatus_DeviceLost, _, _, this))
|
Call(WGPUCreatePipelineAsyncStatus_DeviceLost, _, _, this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback after wire disconnect calls the callback with
|
// Test that registering a callback after wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncAfterDisconnect) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncAfterDisconnect) {
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiVsModule = api.GetNewShaderModule();
|
||||||
|
@ -304,11 +310,11 @@ TEST_F(WireCreatePipelineAsyncTest, CreateRenderPipelineAsyncAfterDisconnect) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuDeviceCreateRenderPipelineAsync(device, &pipelineDescriptor,
|
wgpuDeviceCreateRenderPipelineAsync(device, &pipelineDescriptor,
|
||||||
ToMockCreateRenderPipelineAsyncCallback, this);
|
ToMockCreateRenderPipelineAsyncCallback, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback after wire disconnect calls the callback with
|
// Test that registering a callback after wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncAfterDisconnect) {
|
TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncAfterDisconnect) {
|
||||||
WGPUShaderModuleDescriptor csDescriptor{};
|
WGPUShaderModuleDescriptor csDescriptor{};
|
||||||
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
WGPUShaderModule csModule = wgpuDeviceCreateShaderModule(device, &csDescriptor);
|
||||||
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
WGPUShaderModule apiCsModule = api.GetNewShaderModule();
|
||||||
|
@ -328,9 +334,9 @@ TEST_F(WireCreatePipelineAsyncTest, CreateComputePipelineAsyncAfterDisconnect) {
|
||||||
|
|
||||||
wgpuDeviceCreateComputePipelineAsync(device, &descriptor,
|
wgpuDeviceCreateComputePipelineAsync(device, &descriptor,
|
||||||
ToMockCreateComputePipelineAsyncCallback, this);
|
ToMockCreateComputePipelineAsyncCallback, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WireCreatePipelineAsyncTest, DeviceDeletedBeforeCallback) {
|
TEST_F(WireCreatePipelineAsyncTest, DeviceDeletedBeforeCallback) {
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule module = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule module = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
WGPUShaderModule apiModule = api.GetNewShaderModule();
|
WGPUShaderModule apiModule = api.GetNewShaderModule();
|
||||||
|
@ -374,4 +380,6 @@ TEST_F(WireCreatePipelineAsyncTest, DeviceDeletedBeforeCallback) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
DefaultApiDeviceWasReleased();
|
DefaultApiDeviceWasReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -15,17 +15,20 @@
|
||||||
#include "dawn/tests/MockCallback.h"
|
#include "dawn/tests/MockCallback.h"
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireDestroyObjectTests : public WireTest {};
|
using testing::Return;
|
||||||
|
using testing::Sequence;
|
||||||
|
|
||||||
// Test that destroying the device also destroys child objects.
|
class WireDestroyObjectTests : public WireTest {};
|
||||||
TEST_F(WireDestroyObjectTests, DestroyDeviceDestroysChildren) {
|
|
||||||
|
// Test that destroying the device also destroys child objects.
|
||||||
|
TEST_F(WireDestroyObjectTests, DestroyDeviceDestroysChildren) {
|
||||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
WGPUCommandEncoder apiEncoder = api.GetNewCommandEncoder();
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr)).WillOnce(Return(apiEncoder));
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
||||||
|
.WillOnce(Return(apiEncoder));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -55,4 +58,6 @@ TEST_F(WireDestroyObjectTests, DestroyDeviceDestroysChildren) {
|
||||||
// Using the command encoder should be an error.
|
// Using the command encoder should be an error.
|
||||||
wgpuCommandEncoderFinish(encoder, nullptr);
|
wgpuCommandEncoderFinish(encoder, nullptr);
|
||||||
FlushClient(false);
|
FlushClient(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -18,17 +18,24 @@
|
||||||
#include "dawn/tests/MockCallback.h"
|
#include "dawn/tests/MockCallback.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::Exactly;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::Sequence;
|
||||||
|
using testing::StrEq;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
class WireDisconnectTests : public WireTest {};
|
class WireDisconnectTests : public WireTest {};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
// Test that commands are not received if the client disconnects.
|
// Test that commands are not received if the client disconnects.
|
||||||
TEST_F(WireDisconnectTests, CommandsAfterDisconnect) {
|
TEST_F(WireDisconnectTests, CommandsAfterDisconnect) {
|
||||||
// Check that commands work at all.
|
// Check that commands work at all.
|
||||||
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
|
@ -44,11 +51,11 @@ TEST_F(WireDisconnectTests, CommandsAfterDisconnect) {
|
||||||
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(_, _)).Times(Exactly(0));
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(_, _)).Times(Exactly(0));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that commands that are serialized before a disconnect but flushed
|
// Test that commands that are serialized before a disconnect but flushed
|
||||||
// after are received.
|
// after are received.
|
||||||
TEST_F(WireDisconnectTests, FlushAfterDisconnect) {
|
TEST_F(WireDisconnectTests, FlushAfterDisconnect) {
|
||||||
// Check that commands work at all.
|
// Check that commands work at all.
|
||||||
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
|
|
||||||
|
@ -60,10 +67,10 @@ TEST_F(WireDisconnectTests, FlushAfterDisconnect) {
|
||||||
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
||||||
.WillOnce(Return(apiCmdBufEncoder));
|
.WillOnce(Return(apiCmdBufEncoder));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that disconnecting the wire client calls the device lost callback exacty once.
|
// Check that disconnecting the wire client calls the device lost callback exacty once.
|
||||||
TEST_F(WireDisconnectTests, CallsDeviceLostCallback) {
|
TEST_F(WireDisconnectTests, CallsDeviceLostCallback) {
|
||||||
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
||||||
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
||||||
mockDeviceLostCallback.MakeUserdata(this));
|
mockDeviceLostCallback.MakeUserdata(this));
|
||||||
|
@ -73,10 +80,11 @@ TEST_F(WireDisconnectTests, CallsDeviceLostCallback) {
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that disconnecting the wire client after a device loss does not trigger the callback again.
|
// Check that disconnecting the wire client after a device loss does not trigger the callback
|
||||||
TEST_F(WireDisconnectTests, ServerLostThenDisconnect) {
|
// again.
|
||||||
|
TEST_F(WireDisconnectTests, ServerLostThenDisconnect) {
|
||||||
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
||||||
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
||||||
mockDeviceLostCallback.MakeUserdata(this));
|
mockDeviceLostCallback.MakeUserdata(this));
|
||||||
|
@ -93,11 +101,11 @@ TEST_F(WireDisconnectTests, ServerLostThenDisconnect) {
|
||||||
// Disconnect the client. We shouldn't see the lost callback again.
|
// Disconnect the client. We shouldn't see the lost callback again.
|
||||||
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that disconnecting the wire client inside the device loss callback does not trigger the
|
// Check that disconnecting the wire client inside the device loss callback does not trigger the
|
||||||
// callback again.
|
// callback again.
|
||||||
TEST_F(WireDisconnectTests, ServerLostThenDisconnectInCallback) {
|
TEST_F(WireDisconnectTests, ServerLostThenDisconnectInCallback) {
|
||||||
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
||||||
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
||||||
mockDeviceLostCallback.MakeUserdata(this));
|
mockDeviceLostCallback.MakeUserdata(this));
|
||||||
|
@ -114,10 +122,10 @@ TEST_F(WireDisconnectTests, ServerLostThenDisconnectInCallback) {
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}));
|
}));
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a device loss after a disconnect does not trigger the callback again.
|
// Check that a device loss after a disconnect does not trigger the callback again.
|
||||||
TEST_F(WireDisconnectTests, DisconnectThenServerLost) {
|
TEST_F(WireDisconnectTests, DisconnectThenServerLost) {
|
||||||
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
||||||
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
||||||
mockDeviceLostCallback.MakeUserdata(this));
|
mockDeviceLostCallback.MakeUserdata(this));
|
||||||
|
@ -133,10 +141,10 @@ TEST_F(WireDisconnectTests, DisconnectThenServerLost) {
|
||||||
"lost reason");
|
"lost reason");
|
||||||
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that client objects are all destroyed if the WireClient is destroyed.
|
// Test that client objects are all destroyed if the WireClient is destroyed.
|
||||||
TEST_F(WireDisconnectTests, DeleteClientDestroysObjects) {
|
TEST_F(WireDisconnectTests, DeleteClientDestroysObjects) {
|
||||||
WGPUSamplerDescriptor desc = {};
|
WGPUSamplerDescriptor desc = {};
|
||||||
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
||||||
wgpuDeviceCreateSampler(device, &desc);
|
wgpuDeviceCreateSampler(device, &desc);
|
||||||
|
@ -171,4 +179,6 @@ TEST_F(WireDisconnectTests, DeleteClientDestroysObjects) {
|
||||||
|
|
||||||
// Signal that we already released and cleared callbacks for |apiDevice|
|
// Signal that we already released and cleared callbacks for |apiDevice|
|
||||||
DefaultApiDeviceWasReleased();
|
DefaultApiDeviceWasReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,10 +17,17 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::DoAll;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::SaveArg;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::StrictMock;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Mock classes to add expectations on the wire calling callbacks
|
// Mock classes to add expectations on the wire calling callbacks
|
||||||
class MockDeviceErrorCallback {
|
class MockDeviceErrorCallback {
|
||||||
|
@ -38,7 +45,8 @@ namespace {
|
||||||
MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
|
MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<StrictMock<MockDevicePopErrorScopeCallback>> mockDevicePopErrorScopeCallback;
|
std::unique_ptr<StrictMock<MockDevicePopErrorScopeCallback>>
|
||||||
|
mockDevicePopErrorScopeCallback;
|
||||||
void ToMockDevicePopErrorScopeCallback(WGPUErrorType type,
|
void ToMockDevicePopErrorScopeCallback(WGPUErrorType type,
|
||||||
const char* message,
|
const char* message,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
|
@ -51,13 +59,17 @@ namespace {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<StrictMock<MockDeviceLoggingCallback>> mockDeviceLoggingCallback;
|
std::unique_ptr<StrictMock<MockDeviceLoggingCallback>> mockDeviceLoggingCallback;
|
||||||
void ToMockDeviceLoggingCallback(WGPULoggingType type, const char* message, void* userdata) {
|
void ToMockDeviceLoggingCallback(WGPULoggingType type,
|
||||||
|
const char* message,
|
||||||
|
void* userdata) {
|
||||||
mockDeviceLoggingCallback->Call(type, message, userdata);
|
mockDeviceLoggingCallback->Call(type, message, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockDeviceLostCallback {
|
class MockDeviceLostCallback {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(void, Call, (WGPUDeviceLostReason reason, const char* message, void* userdata));
|
MOCK_METHOD(void,
|
||||||
|
Call,
|
||||||
|
(WGPUDeviceLostReason reason, const char* message, void* userdata));
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<StrictMock<MockDeviceLostCallback>> mockDeviceLostCallback;
|
std::unique_ptr<StrictMock<MockDeviceLostCallback>> mockDeviceLostCallback;
|
||||||
|
@ -67,9 +79,9 @@ namespace {
|
||||||
mockDeviceLostCallback->Call(reason, message, userdata);
|
mockDeviceLostCallback->Call(reason, message, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireErrorCallbackTests : public WireTest {
|
class WireErrorCallbackTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireErrorCallbackTests() {
|
WireErrorCallbackTests() {
|
||||||
}
|
}
|
||||||
|
@ -100,10 +112,10 @@ class WireErrorCallbackTests : public WireTest {
|
||||||
Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
|
Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
|
||||||
Mock::VerifyAndClearExpectations(&mockDevicePopErrorScopeCallback);
|
Mock::VerifyAndClearExpectations(&mockDevicePopErrorScopeCallback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test the return wire for device error callbacks
|
// Test the return wire for device error callbacks
|
||||||
TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
|
TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
|
||||||
wgpuDeviceSetUncapturedErrorCallback(device, ToMockDeviceErrorCallback, this);
|
wgpuDeviceSetUncapturedErrorCallback(device, ToMockDeviceErrorCallback, this);
|
||||||
|
|
||||||
// Setting the error callback should stay on the client side and do nothing
|
// Setting the error callback should stay on the client side and do nothing
|
||||||
|
@ -119,10 +131,10 @@ TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the return wire for device user warning callbacks
|
// Test the return wire for device user warning callbacks
|
||||||
TEST_F(WireErrorCallbackTests, DeviceLoggingCallback) {
|
TEST_F(WireErrorCallbackTests, DeviceLoggingCallback) {
|
||||||
wgpuDeviceSetLoggingCallback(device, ToMockDeviceLoggingCallback, this);
|
wgpuDeviceSetLoggingCallback(device, ToMockDeviceLoggingCallback, this);
|
||||||
|
|
||||||
// Setting the injected warning callback should stay on the client side and do nothing
|
// Setting the injected warning callback should stay on the client side and do nothing
|
||||||
|
@ -132,14 +144,15 @@ TEST_F(WireErrorCallbackTests, DeviceLoggingCallback) {
|
||||||
// client side
|
// client side
|
||||||
api.CallDeviceSetLoggingCallbackCallback(apiDevice, WGPULoggingType_Info, "Some message");
|
api.CallDeviceSetLoggingCallbackCallback(apiDevice, WGPULoggingType_Info, "Some message");
|
||||||
|
|
||||||
EXPECT_CALL(*mockDeviceLoggingCallback, Call(WGPULoggingType_Info, StrEq("Some message"), this))
|
EXPECT_CALL(*mockDeviceLoggingCallback,
|
||||||
|
Call(WGPULoggingType_Info, StrEq("Some message"), this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the return wire for error scopes.
|
// Test the return wire for error scopes.
|
||||||
TEST_F(WireErrorCallbackTests, PushPopErrorScopeCallback) {
|
TEST_F(WireErrorCallbackTests, PushPopErrorScopeCallback) {
|
||||||
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
||||||
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
@ -156,10 +169,10 @@ TEST_F(WireErrorCallbackTests, PushPopErrorScopeCallback) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
callback(WGPUErrorType_Validation, "Some error message", userdata);
|
callback(WGPUErrorType_Validation, "Some error message", userdata);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the return wire for error scopes when callbacks return in a various orders.
|
// Test the return wire for error scopes when callbacks return in a various orders.
|
||||||
TEST_F(WireErrorCallbackTests, PopErrorScopeCallbackOrdering) {
|
TEST_F(WireErrorCallbackTests, PopErrorScopeCallbackOrdering) {
|
||||||
// Two error scopes are popped, and the first one returns first.
|
// Two error scopes are popped, and the first one returns first.
|
||||||
{
|
{
|
||||||
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(2);
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(2);
|
||||||
|
@ -221,10 +234,10 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeCallbackOrdering) {
|
||||||
callback1(WGPUErrorType_Validation, "First error message", userdata1);
|
callback1(WGPUErrorType_Validation, "First error message", userdata1);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the return wire for error scopes in flight when the device is destroyed.
|
// Test the return wire for error scopes in flight when the device is destroyed.
|
||||||
TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceInFlightDestroy) {
|
TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceInFlightDestroy) {
|
||||||
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
||||||
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
@ -233,15 +246,16 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceInFlightDestroy) {
|
||||||
wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Incomplete callback called in Device destructor. This is resolved after the end of this test.
|
// Incomplete callback called in Device destructor. This is resolved after the end of this
|
||||||
|
// test.
|
||||||
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
||||||
Call(WGPUErrorType_Unknown, ValidStringMessage(), this))
|
Call(WGPUErrorType_Unknown, ValidStringMessage(), this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback then wire disconnect calls the callback with
|
// Test that registering a callback then wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireErrorCallbackTests, PopErrorScopeThenDisconnect) {
|
TEST_F(WireErrorCallbackTests, PopErrorScopeThenDisconnect) {
|
||||||
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
||||||
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
||||||
|
|
||||||
|
@ -253,11 +267,11 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeThenDisconnect) {
|
||||||
Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
|
Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that registering a callback after wire disconnect calls the callback with
|
// Test that registering a callback after wire disconnect calls the callback with
|
||||||
// DeviceLost.
|
// DeviceLost.
|
||||||
TEST_F(WireErrorCallbackTests, PopErrorScopeAfterDisconnect) {
|
TEST_F(WireErrorCallbackTests, PopErrorScopeAfterDisconnect) {
|
||||||
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
|
||||||
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
@ -268,10 +282,10 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeAfterDisconnect) {
|
||||||
Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
|
Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty stack (We are emulating the errors that would be callback-ed from native).
|
// Empty stack (We are emulating the errors that would be callback-ed from native).
|
||||||
TEST_F(WireErrorCallbackTests, PopErrorScopeEmptyStack) {
|
TEST_F(WireErrorCallbackTests, PopErrorScopeEmptyStack) {
|
||||||
WGPUErrorCallback callback;
|
WGPUErrorCallback callback;
|
||||||
void* userdata;
|
void* userdata;
|
||||||
EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
|
EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
|
||||||
|
@ -284,10 +298,10 @@ TEST_F(WireErrorCallbackTests, PopErrorScopeEmptyStack) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
callback(WGPUErrorType_Validation, "No error scopes to pop", userdata);
|
callback(WGPUErrorType_Validation, "No error scopes to pop", userdata);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the return wire for device lost callback
|
// Test the return wire for device lost callback
|
||||||
TEST_F(WireErrorCallbackTests, DeviceLostCallback) {
|
TEST_F(WireErrorCallbackTests, DeviceLostCallback) {
|
||||||
wgpuDeviceSetDeviceLostCallback(device, ToMockDeviceLostCallback, this);
|
wgpuDeviceSetDeviceLostCallback(device, ToMockDeviceLostCallback, this);
|
||||||
|
|
||||||
// Setting the error callback should stay on the client side and do nothing
|
// Setting the error callback should stay on the client side and do nothing
|
||||||
|
@ -303,4 +317,6 @@ TEST_F(WireErrorCallbackTests, DeviceLostCallback) {
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -14,18 +14,23 @@
|
||||||
|
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireExtensionTests : public WireTest {
|
using testing::_;
|
||||||
|
using testing::Invoke;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::Unused;
|
||||||
|
|
||||||
|
class WireExtensionTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireExtensionTests() {
|
WireExtensionTests() {
|
||||||
}
|
}
|
||||||
~WireExtensionTests() override = default;
|
~WireExtensionTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Serialize/Deserializes a chained struct correctly.
|
// Serialize/Deserializes a chained struct correctly.
|
||||||
TEST_F(WireExtensionTests, ChainedStruct) {
|
TEST_F(WireExtensionTests, ChainedStruct) {
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
||||||
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
||||||
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
@ -55,10 +60,10 @@ TEST_F(WireExtensionTests, ChainedStruct) {
|
||||||
return api.GetNewRenderPipeline();
|
return api.GetNewRenderPipeline();
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize/Deserializes multiple chained structs correctly.
|
// Serialize/Deserializes multiple chained structs correctly.
|
||||||
TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
||||||
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
||||||
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
@ -82,8 +87,8 @@ TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||||
|
|
||||||
wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
||||||
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
|
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
|
||||||
.WillOnce(Invoke(
|
.WillOnce(Invoke([&](Unused, const WGPURenderPipelineDescriptor* serverDesc)
|
||||||
[&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
|
-> WGPURenderPipeline {
|
||||||
const auto* ext1 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
|
const auto* ext1 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
|
||||||
serverDesc->primitive.nextInChain);
|
serverDesc->primitive.nextInChain);
|
||||||
EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
|
EXPECT_EQ(ext1->chain.sType, clientExt1.chain.sType);
|
||||||
|
@ -106,8 +111,8 @@ TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||||
|
|
||||||
wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
wgpuDeviceCreateRenderPipeline(device, &renderPipelineDesc);
|
||||||
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
|
EXPECT_CALL(api, DeviceCreateRenderPipeline(apiDevice, NotNull()))
|
||||||
.WillOnce(Invoke(
|
.WillOnce(Invoke([&](Unused, const WGPURenderPipelineDescriptor* serverDesc)
|
||||||
[&](Unused, const WGPURenderPipelineDescriptor* serverDesc) -> WGPURenderPipeline {
|
-> WGPURenderPipeline {
|
||||||
const auto* ext2 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
|
const auto* ext2 = reinterpret_cast<const WGPUPrimitiveDepthClampingState*>(
|
||||||
serverDesc->primitive.nextInChain);
|
serverDesc->primitive.nextInChain);
|
||||||
EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
|
EXPECT_EQ(ext2->chain.sType, clientExt2.chain.sType);
|
||||||
|
@ -122,10 +127,10 @@ TEST_F(WireExtensionTests, MutlipleChainedStructs) {
|
||||||
return api.GetNewRenderPipeline();
|
return api.GetNewRenderPipeline();
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a chained struct with Invalid sType passes through as Invalid.
|
// Test that a chained struct with Invalid sType passes through as Invalid.
|
||||||
TEST_F(WireExtensionTests, InvalidSType) {
|
TEST_F(WireExtensionTests, InvalidSType) {
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
||||||
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
||||||
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
@ -150,10 +155,10 @@ TEST_F(WireExtensionTests, InvalidSType) {
|
||||||
return api.GetNewRenderPipeline();
|
return api.GetNewRenderPipeline();
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a chained struct with unknown sType passes through as Invalid.
|
// Test that a chained struct with unknown sType passes through as Invalid.
|
||||||
TEST_F(WireExtensionTests, UnknownSType) {
|
TEST_F(WireExtensionTests, UnknownSType) {
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
||||||
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
||||||
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
@ -178,11 +183,11 @@ TEST_F(WireExtensionTests, UnknownSType) {
|
||||||
return api.GetNewRenderPipeline();
|
return api.GetNewRenderPipeline();
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that if both an invalid and valid stype are passed on the chain, only the invalid
|
// Test that if both an invalid and valid stype are passed on the chain, only the invalid
|
||||||
// sType passes through as Invalid.
|
// sType passes through as Invalid.
|
||||||
TEST_F(WireExtensionTests, ValidAndInvalidSTypeInChain) {
|
TEST_F(WireExtensionTests, ValidAndInvalidSTypeInChain) {
|
||||||
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
WGPUShaderModuleDescriptor shaderModuleDesc = {};
|
||||||
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
WGPUShaderModule apiShaderModule = api.GetNewShaderModule();
|
||||||
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
WGPUShaderModule shaderModule = wgpuDeviceCreateShaderModule(device, &shaderModuleDesc);
|
||||||
|
@ -238,4 +243,6 @@ TEST_F(WireExtensionTests, ValidAndInvalidSTypeInChain) {
|
||||||
return api.GetNewRenderPipeline();
|
return api.GetNewRenderPipeline();
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,19 +17,23 @@
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
#include "dawn/wire/WireServer.h"
|
#include "dawn/wire/WireServer.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireInjectDeviceTests : public WireTest {
|
using testing::_;
|
||||||
|
using testing::Exactly;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
|
class WireInjectDeviceTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireInjectDeviceTests() {
|
WireInjectDeviceTests() {
|
||||||
}
|
}
|
||||||
~WireInjectDeviceTests() override = default;
|
~WireInjectDeviceTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that reserving and injecting a device makes calls on the client object forward to the
|
// Test that reserving and injecting a device makes calls on the client object forward to the
|
||||||
// server object correctly.
|
// server object correctly.
|
||||||
TEST_F(WireInjectDeviceTests, CallAfterReserveInject) {
|
TEST_F(WireInjectDeviceTests, CallAfterReserveInject) {
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
WGPUDevice serverDevice = api.GetNewDevice();
|
WGPUDevice serverDevice = api.GetNewDevice();
|
||||||
|
@ -49,22 +53,23 @@ TEST_F(WireInjectDeviceTests, CallAfterReserveInject) {
|
||||||
// Called on shutdown.
|
// Called on shutdown.
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(Exactly(1));
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr))
|
||||||
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that reserve correctly returns different IDs each time.
|
// Test that reserve correctly returns different IDs each time.
|
||||||
TEST_F(WireInjectDeviceTests, ReserveDifferentIDs) {
|
TEST_F(WireInjectDeviceTests, ReserveDifferentIDs) {
|
||||||
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
||||||
ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
ASSERT_NE(reservation1.id, reservation2.id);
|
ASSERT_NE(reservation1.id, reservation2.id);
|
||||||
ASSERT_NE(reservation1.device, reservation2.device);
|
ASSERT_NE(reservation1.device, reservation2.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that injecting the same id without a destroy first fails.
|
// Test that injecting the same id without a destroy first fails.
|
||||||
TEST_F(WireInjectDeviceTests, InjectExistingID) {
|
TEST_F(WireInjectDeviceTests, InjectExistingID) {
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
WGPUDevice serverDevice = api.GetNewDevice();
|
WGPUDevice serverDevice = api.GetNewDevice();
|
||||||
|
@ -82,13 +87,14 @@ TEST_F(WireInjectDeviceTests, InjectExistingID) {
|
||||||
// Called on shutdown.
|
// Called on shutdown.
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(Exactly(1));
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr))
|
||||||
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the server only borrows the device and does a single reference-release
|
// Test that the server only borrows the device and does a single reference-release
|
||||||
TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
|
TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
// Injecting the device adds a reference
|
// Injecting the device adds a reference
|
||||||
|
@ -103,7 +109,8 @@ TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
|
||||||
// Releasing the device removes a single reference and clears its error callbacks.
|
// Releasing the device removes a single reference and clears its error callbacks.
|
||||||
wgpuDeviceRelease(reservation.device);
|
wgpuDeviceRelease(reservation.device);
|
||||||
EXPECT_CALL(api, DeviceRelease(serverDevice));
|
EXPECT_CALL(api, DeviceRelease(serverDevice));
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
||||||
|
.Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
@ -111,20 +118,20 @@ TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
|
||||||
// Deleting the server doesn't release a second reference.
|
// Deleting the server doesn't release a second reference.
|
||||||
DeleteServer();
|
DeleteServer();
|
||||||
Mock::VerifyAndClearExpectations(&api);
|
Mock::VerifyAndClearExpectations(&api);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is an error to get the primary queue of a device before it has been
|
// Test that it is an error to get the primary queue of a device before it has been
|
||||||
// injected on the server.
|
// injected on the server.
|
||||||
TEST_F(WireInjectDeviceTests, GetQueueBeforeInject) {
|
TEST_F(WireInjectDeviceTests, GetQueueBeforeInject) {
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
wgpuDeviceGetQueue(reservation.device);
|
wgpuDeviceGetQueue(reservation.device);
|
||||||
FlushClient(false);
|
FlushClient(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is valid to get the primary queue of a device after it has been
|
// Test that it is valid to get the primary queue of a device after it has been
|
||||||
// injected on the server.
|
// injected on the server.
|
||||||
TEST_F(WireInjectDeviceTests, GetQueueAfterInject) {
|
TEST_F(WireInjectDeviceTests, GetQueueAfterInject) {
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
WGPUDevice serverDevice = api.GetNewDevice();
|
WGPUDevice serverDevice = api.GetNewDevice();
|
||||||
|
@ -144,13 +151,14 @@ TEST_F(WireInjectDeviceTests, GetQueueAfterInject) {
|
||||||
// Called on shutdown.
|
// Called on shutdown.
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(Exactly(1));
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr))
|
||||||
|
.Times(Exactly(1));
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, nullptr, nullptr))
|
||||||
.Times(Exactly(1));
|
.Times(Exactly(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the list of live devices can be reflected using GetDevice.
|
// Test that the list of live devices can be reflected using GetDevice.
|
||||||
TEST_F(WireInjectDeviceTests, ReflectLiveDevices) {
|
TEST_F(WireInjectDeviceTests, ReflectLiveDevices) {
|
||||||
// Reserve two devices.
|
// Reserve two devices.
|
||||||
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
||||||
ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation2 = GetWireClient()->ReserveDevice();
|
||||||
|
@ -174,31 +182,36 @@ TEST_F(WireInjectDeviceTests, ReflectLiveDevices) {
|
||||||
GetWireServer()->InjectDevice(serverDevice2, reservation2.id, reservation2.generation));
|
GetWireServer()->InjectDevice(serverDevice2, reservation2.id, reservation2.generation));
|
||||||
|
|
||||||
// Test that both devices can be reflected.
|
// Test that both devices can be reflected.
|
||||||
ASSERT_EQ(serverDevice1, GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
|
ASSERT_EQ(serverDevice1,
|
||||||
ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
|
GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
|
||||||
|
ASSERT_EQ(serverDevice2,
|
||||||
|
GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
|
||||||
|
|
||||||
// Release the first device
|
// Release the first device
|
||||||
wgpuDeviceRelease(reservation1.device);
|
wgpuDeviceRelease(reservation1.device);
|
||||||
EXPECT_CALL(api, DeviceRelease(serverDevice1));
|
EXPECT_CALL(api, DeviceRelease(serverDevice1));
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, nullptr, nullptr))
|
||||||
|
.Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// The first device should no longer reflect, but the second should
|
// The first device should no longer reflect, but the second should
|
||||||
ASSERT_EQ(nullptr, GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
|
ASSERT_EQ(nullptr, GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
|
||||||
ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
|
ASSERT_EQ(serverDevice2,
|
||||||
|
GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
|
||||||
|
|
||||||
// Called on shutdown.
|
// Called on shutdown.
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, nullptr, nullptr))
|
||||||
|
.Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a regression test where a second device reservation invalidated pointers into the
|
// This is a regression test where a second device reservation invalidated pointers into the
|
||||||
// KnownObjects std::vector of devices. The fix was to store pointers to heap allocated
|
// KnownObjects std::vector of devices. The fix was to store pointers to heap allocated
|
||||||
// objects instead.
|
// objects instead.
|
||||||
TEST_F(WireInjectDeviceTests, TrackChildObjectsWithTwoReservedDevices) {
|
TEST_F(WireInjectDeviceTests, TrackChildObjectsWithTwoReservedDevices) {
|
||||||
// Reserve one device, inject it, and get the primary queue.
|
// Reserve one device, inject it, and get the primary queue.
|
||||||
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation1 = GetWireClient()->ReserveDevice();
|
||||||
|
|
||||||
|
@ -237,17 +250,19 @@ TEST_F(WireInjectDeviceTests, TrackChildObjectsWithTwoReservedDevices) {
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Called on shutdown.
|
// Called on shutdown.
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, nullptr, nullptr))
|
||||||
|
.Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, nullptr, nullptr))
|
||||||
|
.Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
||||||
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, nullptr, nullptr)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a device reservation can be reclaimed. This is necessary to
|
// Test that a device reservation can be reclaimed. This is necessary to
|
||||||
// avoid leaking ObjectIDs for reservations that are never injected.
|
// avoid leaking ObjectIDs for reservations that are never injected.
|
||||||
TEST_F(WireInjectDeviceTests, ReclaimDeviceReservation) {
|
TEST_F(WireInjectDeviceTests, ReclaimDeviceReservation) {
|
||||||
// Test that doing a reservation and full release is an error.
|
// Test that doing a reservation and full release is an error.
|
||||||
{
|
{
|
||||||
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
ReservedDevice reservation = GetWireClient()->ReserveDevice();
|
||||||
|
@ -269,4 +284,6 @@ TEST_F(WireInjectDeviceTests, ReclaimDeviceReservation) {
|
||||||
// No errors should occur.
|
// No errors should occur.
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
#include "dawn/wire/WireServer.h"
|
#include "dawn/wire/WireServer.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire { namespace {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::Mock;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
class WireInjectInstanceTests : public WireTest {
|
class WireInjectInstanceTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
|
@ -116,4 +117,6 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
// TODO(https://crbug.com/dawn/1381) Remove when namespaces are not indented.
|
||||||
|
// NOLINTNEXTLINE(readability/namespace)
|
||||||
|
}} // namespace dawn::wire::
|
||||||
|
|
|
@ -17,19 +17,20 @@
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
#include "dawn/wire/WireServer.h"
|
#include "dawn/wire/WireServer.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireInjectSwapChainTests : public WireTest {
|
using testing::Mock;
|
||||||
|
|
||||||
|
class WireInjectSwapChainTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireInjectSwapChainTests() {
|
WireInjectSwapChainTests() {
|
||||||
}
|
}
|
||||||
~WireInjectSwapChainTests() override = default;
|
~WireInjectSwapChainTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that reserving and injecting a swapchain makes calls on the client object forward to the
|
// Test that reserving and injecting a swapchain makes calls on the client object forward to the
|
||||||
// server object correctly.
|
// server object correctly.
|
||||||
TEST_F(WireInjectSwapChainTests, CallAfterReserveInject) {
|
TEST_F(WireInjectSwapChainTests, CallAfterReserveInject) {
|
||||||
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
||||||
|
|
||||||
WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
|
WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
|
||||||
|
@ -41,19 +42,19 @@ TEST_F(WireInjectSwapChainTests, CallAfterReserveInject) {
|
||||||
wgpuSwapChainPresent(reservation.swapchain);
|
wgpuSwapChainPresent(reservation.swapchain);
|
||||||
EXPECT_CALL(api, SwapChainPresent(apiSwapchain));
|
EXPECT_CALL(api, SwapChainPresent(apiSwapchain));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that reserve correctly returns different IDs each time.
|
// Test that reserve correctly returns different IDs each time.
|
||||||
TEST_F(WireInjectSwapChainTests, ReserveDifferentIDs) {
|
TEST_F(WireInjectSwapChainTests, ReserveDifferentIDs) {
|
||||||
ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device);
|
||||||
ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device);
|
||||||
|
|
||||||
ASSERT_NE(reservation1.id, reservation2.id);
|
ASSERT_NE(reservation1.id, reservation2.id);
|
||||||
ASSERT_NE(reservation1.swapchain, reservation2.swapchain);
|
ASSERT_NE(reservation1.swapchain, reservation2.swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that injecting the same id without a destroy first fails.
|
// Test that injecting the same id without a destroy first fails.
|
||||||
TEST_F(WireInjectSwapChainTests, InjectExistingID) {
|
TEST_F(WireInjectSwapChainTests, InjectExistingID) {
|
||||||
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
||||||
|
|
||||||
WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
|
WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
|
||||||
|
@ -66,10 +67,10 @@ TEST_F(WireInjectSwapChainTests, InjectExistingID) {
|
||||||
ASSERT_FALSE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
|
ASSERT_FALSE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
|
||||||
reservation.generation, reservation.deviceId,
|
reservation.generation, reservation.deviceId,
|
||||||
reservation.deviceGeneration));
|
reservation.deviceGeneration));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the server only borrows the swapchain and does a single reference-release
|
// Test that the server only borrows the swapchain and does a single reference-release
|
||||||
TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime) {
|
TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime) {
|
||||||
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
||||||
|
|
||||||
// Injecting the swapchain adds a reference
|
// Injecting the swapchain adds a reference
|
||||||
|
@ -87,11 +88,11 @@ TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime) {
|
||||||
// Deleting the server doesn't release a second reference.
|
// Deleting the server doesn't release a second reference.
|
||||||
DeleteServer();
|
DeleteServer();
|
||||||
Mock::VerifyAndClearExpectations(&api);
|
Mock::VerifyAndClearExpectations(&api);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a swapchain reservation can be reclaimed. This is necessary to
|
// Test that a swapchain reservation can be reclaimed. This is necessary to
|
||||||
// avoid leaking ObjectIDs for reservations that are never injected.
|
// avoid leaking ObjectIDs for reservations that are never injected.
|
||||||
TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation) {
|
TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation) {
|
||||||
// Test that doing a reservation and full release is an error.
|
// Test that doing a reservation and full release is an error.
|
||||||
{
|
{
|
||||||
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device);
|
||||||
|
@ -113,4 +114,6 @@ TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation) {
|
||||||
// No errors should occur.
|
// No errors should occur.
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,65 +17,71 @@
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
#include "dawn/wire/WireServer.h"
|
#include "dawn/wire/WireServer.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireInjectTextureTests : public WireTest {
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
|
class WireInjectTextureTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireInjectTextureTests() {
|
WireInjectTextureTests() {
|
||||||
}
|
}
|
||||||
~WireInjectTextureTests() override = default;
|
~WireInjectTextureTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that reserving and injecting a texture makes calls on the client object forward to the
|
// Test that reserving and injecting a texture makes calls on the client object forward to the
|
||||||
// server object correctly.
|
// server object correctly.
|
||||||
TEST_F(WireInjectTextureTests, CallAfterReserveInject) {
|
TEST_F(WireInjectTextureTests, CallAfterReserveInject) {
|
||||||
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
||||||
|
|
||||||
WGPUTexture apiTexture = api.GetNewTexture();
|
WGPUTexture apiTexture = api.GetNewTexture();
|
||||||
EXPECT_CALL(api, TextureReference(apiTexture));
|
EXPECT_CALL(api, TextureReference(apiTexture));
|
||||||
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
|
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
|
||||||
reservation.deviceId, reservation.deviceGeneration));
|
reservation.generation, reservation.deviceId,
|
||||||
|
reservation.deviceGeneration));
|
||||||
|
|
||||||
wgpuTextureCreateView(reservation.texture, nullptr);
|
wgpuTextureCreateView(reservation.texture, nullptr);
|
||||||
WGPUTextureView apiPlaceholderView = api.GetNewTextureView();
|
WGPUTextureView apiPlaceholderView = api.GetNewTextureView();
|
||||||
EXPECT_CALL(api, TextureCreateView(apiTexture, nullptr)).WillOnce(Return(apiPlaceholderView));
|
EXPECT_CALL(api, TextureCreateView(apiTexture, nullptr))
|
||||||
|
.WillOnce(Return(apiPlaceholderView));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that reserve correctly returns different IDs each time.
|
// Test that reserve correctly returns different IDs each time.
|
||||||
TEST_F(WireInjectTextureTests, ReserveDifferentIDs) {
|
TEST_F(WireInjectTextureTests, ReserveDifferentIDs) {
|
||||||
ReservedTexture reservation1 = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation1 = GetWireClient()->ReserveTexture(device);
|
||||||
ReservedTexture reservation2 = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation2 = GetWireClient()->ReserveTexture(device);
|
||||||
|
|
||||||
ASSERT_NE(reservation1.id, reservation2.id);
|
ASSERT_NE(reservation1.id, reservation2.id);
|
||||||
ASSERT_NE(reservation1.texture, reservation2.texture);
|
ASSERT_NE(reservation1.texture, reservation2.texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that injecting the same id without a destroy first fails.
|
// Test that injecting the same id without a destroy first fails.
|
||||||
TEST_F(WireInjectTextureTests, InjectExistingID) {
|
TEST_F(WireInjectTextureTests, InjectExistingID) {
|
||||||
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
||||||
|
|
||||||
WGPUTexture apiTexture = api.GetNewTexture();
|
WGPUTexture apiTexture = api.GetNewTexture();
|
||||||
EXPECT_CALL(api, TextureReference(apiTexture));
|
EXPECT_CALL(api, TextureReference(apiTexture));
|
||||||
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
|
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
|
||||||
reservation.deviceId, reservation.deviceGeneration));
|
reservation.generation, reservation.deviceId,
|
||||||
|
reservation.deviceGeneration));
|
||||||
|
|
||||||
// ID already in use, call fails.
|
// ID already in use, call fails.
|
||||||
ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
|
ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
|
||||||
reservation.deviceId,
|
reservation.generation, reservation.deviceId,
|
||||||
reservation.deviceGeneration));
|
reservation.deviceGeneration));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the server only borrows the texture and does a single reference-release
|
// Test that the server only borrows the texture and does a single reference-release
|
||||||
TEST_F(WireInjectTextureTests, InjectedTextureLifetime) {
|
TEST_F(WireInjectTextureTests, InjectedTextureLifetime) {
|
||||||
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
||||||
|
|
||||||
// Injecting the texture adds a reference
|
// Injecting the texture adds a reference
|
||||||
WGPUTexture apiTexture = api.GetNewTexture();
|
WGPUTexture apiTexture = api.GetNewTexture();
|
||||||
EXPECT_CALL(api, TextureReference(apiTexture));
|
EXPECT_CALL(api, TextureReference(apiTexture));
|
||||||
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
|
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
|
||||||
reservation.deviceId, reservation.deviceGeneration));
|
reservation.generation, reservation.deviceId,
|
||||||
|
reservation.deviceGeneration));
|
||||||
|
|
||||||
// Releasing the texture removes a single reference.
|
// Releasing the texture removes a single reference.
|
||||||
wgpuTextureRelease(reservation.texture);
|
wgpuTextureRelease(reservation.texture);
|
||||||
|
@ -85,11 +91,11 @@ TEST_F(WireInjectTextureTests, InjectedTextureLifetime) {
|
||||||
// Deleting the server doesn't release a second reference.
|
// Deleting the server doesn't release a second reference.
|
||||||
DeleteServer();
|
DeleteServer();
|
||||||
Mock::VerifyAndClearExpectations(&api);
|
Mock::VerifyAndClearExpectations(&api);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a texture reservation can be reclaimed. This is necessary to
|
// Test that a texture reservation can be reclaimed. This is necessary to
|
||||||
// avoid leaking ObjectIDs for reservations that are never injected.
|
// avoid leaking ObjectIDs for reservations that are never injected.
|
||||||
TEST_F(WireInjectTextureTests, ReclaimTextureReservation) {
|
TEST_F(WireInjectTextureTests, ReclaimTextureReservation) {
|
||||||
// Test that doing a reservation and full release is an error.
|
// Test that doing a reservation and full release is an error.
|
||||||
{
|
{
|
||||||
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
ReservedTexture reservation = GetWireClient()->ReserveTexture(device);
|
||||||
|
@ -111,4 +117,6 @@ TEST_F(WireInjectTextureTests, ReclaimTextureReservation) {
|
||||||
// No errors should occur.
|
// No errors should occur.
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -23,10 +23,16 @@
|
||||||
|
|
||||||
#include "webgpu/webgpu_cpp.h"
|
#include "webgpu/webgpu_cpp.h"
|
||||||
|
|
||||||
namespace {
|
namespace dawn::wire { namespace {
|
||||||
|
|
||||||
using namespace testing;
|
using testing::Invoke;
|
||||||
using namespace dawn::wire;
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::MockCallback;
|
||||||
|
using testing::NotNull;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::SetArgPointee;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::WithArg;
|
||||||
|
|
||||||
class WireInstanceBasicTest : public WireTest {};
|
class WireInstanceBasicTest : public WireTest {};
|
||||||
class WireInstanceTests : public WireTest {
|
class WireInstanceTests : public WireTest {
|
||||||
|
@ -284,4 +290,6 @@ namespace {
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
// TODO(https://crbug.com/dawn/1381) Remove when namespaces are not indented.
|
||||||
|
// NOLINTNEXTLINE(readability/namespace)
|
||||||
|
}} // namespace dawn::wire::
|
||||||
|
|
|
@ -19,10 +19,18 @@
|
||||||
#include "dawn/wire/client/ClientMemoryTransferService_mock.h"
|
#include "dawn/wire/client/ClientMemoryTransferService_mock.h"
|
||||||
#include "dawn/wire/server/ServerMemoryTransferService_mock.h"
|
#include "dawn/wire/server/ServerMemoryTransferService_mock.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::Eq;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Pointee;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::StrictMock;
|
||||||
|
using testing::WithArg;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Mock class to add expectations on the wire calling callbacks
|
// Mock class to add expectations on the wire calling callbacks
|
||||||
class MockBufferMapCallback {
|
class MockBufferMapCallback {
|
||||||
|
@ -35,21 +43,21 @@ namespace {
|
||||||
mockBufferMapCallback->Call(status, userdata);
|
mockBufferMapCallback->Call(status, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
// WireMemoryTransferServiceTests test the MemoryTransferService with buffer mapping.
|
// WireMemoryTransferServiceTests test the MemoryTransferService with buffer mapping.
|
||||||
// They test the basic success and error cases for buffer mapping, and they test
|
// They test the basic success and error cases for buffer mapping, and they test
|
||||||
// mocked failures of each fallible MemoryTransferService method that an embedder
|
// mocked failures of each fallible MemoryTransferService method that an embedder
|
||||||
// could implement.
|
// could implement.
|
||||||
// The test harness defines multiple helpers for expecting operations on Read/Write handles
|
// The test harness defines multiple helpers for expecting operations on Read/Write handles
|
||||||
// and for mocking failures. The helpers are designed such that for a given run of a test,
|
// and for mocking failures. The helpers are designed such that for a given run of a test,
|
||||||
// a Serialization expection has a corresponding Deserialization expectation for which the
|
// a Serialization expection has a corresponding Deserialization expectation for which the
|
||||||
// serialized data must match.
|
// serialized data must match.
|
||||||
// There are tests which check for Success for every mapping operation which mock an entire mapping
|
// There are tests which check for Success for every mapping operation which mock an entire
|
||||||
// operation from map to unmap, and add all MemoryTransferService expectations.
|
// mapping operation from map to unmap, and add all MemoryTransferService expectations. Tests
|
||||||
// Tests which check for errors perform the same mapping operations but insert mocked failures for
|
// which check for errors perform the same mapping operations but insert mocked failures for
|
||||||
// various mapping or MemoryTransferService operations.
|
// various mapping or MemoryTransferService operations.
|
||||||
class WireMemoryTransferServiceTests : public WireTest {
|
class WireMemoryTransferServiceTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireMemoryTransferServiceTests() {
|
WireMemoryTransferServiceTests() {
|
||||||
}
|
}
|
||||||
|
@ -102,7 +110,8 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
using ClientWriteHandle = client::MockMemoryTransferService::MockWriteHandle;
|
using ClientWriteHandle = client::MockMemoryTransferService::MockWriteHandle;
|
||||||
using ServerWriteHandle = server::MockMemoryTransferService::MockWriteHandle;
|
using ServerWriteHandle = server::MockMemoryTransferService::MockWriteHandle;
|
||||||
|
|
||||||
std::pair<WGPUBuffer, WGPUBuffer> CreateBuffer(WGPUBufferUsage usage = WGPUBufferUsage_None) {
|
std::pair<WGPUBuffer, WGPUBuffer> CreateBuffer(
|
||||||
|
WGPUBufferUsage usage = WGPUBufferUsage_None) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = kBufferSize;
|
descriptor.size = kBufferSize;
|
||||||
descriptor.usage = usage;
|
descriptor.usage = usage;
|
||||||
|
@ -185,7 +194,8 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
void ExpectServerReadHandleSerializeDataUpdate(ServerReadHandle* handle) {
|
void ExpectServerReadHandleSerializeDataUpdate(ServerReadHandle* handle) {
|
||||||
EXPECT_CALL(serverMemoryTransferService,
|
EXPECT_CALL(serverMemoryTransferService,
|
||||||
OnReadHandleSizeOfSerializeDataUpdate(handle, _, _))
|
OnReadHandleSizeOfSerializeDataUpdate(handle, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mReadHandleSerializeDataInfo); }));
|
.WillOnce(
|
||||||
|
InvokeWithoutArgs([&]() { return sizeof(mReadHandleSerializeDataInfo); }));
|
||||||
EXPECT_CALL(serverMemoryTransferService,
|
EXPECT_CALL(serverMemoryTransferService,
|
||||||
OnReadHandleSerializeDataUpdate(handle, _, _, _, _))
|
OnReadHandleSerializeDataUpdate(handle, _, _, _, _))
|
||||||
.WillOnce(WithArg<4>([&](void* serializePointer) {
|
.WillOnce(WithArg<4>([&](void* serializePointer) {
|
||||||
|
@ -266,8 +276,10 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
void ExpectClientWriteHandleSerializeDataUpdate(ClientWriteHandle* handle) {
|
void ExpectClientWriteHandleSerializeDataUpdate(ClientWriteHandle* handle) {
|
||||||
EXPECT_CALL(clientMemoryTransferService,
|
EXPECT_CALL(clientMemoryTransferService,
|
||||||
OnWriteHandleSizeOfSerializeDataUpdate(handle, _, _))
|
OnWriteHandleSizeOfSerializeDataUpdate(handle, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mWriteHandleSerializeDataInfo); }));
|
.WillOnce(
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleSerializeDataUpdate(handle, _, _, _))
|
InvokeWithoutArgs([&]() { return sizeof(mWriteHandleSerializeDataInfo); }));
|
||||||
|
EXPECT_CALL(clientMemoryTransferService,
|
||||||
|
OnWriteHandleSerializeDataUpdate(handle, _, _, _))
|
||||||
.WillOnce(WithArg<1>([&](void* serializePointer) {
|
.WillOnce(WithArg<1>([&](void* serializePointer) {
|
||||||
memcpy(serializePointer, &mWriteHandleSerializeDataInfo,
|
memcpy(serializePointer, &mWriteHandleSerializeDataInfo,
|
||||||
sizeof(mWriteHandleSerializeDataInfo));
|
sizeof(mWriteHandleSerializeDataInfo));
|
||||||
|
@ -277,17 +289,17 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
|
|
||||||
void ExpectServerWriteHandleDeserializeDataUpdate(ServerWriteHandle* handle,
|
void ExpectServerWriteHandleDeserializeDataUpdate(ServerWriteHandle* handle,
|
||||||
uint32_t expectedData) {
|
uint32_t expectedData) {
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(serverMemoryTransferService,
|
||||||
serverMemoryTransferService,
|
OnWriteHandleDeserializeDataUpdate(
|
||||||
OnWriteHandleDeserializeDataUpdate(handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
||||||
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockServerWriteHandleDeserializeDataUpdateFailure(ServerWriteHandle* handle) {
|
void MockServerWriteHandleDeserializeDataUpdateFailure(ServerWriteHandle* handle) {
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(serverMemoryTransferService,
|
||||||
serverMemoryTransferService,
|
OnWriteHandleDeserializeDataUpdate(
|
||||||
OnWriteHandleDeserializeDataUpdate(handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
||||||
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
||||||
.WillOnce(Return(false));
|
.WillOnce(Return(false));
|
||||||
}
|
}
|
||||||
|
@ -313,18 +325,18 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
// mUpdatedBufferContent| after all writes are flushed.
|
// mUpdatedBufferContent| after all writes are flushed.
|
||||||
static uint32_t mUpdatedBufferContent;
|
static uint32_t mUpdatedBufferContent;
|
||||||
|
|
||||||
testing::StrictMock<dawn::wire::server::MockMemoryTransferService> serverMemoryTransferService;
|
StrictMock<dawn::wire::server::MockMemoryTransferService> serverMemoryTransferService;
|
||||||
testing::StrictMock<dawn::wire::client::MockMemoryTransferService> clientMemoryTransferService;
|
StrictMock<dawn::wire::client::MockMemoryTransferService> clientMemoryTransferService;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t WireMemoryTransferServiceTests::mBufferContent = 1337;
|
uint32_t WireMemoryTransferServiceTests::mBufferContent = 1337;
|
||||||
uint32_t WireMemoryTransferServiceTests::mUpdatedBufferContent = 2349;
|
uint32_t WireMemoryTransferServiceTests::mUpdatedBufferContent = 2349;
|
||||||
uint32_t WireMemoryTransferServiceTests::mSerializeCreateInfo = 4242;
|
uint32_t WireMemoryTransferServiceTests::mSerializeCreateInfo = 4242;
|
||||||
uint32_t WireMemoryTransferServiceTests::mReadHandleSerializeDataInfo = 1394;
|
uint32_t WireMemoryTransferServiceTests::mReadHandleSerializeDataInfo = 1394;
|
||||||
uint32_t WireMemoryTransferServiceTests::mWriteHandleSerializeDataInfo = 1235;
|
uint32_t WireMemoryTransferServiceTests::mWriteHandleSerializeDataInfo = 1235;
|
||||||
|
|
||||||
// Test successful mapping for reading.
|
// Test successful mapping for reading.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadSuccess) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -340,7 +352,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadSuccess) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// The handle serialize data update on mapAsync cmd
|
// The handle serialize data update on mapAsync cmd
|
||||||
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
||||||
|
@ -373,10 +386,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadSuccess) {
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test ReadHandle destroy behavior
|
// Test ReadHandle destroy behavior
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroy) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroy) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -399,10 +412,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroy) {
|
||||||
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test unsuccessful mapping for reading.
|
// Test unsuccessful mapping for reading.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadError) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadError) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -416,12 +429,14 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadError) {
|
||||||
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Mock a failed callback.
|
// Mock a failed callback.
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -439,10 +454,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadError) {
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test ReadHandle creation failure.
|
// Test ReadHandle creation failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadHandleCreationFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadHandleCreationFailure) {
|
||||||
// Mock a ReadHandle creation failure
|
// Mock a ReadHandle creation failure
|
||||||
MockReadHandleCreationFailure();
|
MockReadHandleCreationFailure();
|
||||||
|
|
||||||
|
@ -451,10 +466,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadHandleCreationFailure) {
|
||||||
descriptor.usage = WGPUBufferUsage_MapRead;
|
descriptor.usage = WGPUBufferUsage_MapRead;
|
||||||
|
|
||||||
wgpuDeviceCreateBuffer(device, &descriptor);
|
wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test MapRead DeserializeReadHandle failure.
|
// Test MapRead DeserializeReadHandle failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeReadHandleFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeReadHandleFailure) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -471,10 +486,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeReadHandleFailure
|
||||||
|
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test read handle DeserializeDataUpdate failure.
|
// Test read handle DeserializeDataUpdate failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeDataUpdateFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeDataUpdateFailure) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -489,7 +504,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeDataUpdateFailure
|
||||||
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// The handle serialize data update on mapAsync cmd
|
// The handle serialize data update on mapAsync cmd
|
||||||
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
||||||
|
@ -517,10 +533,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeDataUpdateFailure
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mapping for reading destroying the buffer before unmapping on the client side.
|
// Test mapping for reading destroying the buffer before unmapping on the client side.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroyBeforeUnmap) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroyBeforeUnmap) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -535,7 +551,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroyBeforeUnmap) {
|
||||||
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// The handle serialize data update on mapAsync cmd
|
// The handle serialize data update on mapAsync cmd
|
||||||
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
||||||
|
@ -576,10 +593,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroyBeforeUnmap) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful mapping for writing.
|
// Test successful mapping for writing.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteSuccess) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -593,7 +610,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteSuccess) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Mock a successful callback.
|
// Mock a successful callback.
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -630,10 +648,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteSuccess) {
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test WriteHandle destroy behavior
|
// Test WriteHandle destroy behavior
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroy) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroy) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -654,14 +672,15 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroy) {
|
||||||
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test unsuccessful MapWrite.
|
// Test unsuccessful MapWrite.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteError) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteError) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
// The client should create and serialize a WriteHandle on buffer creation with MapWrite usage.
|
// The client should create and serialize a WriteHandle on buffer creation with MapWrite
|
||||||
|
// usage.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
|
||||||
|
@ -672,12 +691,14 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteError) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Mock an error callback.
|
// Mock an error callback.
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs(
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
}));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -695,10 +716,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteError) {
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test WriteHandle creation failure.
|
// Test WriteHandle creation failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteHandleCreationFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteHandleCreationFailure) {
|
||||||
// Mock a WriteHandle creation failure
|
// Mock a WriteHandle creation failure
|
||||||
MockWriteHandleCreationFailure();
|
MockWriteHandleCreationFailure();
|
||||||
|
|
||||||
|
@ -707,14 +728,15 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteHandleCreationFailure) {
|
||||||
descriptor.usage = WGPUBufferUsage_MapWrite;
|
descriptor.usage = WGPUBufferUsage_MapWrite;
|
||||||
|
|
||||||
wgpuDeviceCreateBuffer(device, &descriptor);
|
wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test MapWrite DeserializeWriteHandle failure.
|
// Test MapWrite DeserializeWriteHandle failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeWriteHandleFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeWriteHandleFailure) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
// The client should create and serialize a WriteHandle on buffer creation with MapWrite usage.
|
// The client should create and serialize a WriteHandle on buffer creation with MapWrite
|
||||||
|
// usage.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
|
||||||
|
@ -727,10 +749,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeWriteHandleFailu
|
||||||
|
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test MapWrite DeserializeDataUpdate failure.
|
// Test MapWrite DeserializeDataUpdate failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeDataUpdateFailure) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeDataUpdateFailure) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -744,7 +766,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeDataUpdateFailur
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Mock a successful callback.
|
// Mock a successful callback.
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -779,10 +802,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeDataUpdateFailur
|
||||||
// The handle is destroyed once the buffer is destroyed.
|
// The handle is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test MapWrite destroying the buffer before unmapping on the client side.
|
// Test MapWrite destroying the buffer before unmapping on the client side.
|
||||||
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
||||||
WGPUBuffer buffer;
|
WGPUBuffer buffer;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUBuffer apiBuffer;
|
||||||
|
|
||||||
|
@ -796,7 +819,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
// Mock a successful callback.
|
// Mock a successful callback.
|
||||||
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
||||||
|
@ -836,10 +860,10 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful buffer creation with mappedAtCreation = true.
|
// Test successful buffer creation with mappedAtCreation = true.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
@ -870,10 +894,10 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
||||||
// Mock a WriteHandle creation failure
|
// Mock a WriteHandle creation failure
|
||||||
MockWriteHandleCreationFailure();
|
MockWriteHandleCreationFailure();
|
||||||
|
|
||||||
|
@ -883,10 +907,10 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailur
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
@ -908,10 +932,10 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFai
|
||||||
FlushClient(false);
|
FlushClient(false);
|
||||||
|
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation = true DeserializeDataUpdate failure.
|
// Test buffer creation with mappedAtCreation = true DeserializeDataUpdate failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeDataUpdateFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeDataUpdateFailure) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
@ -942,10 +966,10 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeDataUpdateFail
|
||||||
// Failed BufferUpdateMappedData cmd will early return so BufferUnmap is not processed.
|
// Failed BufferUpdateMappedData cmd will early return so BufferUnmap is not processed.
|
||||||
// The server side writeHandle is destructed at buffer destruction.
|
// The server side writeHandle is destructed at buffer destruction.
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
||||||
ExpectWriteHandleSerialization(clientHandle);
|
ExpectWriteHandleSerialization(clientHandle);
|
||||||
|
@ -977,12 +1001,13 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a buffer with mappedAtCreation and MapRead usage destroy WriteHandle on unmap and switch
|
// Test a buffer with mappedAtCreation and MapRead usage destroy WriteHandle on unmap and switch
|
||||||
// data pointer to ReadHandle
|
// data pointer to ReadHandle
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapReadSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapReadSuccess) {
|
||||||
// The client should create and serialize a ReadHandle and a WriteHandle on createBufferMapped.
|
// The client should create and serialize a ReadHandle and a WriteHandle on
|
||||||
|
// createBufferMapped.
|
||||||
ClientReadHandle* clientReadHandle = ExpectReadHandleCreation();
|
ClientReadHandle* clientReadHandle = ExpectReadHandleCreation();
|
||||||
ExpectReadHandleSerialization(clientReadHandle);
|
ExpectReadHandleSerialization(clientReadHandle);
|
||||||
ClientWriteHandle* clientWriteHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientWriteHandle = ExpectWriteHandleCreation(true);
|
||||||
|
@ -1017,10 +1042,10 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapReadSuccess) {
|
||||||
// The ReadHandle will be destoryed on buffer destroy.
|
// The ReadHandle will be destoryed on buffer destroy.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientReadHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientReadHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverReadHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverReadHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test WriteHandle preserves after unmap for a buffer with mappedAtCreation and MapWrite usage
|
// Test WriteHandle preserves after unmap for a buffer with mappedAtCreation and MapWrite usage
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapWriteSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapWriteSuccess) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
||||||
|
|
||||||
|
@ -1051,4 +1076,6 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapWriteSuccess) {
|
||||||
// The writeHandle is preserved after unmap and is destroyed once the buffer is destroyed.
|
// The writeHandle is preserved after unmap and is destroyed once the buffer is destroyed.
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -14,18 +14,20 @@
|
||||||
|
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class WireOptionalTests : public WireTest {
|
using testing::_;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
|
class WireOptionalTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireOptionalTests() {
|
WireOptionalTests() {
|
||||||
}
|
}
|
||||||
~WireOptionalTests() override = default;
|
~WireOptionalTests() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test passing nullptr instead of objects - object as value version
|
// Test passing nullptr instead of objects - object as value version
|
||||||
TEST_F(WireOptionalTests, OptionalObjectValue) {
|
TEST_F(WireOptionalTests, OptionalObjectValue) {
|
||||||
WGPUBindGroupLayoutDescriptor bglDesc = {};
|
WGPUBindGroupLayoutDescriptor bglDesc = {};
|
||||||
bglDesc.entryCount = 0;
|
bglDesc.entryCount = 0;
|
||||||
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bglDesc);
|
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bglDesc);
|
||||||
|
@ -50,7 +52,8 @@ TEST_F(WireOptionalTests, OptionalObjectValue) {
|
||||||
wgpuDeviceCreateBindGroup(device, &bgDesc);
|
wgpuDeviceCreateBindGroup(device, &bgDesc);
|
||||||
|
|
||||||
WGPUBindGroup apiPlaceholderBindGroup = api.GetNewBindGroup();
|
WGPUBindGroup apiPlaceholderBindGroup = api.GetNewBindGroup();
|
||||||
EXPECT_CALL(api, DeviceCreateBindGroup(
|
EXPECT_CALL(api,
|
||||||
|
DeviceCreateBindGroup(
|
||||||
apiDevice, MatchesLambda([](const WGPUBindGroupDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const WGPUBindGroupDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr && desc->entryCount == 1 &&
|
return desc->nextInChain == nullptr && desc->entryCount == 1 &&
|
||||||
desc->entries[0].binding == 0 &&
|
desc->entries[0].binding == 0 &&
|
||||||
|
@ -61,10 +64,10 @@ TEST_F(WireOptionalTests, OptionalObjectValue) {
|
||||||
.WillOnce(Return(apiPlaceholderBindGroup));
|
.WillOnce(Return(apiPlaceholderBindGroup));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the wire is able to send optional pointers to structures
|
// Test that the wire is able to send optional pointers to structures
|
||||||
TEST_F(WireOptionalTests, OptionalStructPointer) {
|
TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
// Create shader module
|
// Create shader module
|
||||||
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
WGPUShaderModuleDescriptor vertexDescriptor = {};
|
||||||
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
WGPUShaderModule vsModule = wgpuDeviceCreateShaderModule(device, &vertexDescriptor);
|
||||||
|
@ -149,11 +152,13 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
desc->depthStencil->depthCompare == WGPUCompareFunction_Always &&
|
desc->depthStencil->depthCompare == WGPUCompareFunction_Always &&
|
||||||
desc->depthStencil->stencilBack.compare == WGPUCompareFunction_Always &&
|
desc->depthStencil->stencilBack.compare == WGPUCompareFunction_Always &&
|
||||||
desc->depthStencil->stencilBack.failOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilBack.failOp == WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilBack.depthFailOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilBack.depthFailOp ==
|
||||||
|
WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilBack.passOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilBack.passOp == WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilFront.compare == WGPUCompareFunction_Always &&
|
desc->depthStencil->stencilFront.compare == WGPUCompareFunction_Always &&
|
||||||
desc->depthStencil->stencilFront.failOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilFront.failOp == WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilFront.depthFailOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilFront.depthFailOp ==
|
||||||
|
WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilFront.passOp == WGPUStencilOperation_Keep &&
|
desc->depthStencil->stencilFront.passOp == WGPUStencilOperation_Keep &&
|
||||||
desc->depthStencil->stencilReadMask == 0xff &&
|
desc->depthStencil->stencilReadMask == 0xff &&
|
||||||
desc->depthStencil->stencilWriteMask == 0xff &&
|
desc->depthStencil->stencilWriteMask == 0xff &&
|
||||||
|
@ -168,12 +173,14 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
// Second case: depthStencil is null.
|
// Second case: depthStencil is null.
|
||||||
pipelineDescriptor.depthStencil = nullptr;
|
pipelineDescriptor.depthStencil = nullptr;
|
||||||
wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
wgpuDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||||
EXPECT_CALL(api,
|
EXPECT_CALL(
|
||||||
DeviceCreateRenderPipeline(
|
api, DeviceCreateRenderPipeline(
|
||||||
apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const WGPURenderPipelineDescriptor* desc) -> bool {
|
||||||
return desc->depthStencil == nullptr;
|
return desc->depthStencil == nullptr;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(apiPlaceholderPipeline));
|
.WillOnce(Return(apiPlaceholderPipeline));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,20 +17,23 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
class MockQueueWorkDoneCallback {
|
using testing::_;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::Mock;
|
||||||
|
|
||||||
|
class MockQueueWorkDoneCallback {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::unique_ptr<MockQueueWorkDoneCallback> mockQueueWorkDoneCallback;
|
static std::unique_ptr<MockQueueWorkDoneCallback> mockQueueWorkDoneCallback;
|
||||||
static void ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status, void* userdata) {
|
static void ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status, void* userdata) {
|
||||||
mockQueueWorkDoneCallback->Call(status, userdata);
|
mockQueueWorkDoneCallback->Call(status, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WireQueueTests : public WireTest {
|
class WireQueueTests : public WireTest {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
WireTest::SetUp();
|
WireTest::SetUp();
|
||||||
|
@ -46,10 +49,10 @@ class WireQueueTests : public WireTest {
|
||||||
WireTest::FlushServer();
|
WireTest::FlushServer();
|
||||||
Mock::VerifyAndClearExpectations(&mockQueueWorkDoneCallback);
|
Mock::VerifyAndClearExpectations(&mockQueueWorkDoneCallback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that a successful OnSubmittedWorkDone call is forwarded to the client.
|
// Test that a successful OnSubmittedWorkDone call is forwarded to the client.
|
||||||
TEST_F(WireQueueTests, OnSubmittedWorkDoneSuccess) {
|
TEST_F(WireQueueTests, OnSubmittedWorkDoneSuccess) {
|
||||||
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
||||||
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() {
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -57,12 +60,13 @@ TEST_F(WireQueueTests, OnSubmittedWorkDoneSuccess) {
|
||||||
}));
|
}));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this))
|
||||||
|
.Times(1);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that an error OnSubmittedWorkDone call is forwarded as an error to the client.
|
// Test that an error OnSubmittedWorkDone call is forwarded as an error to the client.
|
||||||
TEST_F(WireQueueTests, OnSubmittedWorkDoneError) {
|
TEST_F(WireQueueTests, OnSubmittedWorkDoneError) {
|
||||||
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
||||||
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() {
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -72,11 +76,11 @@ TEST_F(WireQueueTests, OnSubmittedWorkDoneError) {
|
||||||
|
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Error, this)).Times(1);
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Error, this)).Times(1);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering an OnSubmittedWorkDone then disconnecting the wire calls the callback with
|
// Test registering an OnSubmittedWorkDone then disconnecting the wire calls the callback with
|
||||||
// device loss
|
// device loss
|
||||||
TEST_F(WireQueueTests, OnSubmittedWorkDoneBeforeDisconnect) {
|
TEST_F(WireQueueTests, OnSubmittedWorkDoneBeforeDisconnect) {
|
||||||
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
||||||
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
||||||
.WillOnce(InvokeWithoutArgs([&]() {
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -87,26 +91,26 @@ TEST_F(WireQueueTests, OnSubmittedWorkDoneBeforeDisconnect) {
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test registering an OnSubmittedWorkDone after disconnecting the wire calls the callback with
|
// Test registering an OnSubmittedWorkDone after disconnecting the wire calls the callback with
|
||||||
// device loss
|
// device loss
|
||||||
TEST_F(WireQueueTests, OnSubmittedWorkDoneAfterDisconnect) {
|
TEST_F(WireQueueTests, OnSubmittedWorkDoneAfterDisconnect) {
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
|
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack to pass in test context into user callback
|
// Hack to pass in test context into user callback
|
||||||
struct TestData {
|
struct TestData {
|
||||||
WireQueueTests* pTest;
|
WireQueueTests* pTest;
|
||||||
WGPUQueue* pTestQueue;
|
WGPUQueue* pTestQueue;
|
||||||
size_t numRequests;
|
size_t numRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ToMockQueueWorkDoneWithNewRequests(WGPUQueueWorkDoneStatus status, void* userdata) {
|
static void ToMockQueueWorkDoneWithNewRequests(WGPUQueueWorkDoneStatus status, void* userdata) {
|
||||||
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
||||||
// Mimic the user callback is sending new requests
|
// Mimic the user callback is sending new requests
|
||||||
ASSERT_NE(testData, nullptr);
|
ASSERT_NE(testData, nullptr);
|
||||||
|
@ -119,10 +123,10 @@ static void ToMockQueueWorkDoneWithNewRequests(WGPUQueueWorkDoneStatus status, v
|
||||||
wgpuQueueOnSubmittedWorkDone(*(testData->pTestQueue), 0u, ToMockQueueWorkDone,
|
wgpuQueueOnSubmittedWorkDone(*(testData->pTestQueue), 0u, ToMockQueueWorkDone,
|
||||||
testData->pTest);
|
testData->pTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that requests inside user callbacks before disconnect are called
|
// Test that requests inside user callbacks before disconnect are called
|
||||||
TEST_F(WireQueueTests, OnSubmittedWorkDoneInsideCallbackBeforeDisconnect) {
|
TEST_F(WireQueueTests, OnSubmittedWorkDoneInsideCallbackBeforeDisconnect) {
|
||||||
TestData testData = {this, &queue, 10};
|
TestData testData = {this, &queue, 10};
|
||||||
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDoneWithNewRequests, &testData);
|
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDoneWithNewRequests, &testData);
|
||||||
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
|
||||||
|
@ -134,8 +138,10 @@ TEST_F(WireQueueTests, OnSubmittedWorkDoneInsideCallbackBeforeDisconnect) {
|
||||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
|
||||||
.Times(1 + testData.numRequests);
|
.Times(1 + testData.numRequests);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only one default queue is supported now so we cannot test ~Queue triggering ClearAllCallbacks
|
// Only one default queue is supported now so we cannot test ~Queue triggering ClearAllCallbacks
|
||||||
// since it is always destructed after the test TearDown, and we cannot create a new queue obj
|
// since it is always destructed after the test TearDown, and we cannot create a new queue obj
|
||||||
// with wgpuDeviceGetQueue
|
// with wgpuDeviceGetQueue
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -17,10 +17,15 @@
|
||||||
#include "dawn/tests/unittests/wire/WireTest.h"
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
|
|
||||||
using namespace testing;
|
namespace dawn::wire {
|
||||||
using namespace dawn::wire;
|
|
||||||
|
|
||||||
namespace {
|
using testing::_;
|
||||||
|
using testing::InvokeWithoutArgs;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::StrictMock;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Mock class to add expectations on the wire calling callbacks
|
// Mock class to add expectations on the wire calling callbacks
|
||||||
class MockCompilationInfoCallback {
|
class MockCompilationInfoCallback {
|
||||||
|
@ -39,9 +44,9 @@ namespace {
|
||||||
mockCompilationInfoCallback->Call(status, info, userdata);
|
mockCompilationInfoCallback->Call(status, info, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireShaderModuleTests : public WireTest {
|
class WireShaderModuleTests : public WireTest {
|
||||||
public:
|
public:
|
||||||
WireShaderModuleTests() {
|
WireShaderModuleTests() {
|
||||||
}
|
}
|
||||||
|
@ -50,7 +55,8 @@ class WireShaderModuleTests : public WireTest {
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
WireTest::SetUp();
|
WireTest::SetUp();
|
||||||
|
|
||||||
mockCompilationInfoCallback = std::make_unique<StrictMock<MockCompilationInfoCallback>>();
|
mockCompilationInfoCallback =
|
||||||
|
std::make_unique<StrictMock<MockCompilationInfoCallback>>();
|
||||||
apiShaderModule = api.GetNewShaderModule();
|
apiShaderModule = api.GetNewShaderModule();
|
||||||
|
|
||||||
WGPUShaderModuleDescriptor descriptor = {};
|
WGPUShaderModuleDescriptor descriptor = {};
|
||||||
|
@ -82,10 +88,10 @@ class WireShaderModuleTests : public WireTest {
|
||||||
protected:
|
protected:
|
||||||
WGPUShaderModule shaderModule;
|
WGPUShaderModule shaderModule;
|
||||||
WGPUShaderModule apiShaderModule;
|
WGPUShaderModule apiShaderModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check getting CompilationInfo for a successfully created shader module
|
// Check getting CompilationInfo for a successfully created shader module
|
||||||
TEST_F(WireShaderModuleTests, GetCompilationInfo) {
|
TEST_F(WireShaderModuleTests, GetCompilationInfo) {
|
||||||
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
||||||
|
|
||||||
WGPUCompilationMessage message = {
|
WGPUCompilationMessage message = {
|
||||||
|
@ -121,11 +127,11 @@ TEST_F(WireShaderModuleTests, GetCompilationInfo) {
|
||||||
_))
|
_))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that calling GetCompilationInfo then disconnecting the wire calls the callback with a device
|
// Test that calling GetCompilationInfo then disconnecting the wire calls the callback with a
|
||||||
// loss.
|
// device loss.
|
||||||
TEST_F(WireShaderModuleTests, GetCompilationInfoBeforeDisconnect) {
|
TEST_F(WireShaderModuleTests, GetCompilationInfoBeforeDisconnect) {
|
||||||
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
||||||
|
|
||||||
WGPUCompilationMessage message = {
|
WGPUCompilationMessage message = {
|
||||||
|
@ -145,25 +151,25 @@ TEST_F(WireShaderModuleTests, GetCompilationInfoBeforeDisconnect) {
|
||||||
EXPECT_CALL(*mockCompilationInfoCallback,
|
EXPECT_CALL(*mockCompilationInfoCallback,
|
||||||
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _));
|
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _));
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that calling GetCompilationInfo after disconnecting the wire calls the callback with a
|
// Test that calling GetCompilationInfo after disconnecting the wire calls the callback with a
|
||||||
// device loss.
|
// device loss.
|
||||||
TEST_F(WireShaderModuleTests, GetCompilationInfoAfterDisconnect) {
|
TEST_F(WireShaderModuleTests, GetCompilationInfoAfterDisconnect) {
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
EXPECT_CALL(*mockCompilationInfoCallback,
|
EXPECT_CALL(*mockCompilationInfoCallback,
|
||||||
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _));
|
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _));
|
||||||
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack to pass in test context into user callback
|
// Hack to pass in test context into user callback
|
||||||
struct TestData {
|
struct TestData {
|
||||||
WireShaderModuleTests* pTest;
|
WireShaderModuleTests* pTest;
|
||||||
WGPUShaderModule* pTestShaderModule;
|
WGPUShaderModule* pTestShaderModule;
|
||||||
size_t numRequests;
|
size_t numRequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ToMockBufferMapCallbackWithNewRequests(WGPUCompilationInfoRequestStatus status,
|
static void ToMockBufferMapCallbackWithNewRequests(WGPUCompilationInfoRequestStatus status,
|
||||||
const WGPUCompilationInfo* info,
|
const WGPUCompilationInfo* info,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
TestData* testData = reinterpret_cast<TestData*>(userdata);
|
||||||
|
@ -179,10 +185,10 @@ static void ToMockBufferMapCallbackWithNewRequests(WGPUCompilationInfoRequestSta
|
||||||
wgpuShaderModuleGetCompilationInfo(*(testData->pTestShaderModule),
|
wgpuShaderModuleGetCompilationInfo(*(testData->pTestShaderModule),
|
||||||
ToMockGetCompilationInfoCallback, nullptr);
|
ToMockGetCompilationInfoCallback, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that requests inside user callbacks before disconnect are called
|
// Test that requests inside user callbacks before disconnect are called
|
||||||
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDisconnect) {
|
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDisconnect) {
|
||||||
TestData testData = {this, &shaderModule, 10};
|
TestData testData = {this, &shaderModule, 10};
|
||||||
|
|
||||||
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
|
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
|
||||||
|
@ -206,10 +212,10 @@ TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDisconnect)
|
||||||
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _))
|
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _))
|
||||||
.Times(1 + testData.numRequests);
|
.Times(1 + testData.numRequests);
|
||||||
GetWireClient()->Disconnect();
|
GetWireClient()->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that requests inside user callbacks before object destruction are called
|
// Test that requests inside user callbacks before object destruction are called
|
||||||
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDestruction) {
|
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDestruction) {
|
||||||
TestData testData = {this, &shaderModule, 10};
|
TestData testData = {this, &shaderModule, 10};
|
||||||
|
|
||||||
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
|
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
|
||||||
|
@ -233,4 +239,6 @@ TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDestruction)
|
||||||
Call(WGPUCompilationInfoRequestStatus_Unknown, nullptr, _))
|
Call(WGPUCompilationInfoRequestStatus_Unknown, nullptr, _))
|
||||||
.Times(1 + testData.numRequests);
|
.Times(1 + testData.numRequests);
|
||||||
wgpuShaderModuleRelease(shaderModule);
|
wgpuShaderModuleRelease(shaderModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace dawn::wire
|
||||||
|
|
|
@ -19,8 +19,11 @@
|
||||||
#include "dawn/wire/WireClient.h"
|
#include "dawn/wire/WireClient.h"
|
||||||
#include "dawn/wire/WireServer.h"
|
#include "dawn/wire/WireServer.h"
|
||||||
|
|
||||||
using namespace testing;
|
using testing::_;
|
||||||
using namespace dawn::wire;
|
using testing::AnyNumber;
|
||||||
|
using testing::Exactly;
|
||||||
|
using testing::Mock;
|
||||||
|
using testing::Return;
|
||||||
|
|
||||||
WireTest::WireTest() {
|
WireTest::WireTest() {
|
||||||
}
|
}
|
||||||
|
@ -28,11 +31,11 @@ WireTest::WireTest() {
|
||||||
WireTest::~WireTest() {
|
WireTest::~WireTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
client::MemoryTransferService* WireTest::GetClientMemoryTransferService() {
|
dawn::wire::client::MemoryTransferService* WireTest::GetClientMemoryTransferService() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
server::MemoryTransferService* WireTest::GetServerMemoryTransferService() {
|
dawn::wire::server::MemoryTransferService* WireTest::GetServerMemoryTransferService() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,19 +53,19 @@ void WireTest::SetUp() {
|
||||||
mS2cBuf = std::make_unique<utils::TerribleCommandBuffer>();
|
mS2cBuf = std::make_unique<utils::TerribleCommandBuffer>();
|
||||||
mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>(mWireServer.get());
|
mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>(mWireServer.get());
|
||||||
|
|
||||||
WireServerDescriptor serverDesc = {};
|
dawn::wire::WireServerDescriptor serverDesc = {};
|
||||||
serverDesc.procs = &mockProcs;
|
serverDesc.procs = &mockProcs;
|
||||||
serverDesc.serializer = mS2cBuf.get();
|
serverDesc.serializer = mS2cBuf.get();
|
||||||
serverDesc.memoryTransferService = GetServerMemoryTransferService();
|
serverDesc.memoryTransferService = GetServerMemoryTransferService();
|
||||||
|
|
||||||
mWireServer.reset(new WireServer(serverDesc));
|
mWireServer.reset(new dawn::wire::WireServer(serverDesc));
|
||||||
mC2sBuf->SetHandler(mWireServer.get());
|
mC2sBuf->SetHandler(mWireServer.get());
|
||||||
|
|
||||||
WireClientDescriptor clientDesc = {};
|
dawn::wire::WireClientDescriptor clientDesc = {};
|
||||||
clientDesc.serializer = mC2sBuf.get();
|
clientDesc.serializer = mC2sBuf.get();
|
||||||
clientDesc.memoryTransferService = GetClientMemoryTransferService();
|
clientDesc.memoryTransferService = GetClientMemoryTransferService();
|
||||||
|
|
||||||
mWireClient.reset(new WireClient(clientDesc));
|
mWireClient.reset(new dawn::wire::WireClient(clientDesc));
|
||||||
mS2cBuf->SetHandler(mWireClient.get());
|
mS2cBuf->SetHandler(mWireClient.get());
|
||||||
|
|
||||||
dawnProcSetProcs(&dawn::wire::client::GetProcs());
|
dawnProcSetProcs(&dawn::wire::client::GetProcs());
|
||||||
|
|
|
@ -26,16 +26,16 @@
|
||||||
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
constexpr uint32_t kRTSize = 4;
|
namespace dawn::native::d3d12 {
|
||||||
|
|
||||||
// Pooling tests are required to advance the GPU completed serial to reuse heaps.
|
constexpr uint32_t kRTSize = 4;
|
||||||
// This requires Tick() to be called at-least |kFrameDepth| times. This constant
|
|
||||||
// should be updated if the internals of Tick() change.
|
|
||||||
constexpr uint32_t kFrameDepth = 2;
|
|
||||||
|
|
||||||
using namespace dawn::native::d3d12;
|
// Pooling tests are required to advance the GPU completed serial to reuse heaps.
|
||||||
|
// This requires Tick() to be called at-least |kFrameDepth| times. This constant
|
||||||
|
// should be updated if the internals of Tick() change.
|
||||||
|
constexpr uint32_t kFrameDepth = 2;
|
||||||
|
|
||||||
class D3D12DescriptorHeapTests : public DawnTest {
|
class D3D12DescriptorHeapTests : public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
DawnTest::SetUp();
|
DawnTest::SetUp();
|
||||||
|
@ -97,9 +97,9 @@ class D3D12DescriptorHeapTests : public DawnTest {
|
||||||
|
|
||||||
wgpu::ShaderModule mSimpleVSModule;
|
wgpu::ShaderModule mSimpleVSModule;
|
||||||
wgpu::ShaderModule mSimpleFSModule;
|
wgpu::ShaderModule mSimpleFSModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlaceholderStagingDescriptorAllocator {
|
class PlaceholderStagingDescriptorAllocator {
|
||||||
public:
|
public:
|
||||||
PlaceholderStagingDescriptorAllocator(Device* device,
|
PlaceholderStagingDescriptorAllocator(Device* device,
|
||||||
uint32_t descriptorCount,
|
uint32_t descriptorCount,
|
||||||
|
@ -122,10 +122,10 @@ class PlaceholderStagingDescriptorAllocator {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StagingDescriptorAllocator mAllocator;
|
StagingDescriptorAllocator mAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify the shader visible view heaps switch over within a single submit.
|
// Verify the shader visible view heaps switch over within a single submit.
|
||||||
TEST_P(D3D12DescriptorHeapTests, SwitchOverViewHeap) {
|
TEST_P(D3D12DescriptorHeapTests, SwitchOverViewHeap) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -136,7 +136,8 @@ TEST_P(D3D12DescriptorHeapTests, SwitchOverViewHeap) {
|
||||||
renderPipelineDescriptor.vertex.module = mSimpleVSModule;
|
renderPipelineDescriptor.vertex.module = mSimpleVSModule;
|
||||||
renderPipelineDescriptor.cFragment.module = mSimpleFSModule;
|
renderPipelineDescriptor.cFragment.module = mSimpleFSModule;
|
||||||
|
|
||||||
wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&renderPipelineDescriptor);
|
wgpu::RenderPipeline renderPipeline =
|
||||||
|
device.CreateRenderPipeline(&renderPipelineDescriptor);
|
||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
Device* d3dDevice = reinterpret_cast<Device*>(device.Get());
|
Device* d3dDevice = reinterpret_cast<Device*>(device.Get());
|
||||||
|
@ -157,7 +158,8 @@ TEST_P(D3D12DescriptorHeapTests, SwitchOverViewHeap) {
|
||||||
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < heapSize + 1; ++i) {
|
for (uint32_t i = 0; i < heapSize + 1; ++i) {
|
||||||
pass.SetBindGroup(0, utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
pass.SetBindGroup(0,
|
||||||
|
utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
||||||
{{0, uniformBuffer, 0, sizeof(redColor)}}));
|
{{0, uniformBuffer, 0, sizeof(redColor)}}));
|
||||||
pass.Draw(3);
|
pass.Draw(3);
|
||||||
}
|
}
|
||||||
|
@ -169,14 +171,14 @@ TEST_P(D3D12DescriptorHeapTests, SwitchOverViewHeap) {
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(), heapSerial + HeapVersionID(1));
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(), heapSerial + HeapVersionID(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the shader visible sampler heaps does not switch over within a single submit.
|
// Verify the shader visible sampler heaps does not switch over within a single submit.
|
||||||
TEST_P(D3D12DescriptorHeapTests, NoSwitchOverSamplerHeap) {
|
TEST_P(D3D12DescriptorHeapTests, NoSwitchOverSamplerHeap) {
|
||||||
utils::ComboRenderPipelineDescriptor renderPipelineDescriptor;
|
utils::ComboRenderPipelineDescriptor renderPipelineDescriptor;
|
||||||
|
|
||||||
// Fill in a sampler heap with "sampler only" bindgroups (1x sampler per group) by creating a
|
// Fill in a sampler heap with "sampler only" bindgroups (1x sampler per group) by creating
|
||||||
// sampler bindgroup each draw. After HEAP_SIZE + 1 draws, the heaps WILL NOT switch over
|
// a sampler bindgroup each draw. After HEAP_SIZE + 1 draws, the heaps WILL NOT switch over
|
||||||
// because the sampler heap allocations are de-duplicated.
|
// because the sampler heap allocations are de-duplicated.
|
||||||
renderPipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"(
|
renderPipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"(
|
||||||
@stage(vertex) fn main() -> @builtin(position) vec4<f32> {
|
@stage(vertex) fn main() -> @builtin(position) vec4<f32> {
|
||||||
|
@ -190,7 +192,8 @@ TEST_P(D3D12DescriptorHeapTests, NoSwitchOverSamplerHeap) {
|
||||||
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
||||||
})");
|
})");
|
||||||
|
|
||||||
wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&renderPipelineDescriptor);
|
wgpu::RenderPipeline renderPipeline =
|
||||||
|
device.CreateRenderPipeline(&renderPipelineDescriptor);
|
||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
|
|
||||||
wgpu::Sampler sampler = device.CreateSampler();
|
wgpu::Sampler sampler = device.CreateSampler();
|
||||||
|
@ -209,7 +212,8 @@ TEST_P(D3D12DescriptorHeapTests, NoSwitchOverSamplerHeap) {
|
||||||
pass.SetPipeline(renderPipeline);
|
pass.SetPipeline(renderPipeline);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < samplerHeapSize + 1; ++i) {
|
for (uint32_t i = 0; i < samplerHeapSize + 1; ++i) {
|
||||||
pass.SetBindGroup(0, utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
pass.SetBindGroup(0,
|
||||||
|
utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
||||||
{{0, sampler}}));
|
{{0, sampler}}));
|
||||||
pass.Draw(3);
|
pass.Draw(3);
|
||||||
}
|
}
|
||||||
|
@ -221,10 +225,10 @@ TEST_P(D3D12DescriptorHeapTests, NoSwitchOverSamplerHeap) {
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(), HeapVersionID);
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(), HeapVersionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify shader-visible heaps can be recycled for multiple submits.
|
// Verify shader-visible heaps can be recycled for multiple submits.
|
||||||
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInMultipleSubmits) {
|
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInMultipleSubmits) {
|
||||||
// Use small heaps to count only pool-allocated switches.
|
// Use small heaps to count only pool-allocated switches.
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
@ -236,7 +240,8 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInMultipleSubmits) {
|
||||||
|
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 0u);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 0u);
|
||||||
|
|
||||||
// Allocate + increment internal serials up to |kFrameDepth| and ensure heaps are always unique.
|
// Allocate + increment internal serials up to |kFrameDepth| and ensure heaps are always
|
||||||
|
// unique.
|
||||||
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
||||||
EXPECT_TRUE(allocator->AllocateAndSwitchShaderVisibleHeap().IsSuccess());
|
EXPECT_TRUE(allocator->AllocateAndSwitchShaderVisibleHeap().IsSuccess());
|
||||||
ComPtr<ID3D12DescriptorHeap> heap = allocator->GetShaderVisibleHeap();
|
ComPtr<ID3D12DescriptorHeap> heap = allocator->GetShaderVisibleHeap();
|
||||||
|
@ -249,8 +254,8 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInMultipleSubmits) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat up to |kFrameDepth| again but ensure heaps are the same in the expected order
|
// Repeat up to |kFrameDepth| again but ensure heaps are the same in the expected order
|
||||||
// (oldest heaps are recycled first). The "+ 1" is so we also include the very first heap in the
|
// (oldest heaps are recycled first). The "+ 1" is so we also include the very first heap in
|
||||||
// check.
|
// the check.
|
||||||
for (uint32_t i = 0; i < kFrameDepth + 1; i++) {
|
for (uint32_t i = 0; i < kFrameDepth + 1; i++) {
|
||||||
EXPECT_TRUE(allocator->AllocateAndSwitchShaderVisibleHeap().IsSuccess());
|
EXPECT_TRUE(allocator->AllocateAndSwitchShaderVisibleHeap().IsSuccess());
|
||||||
ComPtr<ID3D12DescriptorHeap> heap = allocator->GetShaderVisibleHeap();
|
ComPtr<ID3D12DescriptorHeap> heap = allocator->GetShaderVisibleHeap();
|
||||||
|
@ -262,10 +267,10 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInMultipleSubmits) {
|
||||||
|
|
||||||
EXPECT_TRUE(heaps.empty());
|
EXPECT_TRUE(heaps.empty());
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kFrameDepth);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kFrameDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify shader-visible heaps do not recycle in a pending submit.
|
// Verify shader-visible heaps do not recycle in a pending submit.
|
||||||
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingSubmit) {
|
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingSubmit) {
|
||||||
// Use small heaps to count only pool-allocated switches.
|
// Use small heaps to count only pool-allocated switches.
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
@ -293,11 +298,11 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingSubmit) {
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
||||||
heapSerial + HeapVersionID(kNumOfSwitches));
|
heapSerial + HeapVersionID(kNumOfSwitches));
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify switching shader-visible heaps do not recycle in a pending submit but do so
|
// Verify switching shader-visible heaps do not recycle in a pending submit but do so
|
||||||
// once no longer pending.
|
// once no longer pending.
|
||||||
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingAndMultipleSubmits) {
|
TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingAndMultipleSubmits) {
|
||||||
// Use small heaps to count only pool-allocated switches.
|
// Use small heaps to count only pool-allocated switches.
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
@ -324,7 +329,8 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingAndMultipleSubmits) {
|
||||||
heapSerial + HeapVersionID(kNumOfSwitches));
|
heapSerial + HeapVersionID(kNumOfSwitches));
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
||||||
|
|
||||||
// Ensure switched-over heaps can be recycled by advancing the GPU by at-least |kFrameDepth|.
|
// Ensure switched-over heaps can be recycled by advancing the GPU by at-least
|
||||||
|
// |kFrameDepth|.
|
||||||
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
||||||
mD3DDevice->APITick();
|
mD3DDevice->APITick();
|
||||||
}
|
}
|
||||||
|
@ -341,10 +347,10 @@ TEST_P(D3D12DescriptorHeapTests, PoolHeapsInPendingAndMultipleSubmits) {
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
||||||
heapSerial + HeapVersionID(kNumOfSwitches * 2));
|
heapSerial + HeapVersionID(kNumOfSwitches * 2));
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfSwitches);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify shader-visible heaps do not recycle in multiple submits.
|
// Verify shader-visible heaps do not recycle in multiple submits.
|
||||||
TEST_P(D3D12DescriptorHeapTests, GrowHeapsInMultipleSubmits) {
|
TEST_P(D3D12DescriptorHeapTests, GrowHeapsInMultipleSubmits) {
|
||||||
ShaderVisibleDescriptorAllocator* allocator =
|
ShaderVisibleDescriptorAllocator* allocator =
|
||||||
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
||||||
|
|
||||||
|
@ -367,10 +373,10 @@ TEST_P(D3D12DescriptorHeapTests, GrowHeapsInMultipleSubmits) {
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 1u);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 1u);
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
||||||
heapSerial + HeapVersionID(heaps.size() - 1));
|
heapSerial + HeapVersionID(heaps.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify shader-visible heaps do not recycle in a pending submit.
|
// Verify shader-visible heaps do not recycle in a pending submit.
|
||||||
TEST_P(D3D12DescriptorHeapTests, GrowHeapsInPendingSubmit) {
|
TEST_P(D3D12DescriptorHeapTests, GrowHeapsInPendingSubmit) {
|
||||||
ShaderVisibleDescriptorAllocator* allocator =
|
ShaderVisibleDescriptorAllocator* allocator =
|
||||||
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
||||||
|
|
||||||
|
@ -392,12 +398,12 @@ TEST_P(D3D12DescriptorHeapTests, GrowHeapsInPendingSubmit) {
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 1u);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), 1u);
|
||||||
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
EXPECT_EQ(allocator->GetShaderVisibleHeapSerialForTesting(),
|
||||||
heapSerial + HeapVersionID(heaps.size() - 1));
|
heapSerial + HeapVersionID(heaps.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify switching shader-visible heaps do not recycle in a pending submit but do so
|
// Verify switching shader-visible heaps do not recycle in a pending submit but do so
|
||||||
// once no longer pending.
|
// once no longer pending.
|
||||||
// Switches over many times until |kNumOfPooledHeaps| heaps are pool-allocated.
|
// Switches over many times until |kNumOfPooledHeaps| heaps are pool-allocated.
|
||||||
TEST_P(D3D12DescriptorHeapTests, GrowAndPoolHeapsInPendingAndMultipleSubmits) {
|
TEST_P(D3D12DescriptorHeapTests, GrowAndPoolHeapsInPendingAndMultipleSubmits) {
|
||||||
ShaderVisibleDescriptorAllocator* allocator =
|
ShaderVisibleDescriptorAllocator* allocator =
|
||||||
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
||||||
|
|
||||||
|
@ -415,7 +421,8 @@ TEST_P(D3D12DescriptorHeapTests, GrowAndPoolHeapsInPendingAndMultipleSubmits) {
|
||||||
|
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfPooledHeaps);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfPooledHeaps);
|
||||||
|
|
||||||
// Ensure switched-over heaps can be recycled by advancing the GPU by at-least |kFrameDepth|.
|
// Ensure switched-over heaps can be recycled by advancing the GPU by at-least
|
||||||
|
// |kFrameDepth|.
|
||||||
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
for (uint32_t i = 0; i < kFrameDepth; i++) {
|
||||||
mD3DDevice->APITick();
|
mD3DDevice->APITick();
|
||||||
}
|
}
|
||||||
|
@ -428,15 +435,16 @@ TEST_P(D3D12DescriptorHeapTests, GrowAndPoolHeapsInPendingAndMultipleSubmits) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfPooledHeaps);
|
EXPECT_EQ(allocator->GetShaderVisiblePoolSizeForTesting(), kNumOfPooledHeaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify encoding multiple heaps worth of bindgroups.
|
// Verify encoding multiple heaps worth of bindgroups.
|
||||||
// Shader-visible heaps will switch out |kNumOfHeaps| times.
|
// Shader-visible heaps will switch out |kNumOfHeaps| times.
|
||||||
TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
||||||
// This test draws a solid color triangle |heapSize| times. Each draw uses a new bindgroup that
|
// This test draws a solid color triangle |heapSize| times. Each draw uses a new bindgroup
|
||||||
// has its own UBO with a "color value" in the range [1... heapSize]. After |heapSize| draws,
|
// that has its own UBO with a "color value" in the range [1... heapSize]. After |heapSize|
|
||||||
// the result is the arithmetic sum of the sequence after the framebuffer is blended by
|
// draws, the result is the arithmetic sum of the sequence after the framebuffer is blended
|
||||||
// accumulation. By checking for this sum, we ensure each bindgroup was encoded correctly.
|
// by accumulation. By checking for this sum, we ensure each bindgroup was encoded
|
||||||
|
// correctly.
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -469,8 +477,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
||||||
|
|
||||||
wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
|
|
||||||
const uint32_t heapSize =
|
const uint32_t heapSize = mD3DDevice->GetViewShaderVisibleDescriptorAllocator()
|
||||||
mD3DDevice->GetViewShaderVisibleDescriptorAllocator()->GetShaderVisibleHeapSizeForTesting();
|
->GetShaderVisibleHeapSizeForTesting();
|
||||||
|
|
||||||
constexpr uint32_t kNumOfHeaps = 2;
|
constexpr uint32_t kNumOfHeaps = 2;
|
||||||
|
|
||||||
|
@ -479,8 +487,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
||||||
std::vector<wgpu::BindGroup> bindGroups;
|
std::vector<wgpu::BindGroup> bindGroups;
|
||||||
for (uint32_t i = 0; i < numOfEncodedBindGroups; i++) {
|
for (uint32_t i = 0; i < numOfEncodedBindGroups; i++) {
|
||||||
const float color = i + 1;
|
const float color = i + 1;
|
||||||
wgpu::Buffer uniformBuffer =
|
wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(device, &color, sizeof(color),
|
||||||
utils::CreateBufferFromData(device, &color, sizeof(color), wgpu::BufferUsage::Uniform);
|
wgpu::BufferUsage::Uniform);
|
||||||
bindGroups.push_back(utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
bindGroups.push_back(utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
||||||
{{0, uniformBuffer}}));
|
{{0, uniformBuffer}}));
|
||||||
}
|
}
|
||||||
|
@ -504,13 +512,13 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBO) {
|
||||||
|
|
||||||
float colorSum = numOfEncodedBindGroups * (numOfEncodedBindGroups + 1) / 2;
|
float colorSum = numOfEncodedBindGroups * (numOfEncodedBindGroups + 1) / 2;
|
||||||
EXPECT_PIXEL_FLOAT16_EQ(colorSum, renderPass.color, 0, 0);
|
EXPECT_PIXEL_FLOAT16_EQ(colorSum, renderPass.color, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify encoding one bindgroup then a heaps worth in different submits.
|
// Verify encoding one bindgroup then a heaps worth in different submits.
|
||||||
// Shader-visible heaps should switch out once upon encoding 1 + |heapSize| descriptors.
|
// Shader-visible heaps should switch out once upon encoding 1 + |heapSize| descriptors.
|
||||||
// The first descriptor's memory will be reused when the second submit encodes |heapSize|
|
// The first descriptor's memory will be reused when the second submit encodes |heapSize|
|
||||||
// descriptors.
|
// descriptors.
|
||||||
TEST_P(D3D12DescriptorHeapTests, EncodeUBOOverflowMultipleSubmit) {
|
TEST_P(D3D12DescriptorHeapTests, EncodeUBOOverflowMultipleSubmit) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -562,15 +570,16 @@ TEST_P(D3D12DescriptorHeapTests, EncodeUBOOverflowMultipleSubmit) {
|
||||||
wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &fillColor, sizeof(fillColor), wgpu::BufferUsage::Uniform);
|
device, &fillColor, sizeof(fillColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
bindGroups.push_back(utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
bindGroups.push_back(utils::MakeBindGroup(
|
||||||
{{0, uniformBuffer}}));
|
device, renderPipeline.GetBindGroupLayout(0), {{0, uniformBuffer}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<float, 4> redColor = {1, 0, 0, 1};
|
std::array<float, 4> redColor = {1, 0, 0, 1};
|
||||||
wgpu::Buffer lastUniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer lastUniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
bindGroups.push_back(utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
bindGroups.push_back(
|
||||||
|
utils::MakeBindGroup(device, renderPipeline.GetBindGroupLayout(0),
|
||||||
{{0, lastUniformBuffer, 0, sizeof(redColor)}}));
|
{{0, lastUniformBuffer, 0, sizeof(redColor)}}));
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
@ -592,13 +601,13 @@ TEST_P(D3D12DescriptorHeapTests, EncodeUBOOverflowMultipleSubmit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderPass.color, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderPass.color, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify encoding a heaps worth of bindgroups plus one more then reuse the first
|
// Verify encoding a heaps worth of bindgroups plus one more then reuse the first
|
||||||
// bindgroup in the same submit.
|
// bindgroup in the same submit.
|
||||||
// Shader-visible heaps should switch out once then re-encode the first descriptor at a new offset
|
// Shader-visible heaps should switch out once then re-encode the first descriptor at a new
|
||||||
// in the heap.
|
// offset in the heap.
|
||||||
TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOOverflow) {
|
TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOOverflow) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -615,11 +624,12 @@ TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOOverflow) {
|
||||||
wgpu::Buffer firstUniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer firstUniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
std::vector<wgpu::BindGroup> bindGroups = {utils::MakeBindGroup(
|
std::vector<wgpu::BindGroup> bindGroups = {
|
||||||
device, pipeline.GetBindGroupLayout(0), {{0, firstUniformBuffer, 0, sizeof(redColor)}})};
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||||
|
{{0, firstUniformBuffer, 0, sizeof(redColor)}})};
|
||||||
|
|
||||||
const uint32_t heapSize =
|
const uint32_t heapSize = mD3DDevice->GetViewShaderVisibleDescriptorAllocator()
|
||||||
mD3DDevice->GetViewShaderVisibleDescriptorAllocator()->GetShaderVisibleHeapSizeForTesting();
|
->GetShaderVisibleHeapSizeForTesting();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < heapSize; i++) {
|
for (uint32_t i = 0; i < heapSize; i++) {
|
||||||
const std::array<float, 4>& fillColor = GetSolidColor(i + 1); // Avoid black
|
const std::array<float, 4>& fillColor = GetSolidColor(i + 1); // Avoid black
|
||||||
|
@ -653,13 +663,13 @@ TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOOverflow) {
|
||||||
|
|
||||||
// Make sure the first bindgroup was encoded correctly.
|
// Make sure the first bindgroup was encoded correctly.
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderPass.color, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderPass.color, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify encoding a heaps worth of bindgroups plus one more in the first submit then reuse the
|
// Verify encoding a heaps worth of bindgroups plus one more in the first submit then reuse the
|
||||||
// first bindgroup again in the second submit.
|
// first bindgroup again in the second submit.
|
||||||
// Shader-visible heaps should switch out once then re-encode the
|
// Shader-visible heaps should switch out once then re-encode the
|
||||||
// first descriptor at the same offset in the heap.
|
// first descriptor at the same offset in the heap.
|
||||||
TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOMultipleSubmits) {
|
TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOMultipleSubmits) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -678,11 +688,12 @@ TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOMultipleSubmits) {
|
||||||
wgpu::Buffer firstUniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer firstUniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
std::vector<wgpu::BindGroup> bindGroups = {utils::MakeBindGroup(
|
std::vector<wgpu::BindGroup> bindGroups = {
|
||||||
device, pipeline.GetBindGroupLayout(0), {{0, firstUniformBuffer, 0, sizeof(redColor)}})};
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||||
|
{{0, firstUniformBuffer, 0, sizeof(redColor)}})};
|
||||||
|
|
||||||
const uint32_t heapSize =
|
const uint32_t heapSize = mD3DDevice->GetViewShaderVisibleDescriptorAllocator()
|
||||||
mD3DDevice->GetViewShaderVisibleDescriptorAllocator()->GetShaderVisibleHeapSizeForTesting();
|
->GetShaderVisibleHeapSizeForTesting();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < heapSize; i++) {
|
for (uint32_t i = 0; i < heapSize; i++) {
|
||||||
std::array<float, 4> fillColor = GetSolidColor(i + 1); // Avoid black
|
std::array<float, 4> fillColor = GetSolidColor(i + 1); // Avoid black
|
||||||
|
@ -735,11 +746,11 @@ TEST_P(D3D12DescriptorHeapTests, EncodeReuseUBOMultipleSubmits) {
|
||||||
|
|
||||||
// Make sure the first bindgroup was re-encoded correctly.
|
// Make sure the first bindgroup was re-encoded correctly.
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify encoding many sampler and ubo worth of bindgroups.
|
// Verify encoding many sampler and ubo worth of bindgroups.
|
||||||
// Shader-visible heaps should switch out |kNumOfViewHeaps| times.
|
// Shader-visible heaps should switch out |kNumOfViewHeaps| times.
|
||||||
TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
DAWN_TEST_UNSUPPORTED_IF(!mD3DDevice->IsToggleEnabled(
|
||||||
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
dawn::native::Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
|
||||||
|
|
||||||
|
@ -752,8 +763,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
descriptor.sampleCount = 1;
|
descriptor.sampleCount = 1;
|
||||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
descriptor.mipLevelCount = 1;
|
descriptor.mipLevelCount = 1;
|
||||||
descriptor.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment |
|
descriptor.usage = wgpu::TextureUsage::TextureBinding |
|
||||||
wgpu::TextureUsage::CopySrc;
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
wgpu::TextureView textureView = texture.CreateView();
|
wgpu::TextureView textureView = texture.CreateView();
|
||||||
|
|
||||||
|
@ -809,7 +820,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
return textureSample(texture0, sampler0, FragCoord.xy) + buffer0.color;
|
return textureSample(texture0, sampler0, FragCoord.xy) + buffer0.color;
|
||||||
})");
|
})");
|
||||||
|
|
||||||
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
utils::BasicRenderPass renderPass =
|
||||||
|
utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
|
||||||
pipelineDescriptor.cTargets[0].format = renderPass.colorFormat;
|
pipelineDescriptor.cTargets[0].format = renderPass.colorFormat;
|
||||||
|
|
||||||
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
|
@ -828,16 +840,17 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
ShaderVisibleDescriptorAllocator* samplerAllocator =
|
ShaderVisibleDescriptorAllocator* samplerAllocator =
|
||||||
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
mD3DDevice->GetSamplerShaderVisibleDescriptorAllocator();
|
||||||
|
|
||||||
const HeapVersionID viewHeapSerial = viewAllocator->GetShaderVisibleHeapSerialForTesting();
|
const HeapVersionID viewHeapSerial =
|
||||||
|
viewAllocator->GetShaderVisibleHeapSerialForTesting();
|
||||||
const HeapVersionID samplerHeapSerial =
|
const HeapVersionID samplerHeapSerial =
|
||||||
samplerAllocator->GetShaderVisibleHeapSerialForTesting();
|
samplerAllocator->GetShaderVisibleHeapSerialForTesting();
|
||||||
|
|
||||||
const uint32_t viewHeapSize = viewAllocator->GetShaderVisibleHeapSizeForTesting();
|
const uint32_t viewHeapSize = viewAllocator->GetShaderVisibleHeapSizeForTesting();
|
||||||
|
|
||||||
// "Small" view heap is always 2 x sampler heap size and encodes 3x the descriptors per
|
// "Small" view heap is always 2 x sampler heap size and encodes 3x the descriptors per
|
||||||
// group. This means the count of heaps switches is determined by the total number of views
|
// group. This means the count of heaps switches is determined by the total number of
|
||||||
// to encode. Compute the number of bindgroups to encode by counting the required views for
|
// views to encode. Compute the number of bindgroups to encode by counting the required
|
||||||
// |kNumOfViewHeaps| heaps worth.
|
// views for |kNumOfViewHeaps| heaps worth.
|
||||||
constexpr uint32_t kViewsPerBindGroup = 3;
|
constexpr uint32_t kViewsPerBindGroup = 3;
|
||||||
constexpr uint32_t kNumOfViewHeaps = 5;
|
constexpr uint32_t kNumOfViewHeaps = 5;
|
||||||
|
|
||||||
|
@ -850,7 +863,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer uniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &fillColor, sizeof(fillColor), wgpu::BufferUsage::Uniform);
|
device, &fillColor, sizeof(fillColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
bindGroups.push_back(utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
bindGroups.push_back(
|
||||||
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||||
{{0, transformBuffer, 0, sizeof(transform)},
|
{{0, transformBuffer, 0, sizeof(transform)},
|
||||||
{1, sampler},
|
{1, sampler},
|
||||||
{2, textureView},
|
{2, textureView},
|
||||||
|
@ -861,7 +875,8 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
wgpu::Buffer lastUniformBuffer = utils::CreateBufferFromData(
|
wgpu::Buffer lastUniformBuffer = utils::CreateBufferFromData(
|
||||||
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
device, &redColor, sizeof(redColor), wgpu::BufferUsage::Uniform);
|
||||||
|
|
||||||
bindGroups.push_back(utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
bindGroups.push_back(
|
||||||
|
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
|
||||||
{{0, transformBuffer, 0, sizeof(transform)},
|
{{0, transformBuffer, 0, sizeof(transform)},
|
||||||
{1, sampler},
|
{1, sampler},
|
||||||
{2, textureView},
|
{2, textureView},
|
||||||
|
@ -895,11 +910,11 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||||
EXPECT_EQ(samplerAllocator->GetShaderVisiblePoolSizeForTesting(), 0u);
|
EXPECT_EQ(samplerAllocator->GetShaderVisiblePoolSizeForTesting(), 0u);
|
||||||
EXPECT_EQ(samplerAllocator->GetShaderVisibleHeapSerialForTesting(), samplerHeapSerial);
|
EXPECT_EQ(samplerAllocator->GetShaderVisibleHeapSerialForTesting(), samplerHeapSerial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify a single allocate/deallocate.
|
// Verify a single allocate/deallocate.
|
||||||
// One non-shader visible heap will be created.
|
// One non-shader visible heap will be created.
|
||||||
TEST_P(D3D12DescriptorHeapTests, Single) {
|
TEST_P(D3D12DescriptorHeapTests, Single) {
|
||||||
constexpr uint32_t kDescriptorCount = 4;
|
constexpr uint32_t kDescriptorCount = 4;
|
||||||
constexpr uint32_t kAllocationsPerHeap = 3;
|
constexpr uint32_t kAllocationsPerHeap = 3;
|
||||||
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||||
|
@ -911,11 +926,11 @@ TEST_P(D3D12DescriptorHeapTests, Single) {
|
||||||
|
|
||||||
allocator.Deallocate(allocation);
|
allocator.Deallocate(allocation);
|
||||||
EXPECT_FALSE(allocation.IsValid());
|
EXPECT_FALSE(allocation.IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify allocating many times causes the pool to increase in size.
|
// Verify allocating many times causes the pool to increase in size.
|
||||||
// Creates |kNumOfHeaps| non-shader visible heaps.
|
// Creates |kNumOfHeaps| non-shader visible heaps.
|
||||||
TEST_P(D3D12DescriptorHeapTests, Sequential) {
|
TEST_P(D3D12DescriptorHeapTests, Sequential) {
|
||||||
constexpr uint32_t kDescriptorCount = 4;
|
constexpr uint32_t kDescriptorCount = 4;
|
||||||
constexpr uint32_t kAllocationsPerHeap = 3;
|
constexpr uint32_t kAllocationsPerHeap = 3;
|
||||||
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||||
|
@ -942,11 +957,11 @@ TEST_P(D3D12DescriptorHeapTests, Sequential) {
|
||||||
allocator.Deallocate(allocation);
|
allocator.Deallocate(allocation);
|
||||||
EXPECT_FALSE(allocation.IsValid());
|
EXPECT_FALSE(allocation.IsValid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that re-allocating a number of allocations < pool size, all heaps are reused.
|
// Verify that re-allocating a number of allocations < pool size, all heaps are reused.
|
||||||
// Creates and reuses |kNumofHeaps| non-shader visible heaps.
|
// Creates and reuses |kNumofHeaps| non-shader visible heaps.
|
||||||
TEST_P(D3D12DescriptorHeapTests, ReuseFreedHeaps) {
|
TEST_P(D3D12DescriptorHeapTests, ReuseFreedHeaps) {
|
||||||
constexpr uint32_t kDescriptorCount = 4;
|
constexpr uint32_t kDescriptorCount = 4;
|
||||||
constexpr uint32_t kAllocationsPerHeap = 25;
|
constexpr uint32_t kAllocationsPerHeap = 25;
|
||||||
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||||
|
@ -987,10 +1002,10 @@ TEST_P(D3D12DescriptorHeapTests, ReuseFreedHeaps) {
|
||||||
allocator.Deallocate(allocation);
|
allocator.Deallocate(allocation);
|
||||||
EXPECT_FALSE(allocation.IsValid());
|
EXPECT_FALSE(allocation.IsValid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify allocating then deallocating many times.
|
// Verify allocating then deallocating many times.
|
||||||
TEST_P(D3D12DescriptorHeapTests, AllocateDeallocateMany) {
|
TEST_P(D3D12DescriptorHeapTests, AllocateDeallocateMany) {
|
||||||
constexpr uint32_t kDescriptorCount = 4;
|
constexpr uint32_t kDescriptorCount = 4;
|
||||||
constexpr uint32_t kAllocationsPerHeap = 25;
|
constexpr uint32_t kAllocationsPerHeap = 25;
|
||||||
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
PlaceholderStagingDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||||
|
@ -1046,8 +1061,10 @@ TEST_P(D3D12DescriptorHeapTests, AllocateDeallocateMany) {
|
||||||
allocator.Deallocate(allocation);
|
allocator.Deallocate(allocation);
|
||||||
EXPECT_FALSE(allocation.IsValid());
|
EXPECT_FALSE(allocation.IsValid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(D3D12DescriptorHeapTests,
|
DAWN_INSTANTIATE_TEST(D3D12DescriptorHeapTests,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
D3D12Backend({"use_d3d12_small_shader_visible_heap"}));
|
D3D12Backend({"use_d3d12_small_shader_visible_heap"}));
|
||||||
|
|
||||||
|
} // namespace dawn::native::d3d12
|
||||||
|
|
|
@ -20,8 +20,9 @@
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include "dawn/tests/DawnTest.h"
|
||||||
#include "dawn/utils/WGPUHelpers.h"
|
#include "dawn/utils/WGPUHelpers.h"
|
||||||
|
|
||||||
namespace {
|
namespace dawn::native::d3d12 {
|
||||||
class ExpectBetweenTimestamps : public detail::Expectation {
|
namespace {
|
||||||
|
class ExpectBetweenTimestamps : public ::detail::Expectation {
|
||||||
public:
|
public:
|
||||||
~ExpectBetweenTimestamps() override = default;
|
~ExpectBetweenTimestamps() override = default;
|
||||||
|
|
||||||
|
@ -49,11 +50,9 @@ namespace {
|
||||||
uint64_t mValue1;
|
uint64_t mValue1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
using namespace dawn::native::d3d12;
|
class D3D12GPUTimestampCalibrationTests : public DawnTest {
|
||||||
|
|
||||||
class D3D12GPUTimestampCalibrationTests : public DawnTest {
|
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
DawnTest::SetUp();
|
DawnTest::SetUp();
|
||||||
|
@ -72,11 +71,11 @@ class D3D12GPUTimestampCalibrationTests : public DawnTest {
|
||||||
}
|
}
|
||||||
return requiredFeatures;
|
return requiredFeatures;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that the timestamps got by timestamp query are between the two timestamps from
|
// Check that the timestamps got by timestamp query are between the two timestamps from
|
||||||
// GetClockCalibration() after the timestamp conversion is disabled.
|
// GetClockCalibration() after the timestamp conversion is disabled.
|
||||||
TEST_P(D3D12GPUTimestampCalibrationTests, TimestampsInOrder) {
|
TEST_P(D3D12GPUTimestampCalibrationTests, TimestampsInOrder) {
|
||||||
constexpr uint32_t kQueryCount = 2;
|
constexpr uint32_t kQueryCount = 2;
|
||||||
|
|
||||||
wgpu::QuerySetDescriptor querySetDescriptor;
|
wgpu::QuerySetDescriptor querySetDescriptor;
|
||||||
|
@ -86,8 +85,8 @@ TEST_P(D3D12GPUTimestampCalibrationTests, TimestampsInOrder) {
|
||||||
|
|
||||||
wgpu::BufferDescriptor bufferDescriptor;
|
wgpu::BufferDescriptor bufferDescriptor;
|
||||||
bufferDescriptor.size = kQueryCount * sizeof(uint64_t);
|
bufferDescriptor.size = kQueryCount * sizeof(uint64_t);
|
||||||
bufferDescriptor.usage =
|
bufferDescriptor.usage = wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc |
|
||||||
wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
wgpu::BufferUsage::CopyDst;
|
||||||
wgpu::Buffer destination = device.CreateBuffer(&bufferDescriptor);
|
wgpu::Buffer destination = device.CreateBuffer(&bufferDescriptor);
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
@ -113,7 +112,9 @@ TEST_P(D3D12GPUTimestampCalibrationTests, TimestampsInOrder) {
|
||||||
|
|
||||||
EXPECT_BUFFER(destination, 0, kQueryCount * sizeof(uint64_t),
|
EXPECT_BUFFER(destination, 0, kQueryCount * sizeof(uint64_t),
|
||||||
new ExpectBetweenTimestamps(gpuTimestamp0, gpuTimestamp1));
|
new ExpectBetweenTimestamps(gpuTimestamp0, gpuTimestamp1));
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(D3D12GPUTimestampCalibrationTests,
|
DAWN_INSTANTIATE_TEST(D3D12GPUTimestampCalibrationTests,
|
||||||
D3D12Backend({"disable_timestamp_query_conversion"}));
|
D3D12Backend({"disable_timestamp_query_conversion"}));
|
||||||
|
|
||||||
|
} // namespace dawn::native::d3d12
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
#include "dawn/native/d3d12/TextureD3D12.h"
|
#include "dawn/native/d3d12/TextureD3D12.h"
|
||||||
#include "dawn/tests/DawnTest.h"
|
#include "dawn/tests/DawnTest.h"
|
||||||
|
|
||||||
using namespace dawn::native::d3d12;
|
namespace dawn::native::d3d12 {
|
||||||
|
|
||||||
class D3D12ResourceHeapTests : public DawnTest {
|
class D3D12ResourceHeapTests : public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
DawnTest::SetUp();
|
DawnTest::SetUp();
|
||||||
|
@ -42,10 +42,10 @@ class D3D12ResourceHeapTests : public DawnTest {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mIsBCFormatSupported = false;
|
bool mIsBCFormatSupported = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify that creating a small compressed textures will be 4KB aligned.
|
// Verify that creating a small compressed textures will be 4KB aligned.
|
||||||
TEST_P(D3D12ResourceHeapTests, AlignSmallCompressedTexture) {
|
TEST_P(D3D12ResourceHeapTests, AlignSmallCompressedTexture) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(!IsBCFormatSupported());
|
DAWN_TEST_UNSUPPORTED_IF(!IsBCFormatSupported());
|
||||||
|
|
||||||
// TODO(http://crbug.com/dawn/282): Investigate GPU/driver rejections of small alignment.
|
// TODO(http://crbug.com/dawn/282): Investigate GPU/driver rejections of small alignment.
|
||||||
|
@ -77,10 +77,10 @@ TEST_P(D3D12ResourceHeapTests, AlignSmallCompressedTexture) {
|
||||||
|
|
||||||
EXPECT_EQ(d3dTexture->GetD3D12Resource()->GetDesc().Alignment,
|
EXPECT_EQ(d3dTexture->GetD3D12Resource()->GetDesc().Alignment,
|
||||||
static_cast<uint64_t>(D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
|
static_cast<uint64_t>(D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify creating a UBO will always be 256B aligned.
|
// Verify creating a UBO will always be 256B aligned.
|
||||||
TEST_P(D3D12ResourceHeapTests, AlignUBO) {
|
TEST_P(D3D12ResourceHeapTests, AlignUBO) {
|
||||||
// Create a small UBO
|
// Create a small UBO
|
||||||
wgpu::BufferDescriptor descriptor;
|
wgpu::BufferDescriptor descriptor;
|
||||||
descriptor.size = 4 * 1024;
|
descriptor.size = 4 * 1024;
|
||||||
|
@ -103,6 +103,8 @@ TEST_P(D3D12ResourceHeapTests, AlignUBO) {
|
||||||
EXPECT_EQ((d3dBuffer->GetD3D12Resource()->GetDesc().Width %
|
EXPECT_EQ((d3dBuffer->GetD3D12Resource()->GetDesc().Width %
|
||||||
static_cast<uint64_t>(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT)),
|
static_cast<uint64_t>(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT)),
|
||||||
0u);
|
0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(D3D12ResourceHeapTests, D3D12Backend());
|
DAWN_INSTANTIATE_TEST(D3D12ResourceHeapTests, D3D12Backend());
|
||||||
|
|
||||||
|
} // namespace dawn::native::d3d12
|
||||||
|
|
Loading…
Reference in New Issue