Refactors native mock classes to be more like the Null device.
- Plumbs all descriptors through so that the objects act much more like
a real implementation.
- Lots of changes to DestroyObjectTests.cpp to update usages and test
through the APIs when applicable.
- Put in defaults for the mock device and make it as easy to use as
possible.
Change-Id: I85b243a18ec1872aff0172549aec0f599967ea0e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119821
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp
index c2819b8..5a2e3a4 100644
--- a/src/dawn/native/BindGroup.cpp
+++ b/src/dawn/native/BindGroup.cpp
@@ -456,10 +456,6 @@
GetObjectTrackingList()->Track(this);
}
-BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
BindGroupBase::~BindGroupBase() = default;
void BindGroupBase::DestroyImpl() {
diff --git a/src/dawn/native/BindGroup.h b/src/dawn/native/BindGroup.h
index 34c122b..01df670 100644
--- a/src/dawn/native/BindGroup.h
+++ b/src/dawn/native/BindGroup.h
@@ -76,8 +76,6 @@
static_assert(std::is_base_of<BindGroupBase, Derived>::value);
}
- // Constructor used only for mocking and testing.
- explicit BindGroupBase(DeviceBase* device);
void DestroyImpl() override;
~BindGroupBase() override;
diff --git a/src/dawn/native/BindGroupLayout.cpp b/src/dawn/native/BindGroupLayout.cpp
index abc1e4c..125faa2 100644
--- a/src/dawn/native/BindGroupLayout.cpp
+++ b/src/dawn/native/BindGroupLayout.cpp
@@ -493,11 +493,6 @@
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
-BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device)
- : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
BindGroupLayoutBase::~BindGroupLayoutBase() = default;
void BindGroupLayoutBase::DestroyImpl() {
diff --git a/src/dawn/native/BindGroupLayout.h b/src/dawn/native/BindGroupLayout.h
index a218877..3b435cd 100644
--- a/src/dawn/native/BindGroupLayout.h
+++ b/src/dawn/native/BindGroupLayout.h
@@ -135,8 +135,6 @@
std::string EntriesToString() const;
protected:
- // Constructor used only for mocking and testing.
- explicit BindGroupLayoutBase(DeviceBase* device);
void DestroyImpl() override;
template <typename BindGroup>
diff --git a/src/dawn/native/Buffer.cpp b/src/dawn/native/Buffer.cpp
index b8f8f0a..9f99a71 100644
--- a/src/dawn/native/Buffer.cpp
+++ b/src/dawn/native/Buffer.cpp
@@ -222,11 +222,6 @@
}
}
-BufferBase::BufferBase(DeviceBase* device, BufferState state)
- : ApiObjectBase(device, kLabelNotImplemented), mState(state) {
- GetObjectTrackingList()->Track(this);
-}
-
BufferBase::~BufferBase() {
ASSERT(mState == BufferState::Unmapped || mState == BufferState::Destroyed);
}
diff --git a/src/dawn/native/Buffer.h b/src/dawn/native/Buffer.h
index d152d89..8e86055 100644
--- a/src/dawn/native/Buffer.h
+++ b/src/dawn/native/Buffer.h
@@ -96,8 +96,6 @@
protected:
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
BufferBase(DeviceBase* device, const BufferDescriptor* descriptor, ObjectBase::ErrorTag tag);
- // Constructor used only for mocking and testing.
- BufferBase(DeviceBase* device, BufferState state);
void DestroyImpl() override;
diff --git a/src/dawn/native/CachedObject.cpp b/src/dawn/native/CachedObject.cpp
index 249b0d6..bf2be11 100644
--- a/src/dawn/native/CachedObject.cpp
+++ b/src/dawn/native/CachedObject.cpp
@@ -37,7 +37,7 @@
}
void CachedObject::SetContentHash(size_t contentHash) {
- ASSERT(!mIsContentHashInitialized);
+ ASSERT(!mIsContentHashInitialized || contentHash == mContentHash);
mContentHash = contentHash;
mIsContentHashInitialized = true;
}
diff --git a/src/dawn/native/CommandBuffer.cpp b/src/dawn/native/CommandBuffer.cpp
index 4a54530..061d1c1 100644
--- a/src/dawn/native/CommandBuffer.cpp
+++ b/src/dawn/native/CommandBuffer.cpp
@@ -33,11 +33,6 @@
GetObjectTrackingList()->Track(this);
}
-CommandBufferBase::CommandBufferBase(DeviceBase* device)
- : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
diff --git a/src/dawn/native/CommandBuffer.h b/src/dawn/native/CommandBuffer.h
index 19d9f68..62b7c8b 100644
--- a/src/dawn/native/CommandBuffer.h
+++ b/src/dawn/native/CommandBuffer.h
@@ -45,8 +45,6 @@
CommandIterator* GetCommandIteratorForTesting();
protected:
- // Constructor used only for mocking and testing.
- explicit CommandBufferBase(DeviceBase* device);
void DestroyImpl() override;
CommandIterator mCommands;
diff --git a/src/dawn/native/ComputePipeline.cpp b/src/dawn/native/ComputePipeline.cpp
index a4b669b..93d2804 100644
--- a/src/dawn/native/ComputePipeline.cpp
+++ b/src/dawn/native/ComputePipeline.cpp
@@ -56,10 +56,6 @@
StreamIn(&mCacheKey, CacheKey::Type::ComputePipeline, device->GetCacheKey());
}
-ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
- GetObjectTrackingList()->Track(this);
-}
-
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: PipelineBase(device, tag) {}
diff --git a/src/dawn/native/ComputePipeline.h b/src/dawn/native/ComputePipeline.h
index 36bb34f..f134579 100644
--- a/src/dawn/native/ComputePipeline.h
+++ b/src/dawn/native/ComputePipeline.h
@@ -42,8 +42,6 @@
};
protected:
- // Constructor used only for mocking and testing.
- explicit ComputePipelineBase(DeviceBase* device);
void DestroyImpl() override;
private:
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index b042919..d7132d6 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -125,6 +125,7 @@
std::string mMessage;
void* mUserdata;
};
+} // anonymous namespace
ResultOrError<Ref<PipelineLayoutBase>> ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
DeviceBase* device,
@@ -167,8 +168,6 @@
return layoutRef;
}
-} // anonymous namespace
-
// DeviceBase
DeviceBase::DeviceBase(AdapterBase* adapter,
@@ -210,7 +209,7 @@
}
DeviceBase::DeviceBase() : mState(State::Alive), mToggles(ToggleStage::Device) {
- mCaches = std::make_unique<DeviceBase::Caches>();
+ mFormatTable = BuildFormatTable(this);
}
DeviceBase::~DeviceBase() {
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index b97d2d9..ddb0e20 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -139,7 +139,7 @@
MaybeError ValidateObject(const ApiObjectBase* object) const;
AdapterBase* GetAdapter() const;
- dawn::platform::Platform* GetPlatform() const;
+ virtual dawn::platform::Platform* GetPlatform() const;
// Returns the Format corresponding to the wgpu::TextureFormat or an error if the format
// isn't a valid wgpu::TextureFormat or isn't supported by this device.
@@ -582,6 +582,16 @@
CacheKey mDeviceCacheKey;
};
+ResultOrError<Ref<PipelineLayoutBase>> ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
+ DeviceBase* device,
+ const ComputePipelineDescriptor& descriptor,
+ ComputePipelineDescriptor* outDescriptor);
+
+ResultOrError<Ref<PipelineLayoutBase>> ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults(
+ DeviceBase* device,
+ const RenderPipelineDescriptor& descriptor,
+ RenderPipelineDescriptor* outDescriptor);
+
class IgnoreLazyClearCountScope : public NonMovable {
public:
explicit IgnoreLazyClearCountScope(DeviceBase* device);
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index b95c90f..0e64216 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -137,11 +137,6 @@
GetObjectTrackingList()->Track(this);
}
-ExternalTextureBase::ExternalTextureBase(DeviceBase* device)
- : ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
- GetObjectTrackingList()->Track(this);
-}
-
// Error external texture cannot be used in bind group.
ExternalTextureBase::ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag), mState(ExternalTextureState::Destroyed) {}
diff --git a/src/dawn/native/ExternalTexture.h b/src/dawn/native/ExternalTexture.h
index 1e637b3..6cdeb13 100644
--- a/src/dawn/native/ExternalTexture.h
+++ b/src/dawn/native/ExternalTexture.h
@@ -60,18 +60,16 @@
void APIDestroy();
protected:
- // Constructor used only for mocking and testing.
- explicit ExternalTextureBase(DeviceBase* device);
+ ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
void DestroyImpl() override;
+ MaybeError Initialize(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
+
~ExternalTextureBase() override;
private:
- ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
-
enum class ExternalTextureState { Alive, Destroyed };
ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag);
- MaybeError Initialize(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
Ref<TextureBase> mPlaceholderTexture;
Ref<BufferBase> mParamsBuffer;
diff --git a/src/dawn/native/Pipeline.cpp b/src/dawn/native/Pipeline.cpp
index 8738999..854d6a8 100644
--- a/src/dawn/native/Pipeline.cpp
+++ b/src/dawn/native/Pipeline.cpp
@@ -197,8 +197,6 @@
}
}
-PipelineBase::PipelineBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {}
-
PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
diff --git a/src/dawn/native/Pipeline.h b/src/dawn/native/Pipeline.h
index 212ebb4..ac879e4 100644
--- a/src/dawn/native/Pipeline.h
+++ b/src/dawn/native/Pipeline.h
@@ -83,9 +83,6 @@
std::vector<StageAndDescriptor> stages);
PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
- // Constructor used only for mocking and testing.
- explicit PipelineBase(DeviceBase* device);
-
private:
MaybeError ValidateGetBindGroupLayout(BindGroupIndex group);
diff --git a/src/dawn/native/PipelineLayout.cpp b/src/dawn/native/PipelineLayout.cpp
index 887a519..39372be 100644
--- a/src/dawn/native/PipelineLayout.cpp
+++ b/src/dawn/native/PipelineLayout.cpp
@@ -74,11 +74,6 @@
GetObjectTrackingList()->Track(this);
}
-PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device)
- : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
diff --git a/src/dawn/native/PipelineLayout.h b/src/dawn/native/PipelineLayout.h
index c2536c2..11e9982 100644
--- a/src/dawn/native/PipelineLayout.h
+++ b/src/dawn/native/PipelineLayout.h
@@ -84,8 +84,6 @@
};
protected:
- // Constructor used only for mocking and testing.
- explicit PipelineLayoutBase(DeviceBase* device);
PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
void DestroyImpl() override;
diff --git a/src/dawn/native/QuerySet.cpp b/src/dawn/native/QuerySet.cpp
index 585e185..327f304 100644
--- a/src/dawn/native/QuerySet.cpp
+++ b/src/dawn/native/QuerySet.cpp
@@ -111,10 +111,6 @@
GetObjectTrackingList()->Track(this);
}
-QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
QuerySetBase::QuerySetBase(DeviceBase* device,
const QuerySetDescriptor* descriptor,
ObjectBase::ErrorTag tag)
diff --git a/src/dawn/native/QuerySet.h b/src/dawn/native/QuerySet.h
index d0cfd89..a24f505 100644
--- a/src/dawn/native/QuerySet.h
+++ b/src/dawn/native/QuerySet.h
@@ -52,8 +52,6 @@
const QuerySetDescriptor* descriptor,
ObjectBase::ErrorTag tag);
- // Constructor used only for mocking and testing.
- explicit QuerySetBase(DeviceBase* device);
void DestroyImpl() override;
~QuerySetBase() override;
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index da32d2d..ef234d2 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -672,10 +672,6 @@
StreamIn(&mCacheKey, CacheKey::Type::RenderPipeline, device->GetCacheKey());
}
-RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
- GetObjectTrackingList()->Track(this);
-}
-
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: PipelineBase(device, tag) {}
diff --git a/src/dawn/native/RenderPipeline.h b/src/dawn/native/RenderPipeline.h
index a1eaee6..2f37473 100644
--- a/src/dawn/native/RenderPipeline.h
+++ b/src/dawn/native/RenderPipeline.h
@@ -113,8 +113,6 @@
};
protected:
- // Constructor used only for mocking and testing.
- explicit RenderPipelineBase(DeviceBase* device);
void DestroyImpl() override;
private:
diff --git a/src/dawn/native/Sampler.cpp b/src/dawn/native/Sampler.cpp
index 2205a3b..8f1b7b9 100644
--- a/src/dawn/native/Sampler.cpp
+++ b/src/dawn/native/Sampler.cpp
@@ -89,10 +89,6 @@
GetObjectTrackingList()->Track(this);
}
-SamplerBase::SamplerBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
diff --git a/src/dawn/native/Sampler.h b/src/dawn/native/Sampler.h
index eac3446..1384327 100644
--- a/src/dawn/native/Sampler.h
+++ b/src/dawn/native/Sampler.h
@@ -53,8 +53,6 @@
uint16_t GetMaxAnisotropy() const { return mMaxAnisotropy; }
protected:
- // Constructor used only for mocking and testing.
- explicit SamplerBase(DeviceBase* device);
void DestroyImpl() override;
private:
diff --git a/src/dawn/native/ShaderModule.cpp b/src/dawn/native/ShaderModule.cpp
index 8385fd8..48ad17f 100644
--- a/src/dawn/native/ShaderModule.cpp
+++ b/src/dawn/native/ShaderModule.cpp
@@ -1111,11 +1111,6 @@
GetObjectTrackingList()->Track(this);
}
-ShaderModuleBase::ShaderModuleBase(DeviceBase* device)
- : ApiObjectBase(device, kLabelNotImplemented) {
- GetObjectTrackingList()->Track(this);
-}
-
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag), mType(Type::Undefined) {}
diff --git a/src/dawn/native/ShaderModule.h b/src/dawn/native/ShaderModule.h
index 5612d15..fd604a8 100644
--- a/src/dawn/native/ShaderModule.h
+++ b/src/dawn/native/ShaderModule.h
@@ -286,8 +286,6 @@
OwnedCompilationMessages* GetCompilationMessages() const;
protected:
- // Constructor used only for mocking and testing.
- explicit ShaderModuleBase(DeviceBase* device);
void DestroyImpl() override;
MaybeError InitializeBase(ShaderModuleParseResult* parseResult,
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index 3fe9e58..5c13abf 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -581,11 +581,6 @@
static constexpr Format kUnusedFormat;
-TextureBase::TextureBase(DeviceBase* device, TextureState state)
- : ApiObjectBase(device, kLabelNotImplemented), mFormat(kUnusedFormat), mState(state) {
- GetObjectTrackingList()->Track(this);
-}
-
TextureBase::TextureBase(DeviceBase* device,
const TextureDescriptor* descriptor,
ObjectBase::ErrorTag tag)
@@ -854,13 +849,6 @@
GetObjectTrackingList()->Track(this);
}
-TextureViewBase::TextureViewBase(TextureBase* texture)
- : ApiObjectBase(texture->GetDevice(), kLabelNotImplemented),
- mTexture(texture),
- mFormat(kUnusedFormat) {
- GetObjectTrackingList()->Track(this);
-}
-
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag), mFormat(kUnusedFormat) {}
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h
index 91372af..b6c2143 100644
--- a/src/dawn/native/Texture.h
+++ b/src/dawn/native/Texture.h
@@ -108,8 +108,6 @@
protected:
TextureBase(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
- // Constructor used only for mocking and testing.
- TextureBase(DeviceBase* device, TextureState state);
~TextureBase() override;
void DestroyImpl() override;
@@ -159,8 +157,6 @@
const SubresourceRange& GetSubresourceRange() const;
protected:
- // Constructor used only for mocking and testing.
- explicit TextureViewBase(TextureBase* texture);
void DestroyImpl() override;
private:
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 0b24f0b..fba9cf9 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -191,6 +191,7 @@
deps = [
":gmock_and_gtest",
+ "${dawn_root}/src/dawn:proc",
"${dawn_root}/src/dawn/native:sources",
"${dawn_root}/src/dawn/native:static",
"${dawn_root}/src/dawn/utils",
@@ -210,6 +211,9 @@
"unittests/native/mocks/CommandBufferMock.h",
"unittests/native/mocks/ComputePipelineMock.cpp",
"unittests/native/mocks/ComputePipelineMock.h",
+ "unittests/native/mocks/DawnMockTest.cpp",
+ "unittests/native/mocks/DawnMockTest.h",
+ "unittests/native/mocks/DeviceMock.cpp",
"unittests/native/mocks/DeviceMock.h",
"unittests/native/mocks/ExternalTextureMock.cpp",
"unittests/native/mocks/ExternalTextureMock.h",
@@ -217,6 +221,8 @@
"unittests/native/mocks/PipelineLayoutMock.h",
"unittests/native/mocks/QuerySetMock.cpp",
"unittests/native/mocks/QuerySetMock.h",
+ "unittests/native/mocks/QueueMock.cpp",
+ "unittests/native/mocks/QueueMock.h",
"unittests/native/mocks/RenderPipelineMock.cpp",
"unittests/native/mocks/RenderPipelineMock.h",
"unittests/native/mocks/SamplerMock.cpp",
diff --git a/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp b/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
index dc03f0a..6131777 100644
--- a/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
+++ b/src/dawn/tests/unittests/native/CreatePipelineAsyncTaskTests.cpp
@@ -12,27 +12,45 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "dawn/tests/DawnNativeTest.h"
+#include <gtest/gtest.h>
#include "dawn/native/CreatePipelineAsyncTask.h"
+#include "dawn/utils/WGPUHelpers.h"
#include "mocks/ComputePipelineMock.h"
+#include "mocks/DawnMockTest.h"
#include "mocks/RenderPipelineMock.h"
-class CreatePipelineAsyncTaskTests : public DawnNativeTest {};
+namespace dawn::native {
+namespace {
+
+using ::testing::Test;
+
+static constexpr std::string_view kComputeShader = R"(
+ @compute @workgroup_size(1) fn main() {}
+ )";
+
+static constexpr std::string_view kVertexShader = R"(
+ @vertex fn main() -> @builtin(position) vec4f {
+ return vec4f(0.0, 0.0, 0.0, 1.0);
+ }
+ )";
+
+class CreatePipelineAsyncTaskTests : public DawnMockTest {};
// A regression test for a null pointer issue in CreateRenderPipelineAsyncTask::Run().
// See crbug.com/dawn/1310 for more details.
TEST_F(CreatePipelineAsyncTaskTests, InitializationValidationErrorInCreateRenderPipelineAsync) {
- dawn::native::DeviceBase* deviceBase =
- reinterpret_cast<dawn::native::DeviceBase*>(device.Get());
- Ref<dawn::native::RenderPipelineMock> renderPipelineMock =
- AcquireRef(new dawn::native::RenderPipelineMock(deviceBase));
+ wgpu::RenderPipelineDescriptor desc = {};
+ desc.vertex.module = utils::CreateShaderModule(device, kVertexShader.data());
+ desc.vertex.entryPoint = "main";
+ Ref<RenderPipelineMock> renderPipelineMock =
+ RenderPipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
ON_CALL(*renderPipelineMock.Get(), Initialize)
.WillByDefault(testing::Return(testing::ByMove(
- DAWN_MAKE_ERROR(dawn::native::InternalErrorType::Validation, "Initialization Error"))));
+ DAWN_MAKE_ERROR(InternalErrorType::Validation, "Initialization Error"))));
- dawn::native::CreateRenderPipelineAsyncTask asyncTask(
+ CreateRenderPipelineAsyncTask asyncTask(
renderPipelineMock,
[](WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline returnPipeline,
const char* message, void* userdata) {
@@ -50,10 +68,11 @@
// Test that Internal error are converted to the InternalError status in async pipeline creation
// callbacks.
TEST_F(CreatePipelineAsyncTaskTests, InitializationInternalErrorInCreateRenderPipelineAsync) {
- dawn::native::DeviceBase* deviceBase =
- reinterpret_cast<dawn::native::DeviceBase*>(device.Get());
- Ref<dawn::native::RenderPipelineMock> renderPipelineMock =
- AcquireRef(new dawn::native::RenderPipelineMock(deviceBase));
+ wgpu::RenderPipelineDescriptor desc = {};
+ desc.vertex.module = utils::CreateShaderModule(device, kVertexShader.data());
+ desc.vertex.entryPoint = "main";
+ Ref<RenderPipelineMock> renderPipelineMock =
+ RenderPipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
ON_CALL(*renderPipelineMock.Get(), Initialize)
.WillByDefault(testing::Return(testing::ByMove(
@@ -77,16 +96,17 @@
// A regression test for a null pointer issue in CreateComputePipelineAsyncTask::Run().
// See crbug.com/dawn/1310 for more details.
TEST_F(CreatePipelineAsyncTaskTests, InitializationValidationErrorInCreateComputePipelineAsync) {
- dawn::native::DeviceBase* deviceBase =
- reinterpret_cast<dawn::native::DeviceBase*>(device.Get());
- Ref<dawn::native::ComputePipelineMock> computePipelineMock =
- AcquireRef(new dawn::native::ComputePipelineMock(deviceBase));
+ wgpu::ComputePipelineDescriptor desc = {};
+ desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
+ desc.compute.entryPoint = "main";
+ Ref<ComputePipelineMock> computePipelineMock =
+ ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
ON_CALL(*computePipelineMock.Get(), Initialize)
.WillByDefault(testing::Return(testing::ByMove(
- DAWN_MAKE_ERROR(dawn::native::InternalErrorType::Validation, "Initialization Error"))));
+ DAWN_MAKE_ERROR(InternalErrorType::Validation, "Initialization Error"))));
- dawn::native::CreateComputePipelineAsyncTask asyncTask(
+ CreateComputePipelineAsyncTask asyncTask(
computePipelineMock,
[](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
const char* message, void* userdata) {
@@ -104,10 +124,11 @@
// Test that Internal error are converted to the InternalError status in async pipeline creation
// callbacks.
TEST_F(CreatePipelineAsyncTaskTests, InitializationInternalErrorInCreateComputePipelineAsync) {
- dawn::native::DeviceBase* deviceBase =
- reinterpret_cast<dawn::native::DeviceBase*>(device.Get());
- Ref<dawn::native::ComputePipelineMock> computePipelineMock =
- AcquireRef(new dawn::native::ComputePipelineMock(deviceBase));
+ wgpu::ComputePipelineDescriptor desc = {};
+ desc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
+ desc.compute.entryPoint = "main";
+ Ref<ComputePipelineMock> computePipelineMock =
+ ComputePipelineMock::Create(mDeviceMock, FromCppAPI(&desc));
ON_CALL(*computePipelineMock.Get(), Initialize)
.WillByDefault(testing::Return(testing::ByMove(
@@ -127,3 +148,6 @@
EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
}
+
+} // namespace
+} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/DestroyObjectTests.cpp b/src/dawn/tests/unittests/native/DestroyObjectTests.cpp
index 4cc2c3b..8151f79 100644
--- a/src/dawn/tests/unittests/native/DestroyObjectTests.cpp
+++ b/src/dawn/tests/unittests/native/DestroyObjectTests.cpp
@@ -14,15 +14,22 @@
#include <gtest/gtest.h>
+#include <utility>
+#include <vector>
+
#include "dawn/native/Toggles.h"
+#include "dawn/native/utils/WGPUHelpers.h"
#include "dawn/tests/DawnNativeTest.h"
+#include "dawn/tests/MockCallback.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"
+#include "dawn/webgpu_cpp.h"
#include "mocks/BindGroupLayoutMock.h"
#include "mocks/BindGroupMock.h"
#include "mocks/BufferMock.h"
#include "mocks/CommandBufferMock.h"
#include "mocks/ComputePipelineMock.h"
+#include "mocks/DawnMockTest.h"
#include "mocks/DeviceMock.h"
#include "mocks/ExternalTextureMock.h"
#include "mocks/PipelineLayoutMock.h"
@@ -39,721 +46,13 @@
using ::testing::_;
using ::testing::ByMove;
using ::testing::InSequence;
+using ::testing::Mock;
+using testing::MockCallback;
+using ::testing::NiceMock;
using ::testing::Return;
+using ::testing::StrictMock;
using ::testing::Test;
-class DestroyObjectTests : public Test {
- public:
- DestroyObjectTests() : Test() {
- // Skipping validation on descriptors as coverage for validation is already present.
- mDevice.ForceSetToggleForTesting(Toggle::SkipValidation, true);
- }
-
- Ref<TextureMock> GetTexture() {
- if (mTexture != nullptr) {
- return mTexture;
- }
- mTexture = AcquireRef(new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal));
- EXPECT_CALL(*mTexture.Get(), DestroyImpl).Times(1);
- return mTexture;
- }
-
- Ref<PipelineLayoutMock> GetPipelineLayout() {
- if (mPipelineLayout != nullptr) {
- return mPipelineLayout;
- }
- mPipelineLayout = AcquireRef(new PipelineLayoutMock(&mDevice));
- EXPECT_CALL(*mPipelineLayout.Get(), DestroyImpl).Times(1);
- return mPipelineLayout;
- }
-
- Ref<ShaderModuleMock> GetVertexShaderModule() {
- if (mVsModule != nullptr) {
- return mVsModule;
- }
- DAWN_TRY_ASSIGN_WITH_CLEANUP(
- mVsModule, ShaderModuleMock::Create(&mDevice, R"(
- @vertex fn main() -> @builtin(position) vec4f {
- return vec4f(0.0, 0.0, 0.0, 1.0);
- })"),
- { ASSERT(false); }, mVsModule);
- EXPECT_CALL(*mVsModule.Get(), DestroyImpl).Times(1);
- return mVsModule;
- }
-
- Ref<ShaderModuleMock> GetComputeShaderModule() {
- if (mCsModule != nullptr) {
- return mCsModule;
- }
- DAWN_TRY_ASSIGN_WITH_CLEANUP(
- mCsModule, ShaderModuleMock::Create(&mDevice, R"(
- @compute @workgroup_size(1) fn main() {
- })"),
- { ASSERT(false); }, mCsModule);
- EXPECT_CALL(*mCsModule.Get(), DestroyImpl).Times(1);
- return mCsModule;
- }
-
- protected:
- DeviceMock mDevice;
-
- // The following lazy-initialized objects are used to facilitate creation of dependent
- // objects under test.
- Ref<TextureMock> mTexture;
- Ref<PipelineLayoutMock> mPipelineLayout;
- Ref<ShaderModuleMock> mVsModule;
- Ref<ShaderModuleMock> mCsModule;
-};
-
-TEST_F(DestroyObjectTests, BindGroupExplicit) {
- BindGroupMock bindGroupMock(&mDevice);
- EXPECT_CALL(bindGroupMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(bindGroupMock.IsAlive());
- bindGroupMock.Destroy();
- EXPECT_FALSE(bindGroupMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, BindGroupImplicit) {
- BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
- EXPECT_CALL(*bindGroupMock, DestroyImpl).Times(1);
- {
- BindGroupDescriptor desc = {};
- Ref<BindGroupBase> bindGroup;
- EXPECT_CALL(mDevice, CreateBindGroupImpl)
- .WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
- DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
-
- EXPECT_TRUE(bindGroup->IsAlive());
- }
-}
-
-TEST_F(DestroyObjectTests, BindGroupLayoutExplicit) {
- BindGroupLayoutMock bindGroupLayoutMock(&mDevice);
- EXPECT_CALL(bindGroupLayoutMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(bindGroupLayoutMock.IsAlive());
- bindGroupLayoutMock.Destroy();
- EXPECT_FALSE(bindGroupLayoutMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, BindGroupLayoutImplicit) {
- BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
- EXPECT_CALL(*bindGroupLayoutMock, DestroyImpl).Times(1);
- {
- BindGroupLayoutDescriptor desc = {};
- Ref<BindGroupLayoutBase> bindGroupLayout;
- EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
- .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
- DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, mDevice.CreateBindGroupLayout(&desc));
-
- EXPECT_TRUE(bindGroupLayout->IsAlive());
- EXPECT_TRUE(bindGroupLayout->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, BufferExplicit) {
- {
- BufferMock bufferMock(&mDevice, BufferBase::BufferState::Unmapped);
- EXPECT_CALL(bufferMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(bufferMock.IsAlive());
- bufferMock.Destroy();
- EXPECT_FALSE(bufferMock.IsAlive());
- }
- {
- BufferMock bufferMock(&mDevice, BufferBase::BufferState::Mapped);
- {
- InSequence seq;
- EXPECT_CALL(bufferMock, DestroyImpl).Times(1);
- EXPECT_CALL(bufferMock, UnmapImpl).Times(1);
- }
-
- EXPECT_TRUE(bufferMock.IsAlive());
- bufferMock.Destroy();
- EXPECT_FALSE(bufferMock.IsAlive());
- }
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, BufferImplicit) {
- {
- BufferMock* bufferMock = new BufferMock(&mDevice, BufferBase::BufferState::Unmapped);
- EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
- {
- BufferDescriptor desc = {};
- Ref<BufferBase> buffer;
- EXPECT_CALL(mDevice, CreateBufferImpl).WillOnce(Return(ByMove(AcquireRef(bufferMock))));
- DAWN_ASSERT_AND_ASSIGN(buffer, mDevice.CreateBuffer(&desc));
-
- EXPECT_TRUE(buffer->IsAlive());
- }
- }
- {
- BufferMock* bufferMock = new BufferMock(&mDevice, BufferBase::BufferState::Mapped);
- {
- InSequence seq;
- EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
- EXPECT_CALL(*bufferMock, UnmapImpl).Times(1);
- }
- {
- BufferDescriptor desc = {};
- Ref<BufferBase> buffer;
- EXPECT_CALL(mDevice, CreateBufferImpl).WillOnce(Return(ByMove(AcquireRef(bufferMock))));
- DAWN_ASSERT_AND_ASSIGN(buffer, mDevice.CreateBuffer(&desc));
-
- EXPECT_TRUE(buffer->IsAlive());
- }
- }
-}
-
-TEST_F(DestroyObjectTests, CommandBufferExplicit) {
- CommandBufferMock commandBufferMock(&mDevice);
- EXPECT_CALL(commandBufferMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(commandBufferMock.IsAlive());
- commandBufferMock.Destroy();
- EXPECT_FALSE(commandBufferMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, CommandBufferImplicit) {
- CommandBufferMock* commandBufferMock = new CommandBufferMock(&mDevice);
- EXPECT_CALL(*commandBufferMock, DestroyImpl).Times(1);
- {
- CommandBufferDescriptor desc = {};
- Ref<CommandBufferBase> commandBuffer;
- EXPECT_CALL(mDevice, CreateCommandBuffer)
- .WillOnce(Return(ByMove(AcquireRef(commandBufferMock))));
- DAWN_ASSERT_AND_ASSIGN(commandBuffer, mDevice.CreateCommandBuffer(nullptr, &desc));
-
- EXPECT_TRUE(commandBuffer->IsAlive());
- }
-}
-
-TEST_F(DestroyObjectTests, ComputePipelineExplicit) {
- ComputePipelineMock computePipelineMock(&mDevice);
- EXPECT_CALL(computePipelineMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(computePipelineMock.IsAlive());
- computePipelineMock.Destroy();
- EXPECT_FALSE(computePipelineMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, ComputePipelineImplicit) {
- // ComputePipelines usually set their hash values at construction, but the mock does not, so
- // we set it here.
- constexpr size_t hash = 0x12345;
- ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
- computePipelineMock->SetContentHash(hash);
- ON_CALL(*computePipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
- // Compute pipelines are initialized during their creation via the device.
- EXPECT_CALL(*computePipelineMock, Initialize).Times(1);
- EXPECT_CALL(*computePipelineMock, DestroyImpl).Times(1);
-
- {
- ComputePipelineDescriptor desc = {};
- desc.layout = GetPipelineLayout().Get();
- desc.compute.module = GetComputeShaderModule().Get();
-
- Ref<ComputePipelineBase> computePipeline;
- EXPECT_CALL(mDevice, CreateUninitializedComputePipelineImpl)
- .WillOnce(Return(ByMove(AcquireRef(computePipelineMock))));
- DAWN_ASSERT_AND_ASSIGN(computePipeline, mDevice.CreateComputePipeline(&desc));
-
- EXPECT_TRUE(computePipeline->IsAlive());
- EXPECT_TRUE(computePipeline->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, ExternalTextureExplicit) {
- ExternalTextureMock externalTextureMock(&mDevice);
- EXPECT_CALL(externalTextureMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(externalTextureMock.IsAlive());
- externalTextureMock.Destroy();
- EXPECT_FALSE(externalTextureMock.IsAlive());
-}
-
-TEST_F(DestroyObjectTests, ExternalTextureImplicit) {
- ExternalTextureMock* externalTextureMock = new ExternalTextureMock(&mDevice);
- EXPECT_CALL(*externalTextureMock, DestroyImpl).Times(1);
- {
- ExternalTextureDescriptor desc = {};
- Ref<ExternalTextureBase> externalTexture;
- EXPECT_CALL(mDevice, CreateExternalTextureImpl)
- .WillOnce(Return(ByMove(AcquireRef(externalTextureMock))));
- DAWN_ASSERT_AND_ASSIGN(externalTexture, mDevice.CreateExternalTextureImpl(&desc));
-
- EXPECT_TRUE(externalTexture->IsAlive());
- }
-}
-
-TEST_F(DestroyObjectTests, PipelineLayoutExplicit) {
- PipelineLayoutMock pipelineLayoutMock(&mDevice);
- EXPECT_CALL(pipelineLayoutMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(pipelineLayoutMock.IsAlive());
- pipelineLayoutMock.Destroy();
- EXPECT_FALSE(pipelineLayoutMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, PipelineLayoutImplicit) {
- PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
- EXPECT_CALL(*pipelineLayoutMock, DestroyImpl).Times(1);
- {
- PipelineLayoutDescriptor desc = {};
- Ref<PipelineLayoutBase> pipelineLayout;
- EXPECT_CALL(mDevice, CreatePipelineLayoutImpl)
- .WillOnce(Return(ByMove(AcquireRef(pipelineLayoutMock))));
- DAWN_ASSERT_AND_ASSIGN(pipelineLayout, mDevice.CreatePipelineLayout(&desc));
-
- EXPECT_TRUE(pipelineLayout->IsAlive());
- EXPECT_TRUE(pipelineLayout->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, QuerySetExplicit) {
- QuerySetMock querySetMock(&mDevice);
- EXPECT_CALL(querySetMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(querySetMock.IsAlive());
- querySetMock.Destroy();
- EXPECT_FALSE(querySetMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, QuerySetImplicit) {
- QuerySetMock* querySetMock = new QuerySetMock(&mDevice);
- EXPECT_CALL(*querySetMock, DestroyImpl).Times(1);
- {
- QuerySetDescriptor desc = {};
- Ref<QuerySetBase> querySet;
- EXPECT_CALL(mDevice, CreateQuerySetImpl).WillOnce(Return(ByMove(AcquireRef(querySetMock))));
- DAWN_ASSERT_AND_ASSIGN(querySet, mDevice.CreateQuerySet(&desc));
-
- EXPECT_TRUE(querySet->IsAlive());
- }
-}
-
-TEST_F(DestroyObjectTests, RenderPipelineExplicit) {
- RenderPipelineMock renderPipelineMock(&mDevice);
- EXPECT_CALL(renderPipelineMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(renderPipelineMock.IsAlive());
- renderPipelineMock.Destroy();
- EXPECT_FALSE(renderPipelineMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, RenderPipelineImplicit) {
- // RenderPipelines usually set their hash values at construction, but the mock does not, so
- // we set it here.
- constexpr size_t hash = 0x12345;
- RenderPipelineMock* renderPipelineMock = new RenderPipelineMock(&mDevice);
- renderPipelineMock->SetContentHash(hash);
- ON_CALL(*renderPipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
- // Render pipelines are initialized during their creation via the device.
- EXPECT_CALL(*renderPipelineMock, Initialize).Times(1);
- EXPECT_CALL(*renderPipelineMock, DestroyImpl).Times(1);
-
- {
- RenderPipelineDescriptor desc = {};
- desc.layout = GetPipelineLayout().Get();
- desc.vertex.module = GetVertexShaderModule().Get();
-
- Ref<RenderPipelineBase> renderPipeline;
- EXPECT_CALL(mDevice, CreateUninitializedRenderPipelineImpl)
- .WillOnce(Return(ByMove(AcquireRef(renderPipelineMock))));
- DAWN_ASSERT_AND_ASSIGN(renderPipeline, mDevice.CreateRenderPipeline(&desc));
-
- EXPECT_TRUE(renderPipeline->IsAlive());
- EXPECT_TRUE(renderPipeline->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, SamplerExplicit) {
- SamplerMock samplerMock(&mDevice);
- EXPECT_CALL(samplerMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(samplerMock.IsAlive());
- samplerMock.Destroy();
- EXPECT_FALSE(samplerMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, SamplerImplicit) {
- SamplerMock* samplerMock = new SamplerMock(&mDevice);
- EXPECT_CALL(*samplerMock, DestroyImpl).Times(1);
- {
- SamplerDescriptor desc = {};
- Ref<SamplerBase> sampler;
- EXPECT_CALL(mDevice, CreateSamplerImpl).WillOnce(Return(ByMove(AcquireRef(samplerMock))));
- DAWN_ASSERT_AND_ASSIGN(sampler, mDevice.CreateSampler(&desc));
-
- EXPECT_TRUE(sampler->IsAlive());
- EXPECT_TRUE(sampler->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, ShaderModuleExplicit) {
- ShaderModuleMock shaderModuleMock(&mDevice);
- EXPECT_CALL(shaderModuleMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(shaderModuleMock.IsAlive());
- shaderModuleMock.Destroy();
- EXPECT_FALSE(shaderModuleMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, ShaderModuleImplicit) {
- ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
- EXPECT_CALL(*shaderModuleMock, DestroyImpl).Times(1);
- {
- ShaderModuleWGSLDescriptor wgslDesc;
- wgslDesc.source = R"(
- @compute @workgroup_size(1) fn main() {
- }
- )";
- ShaderModuleDescriptor desc = {};
- desc.nextInChain = &wgslDesc;
- Ref<ShaderModuleBase> shaderModule;
- EXPECT_CALL(mDevice, CreateShaderModuleImpl)
- .WillOnce(Return(ByMove(AcquireRef(shaderModuleMock))));
- DAWN_ASSERT_AND_ASSIGN(shaderModule, mDevice.CreateShaderModule(&desc));
-
- EXPECT_TRUE(shaderModule->IsAlive());
- EXPECT_TRUE(shaderModule->IsCachedReference());
- }
-}
-
-TEST_F(DestroyObjectTests, SwapChainExplicit) {
- SwapChainMock swapChainMock(&mDevice);
- EXPECT_CALL(swapChainMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(swapChainMock.IsAlive());
- swapChainMock.Destroy();
- EXPECT_FALSE(swapChainMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, SwapChainImplicit) {
- SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
- EXPECT_CALL(*swapChainMock, DestroyImpl).Times(1);
- {
- SwapChainDescriptor desc = {};
- Ref<SwapChainBase> swapChain;
- EXPECT_CALL(mDevice, CreateSwapChainImpl(_))
- .WillOnce(Return(ByMove(AcquireRef(swapChainMock))));
- DAWN_ASSERT_AND_ASSIGN(swapChain, mDevice.CreateSwapChain(nullptr, &desc));
-
- EXPECT_TRUE(swapChain->IsAlive());
- }
-}
-
-TEST_F(DestroyObjectTests, TextureExplicit) {
- {
- TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
- EXPECT_CALL(textureMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(textureMock.IsAlive());
- textureMock.Destroy();
- EXPECT_FALSE(textureMock.IsAlive());
- }
- {
- TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
- EXPECT_CALL(textureMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(textureMock.IsAlive());
- textureMock.Destroy();
- EXPECT_FALSE(textureMock.IsAlive());
- }
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, TextureImplicit) {
- {
- TextureMock* textureMock =
- new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
- EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
- {
- TextureDescriptor desc = {};
- Ref<TextureBase> texture;
- EXPECT_CALL(mDevice, CreateTextureImpl)
- .WillOnce(Return(ByMove(AcquireRef(textureMock))));
- DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
-
- EXPECT_TRUE(texture->IsAlive());
- }
- }
- {
- TextureMock* textureMock =
- new TextureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
- EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
- {
- TextureDescriptor desc = {};
- Ref<TextureBase> texture;
- EXPECT_CALL(mDevice, CreateTextureImpl)
- .WillOnce(Return(ByMove(AcquireRef(textureMock))));
- DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
-
- EXPECT_TRUE(texture->IsAlive());
- }
- }
-}
-
-TEST_F(DestroyObjectTests, TextureViewExplicit) {
- TextureViewMock textureViewMock(GetTexture().Get());
- EXPECT_CALL(textureViewMock, DestroyImpl).Times(1);
-
- EXPECT_TRUE(textureViewMock.IsAlive());
- textureViewMock.Destroy();
- EXPECT_FALSE(textureViewMock.IsAlive());
-}
-
-// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-// will also complain if there is a memory leak.
-TEST_F(DestroyObjectTests, TextureViewImplicit) {
- TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
- EXPECT_CALL(*textureViewMock, DestroyImpl).Times(1);
- {
- TextureViewDescriptor desc = {};
- Ref<TextureViewBase> textureView;
- EXPECT_CALL(mDevice, CreateTextureViewImpl)
- .WillOnce(Return(ByMove(AcquireRef(textureViewMock))));
- DAWN_ASSERT_AND_ASSIGN(textureView, mDevice.CreateTextureView(GetTexture().Get(), &desc));
-
- EXPECT_TRUE(textureView->IsAlive());
- }
-}
-
-// Destroying the objects on the mDevice should result in all created objects being destroyed in
-// order.
-TEST_F(DestroyObjectTests, DestroyObjects) {
- BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
- BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
- BufferMock* bufferMock = new BufferMock(&mDevice, BufferBase::BufferState::Unmapped);
- CommandBufferMock* commandBufferMock = new CommandBufferMock(&mDevice);
- ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
- ExternalTextureMock* externalTextureMock = new ExternalTextureMock(&mDevice);
- PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
- QuerySetMock* querySetMock = new QuerySetMock(&mDevice);
- RenderPipelineMock* renderPipelineMock = new RenderPipelineMock(&mDevice);
- SamplerMock* samplerMock = new SamplerMock(&mDevice);
- ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
- SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
- TextureMock* textureMock = new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
- TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
- {
- InSequence seq;
- EXPECT_CALL(*commandBufferMock, DestroyImpl).Times(1);
- EXPECT_CALL(*renderPipelineMock, DestroyImpl).Times(1);
- EXPECT_CALL(*computePipelineMock, DestroyImpl).Times(1);
- EXPECT_CALL(*pipelineLayoutMock, DestroyImpl).Times(1);
- EXPECT_CALL(*swapChainMock, DestroyImpl).Times(1);
- EXPECT_CALL(*bindGroupMock, DestroyImpl).Times(1);
- EXPECT_CALL(*bindGroupLayoutMock, DestroyImpl).Times(1);
- EXPECT_CALL(*shaderModuleMock, DestroyImpl).Times(1);
- EXPECT_CALL(*externalTextureMock, DestroyImpl).Times(1);
- EXPECT_CALL(*textureViewMock, DestroyImpl).Times(1);
- EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
- EXPECT_CALL(*querySetMock, DestroyImpl).Times(1);
- EXPECT_CALL(*samplerMock, DestroyImpl).Times(1);
- EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
- }
-
- Ref<BindGroupBase> bindGroup;
- {
- BindGroupDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateBindGroupImpl)
- .WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
- DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
- EXPECT_TRUE(bindGroup->IsAlive());
- }
-
- Ref<BindGroupLayoutBase> bindGroupLayout;
- {
- BindGroupLayoutDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
- .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
- DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, mDevice.CreateBindGroupLayout(&desc));
- EXPECT_TRUE(bindGroupLayout->IsAlive());
- EXPECT_TRUE(bindGroupLayout->IsCachedReference());
- }
-
- Ref<BufferBase> buffer;
- {
- BufferDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateBufferImpl).WillOnce(Return(ByMove(AcquireRef(bufferMock))));
- DAWN_ASSERT_AND_ASSIGN(buffer, mDevice.CreateBuffer(&desc));
- EXPECT_TRUE(buffer->IsAlive());
- }
-
- Ref<CommandBufferBase> commandBuffer;
- {
- CommandBufferDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateCommandBuffer)
- .WillOnce(Return(ByMove(AcquireRef(commandBufferMock))));
- DAWN_ASSERT_AND_ASSIGN(commandBuffer, mDevice.CreateCommandBuffer(nullptr, &desc));
- EXPECT_TRUE(commandBuffer->IsAlive());
- }
-
- Ref<ComputePipelineBase> computePipeline;
- {
- // Compute pipelines usually set their hash values at construction, but the mock does
- // not, so we set it here.
- constexpr size_t hash = 0x12345;
- computePipelineMock->SetContentHash(hash);
- ON_CALL(*computePipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
- // Compute pipelines are initialized during their creation via the device.
- EXPECT_CALL(*computePipelineMock, Initialize).Times(1);
-
- ComputePipelineDescriptor desc = {};
- desc.layout = GetPipelineLayout().Get();
- desc.compute.module = GetComputeShaderModule().Get();
- EXPECT_CALL(mDevice, CreateUninitializedComputePipelineImpl)
- .WillOnce(Return(ByMove(AcquireRef(computePipelineMock))));
- DAWN_ASSERT_AND_ASSIGN(computePipeline, mDevice.CreateComputePipeline(&desc));
- EXPECT_TRUE(computePipeline->IsAlive());
- EXPECT_TRUE(computePipeline->IsCachedReference());
- }
-
- Ref<ExternalTextureBase> externalTexture;
- {
- ExternalTextureDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateExternalTextureImpl)
- .WillOnce(Return(ByMove(AcquireRef(externalTextureMock))));
- DAWN_ASSERT_AND_ASSIGN(externalTexture, mDevice.CreateExternalTextureImpl(&desc));
- EXPECT_TRUE(externalTexture->IsAlive());
- }
-
- Ref<PipelineLayoutBase> pipelineLayout;
- {
- PipelineLayoutDescriptor desc = {};
- EXPECT_CALL(mDevice, CreatePipelineLayoutImpl)
- .WillOnce(Return(ByMove(AcquireRef(pipelineLayoutMock))));
- DAWN_ASSERT_AND_ASSIGN(pipelineLayout, mDevice.CreatePipelineLayout(&desc));
- EXPECT_TRUE(pipelineLayout->IsAlive());
- EXPECT_TRUE(pipelineLayout->IsCachedReference());
- }
-
- Ref<QuerySetBase> querySet;
- {
- QuerySetDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateQuerySetImpl).WillOnce(Return(ByMove(AcquireRef(querySetMock))));
- DAWN_ASSERT_AND_ASSIGN(querySet, mDevice.CreateQuerySet(&desc));
- EXPECT_TRUE(querySet->IsAlive());
- }
-
- Ref<RenderPipelineBase> renderPipeline;
- {
- // Render pipelines usually set their hash values at construction, but the mock does
- // not, so we set it here.
- constexpr size_t hash = 0x12345;
- renderPipelineMock->SetContentHash(hash);
- ON_CALL(*renderPipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
- // Render pipelines are initialized during their creation via the device.
- EXPECT_CALL(*renderPipelineMock, Initialize).Times(1);
-
- RenderPipelineDescriptor desc = {};
- desc.layout = GetPipelineLayout().Get();
- desc.vertex.module = GetVertexShaderModule().Get();
- EXPECT_CALL(mDevice, CreateUninitializedRenderPipelineImpl)
- .WillOnce(Return(ByMove(AcquireRef(renderPipelineMock))));
- DAWN_ASSERT_AND_ASSIGN(renderPipeline, mDevice.CreateRenderPipeline(&desc));
- EXPECT_TRUE(renderPipeline->IsAlive());
- EXPECT_TRUE(renderPipeline->IsCachedReference());
- }
-
- Ref<SamplerBase> sampler;
- {
- SamplerDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateSamplerImpl).WillOnce(Return(ByMove(AcquireRef(samplerMock))));
- DAWN_ASSERT_AND_ASSIGN(sampler, mDevice.CreateSampler(&desc));
- EXPECT_TRUE(sampler->IsAlive());
- EXPECT_TRUE(sampler->IsCachedReference());
- }
-
- Ref<ShaderModuleBase> shaderModule;
- {
- ShaderModuleWGSLDescriptor wgslDesc;
- wgslDesc.source = R"(
- @compute @workgroup_size(1) fn main() {
- }
- )";
- ShaderModuleDescriptor desc = {};
- desc.nextInChain = &wgslDesc;
-
- EXPECT_CALL(mDevice, CreateShaderModuleImpl)
- .WillOnce(Return(ByMove(AcquireRef(shaderModuleMock))));
- DAWN_ASSERT_AND_ASSIGN(shaderModule, mDevice.CreateShaderModule(&desc));
- EXPECT_TRUE(shaderModule->IsAlive());
- EXPECT_TRUE(shaderModule->IsCachedReference());
- }
-
- Ref<SwapChainBase> swapChain;
- {
- SwapChainDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateSwapChainImpl(_))
- .WillOnce(Return(ByMove(AcquireRef(swapChainMock))));
- DAWN_ASSERT_AND_ASSIGN(swapChain, mDevice.CreateSwapChain(nullptr, &desc));
- EXPECT_TRUE(swapChain->IsAlive());
- }
-
- Ref<TextureBase> texture;
- {
- TextureDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateTextureImpl).WillOnce(Return(ByMove(AcquireRef(textureMock))));
- DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
- EXPECT_TRUE(texture->IsAlive());
- }
-
- Ref<TextureViewBase> textureView;
- {
- TextureViewDescriptor desc = {};
- EXPECT_CALL(mDevice, CreateTextureViewImpl)
- .WillOnce(Return(ByMove(AcquireRef(textureViewMock))));
- DAWN_ASSERT_AND_ASSIGN(textureView, mDevice.CreateTextureView(GetTexture().Get(), &desc));
- EXPECT_TRUE(textureView->IsAlive());
- }
-
- mDevice.DestroyObjects();
- EXPECT_FALSE(bindGroup->IsAlive());
- EXPECT_FALSE(bindGroupLayout->IsAlive());
- EXPECT_FALSE(buffer->IsAlive());
- EXPECT_FALSE(commandBuffer->IsAlive());
- EXPECT_FALSE(computePipeline->IsAlive());
- EXPECT_FALSE(externalTexture->IsAlive());
- EXPECT_FALSE(pipelineLayout->IsAlive());
- EXPECT_FALSE(querySet->IsAlive());
- EXPECT_FALSE(renderPipeline->IsAlive());
- EXPECT_FALSE(sampler->IsAlive());
- EXPECT_FALSE(shaderModule->IsAlive());
- EXPECT_FALSE(swapChain->IsAlive());
- EXPECT_FALSE(texture->IsAlive());
- EXPECT_FALSE(textureView->IsAlive());
-}
-
static constexpr std::string_view kComputeShader = R"(
@compute @workgroup_size(1) fn main() {}
)";
@@ -768,6 +67,971 @@
@fragment fn main() {}
)";
+// Stores and scopes a raw mock object ptr expectation. This is particularly useful on objects that
+// are expected to be destroyed at the end of the scope. In most cases, when the validation in this
+// class's destructor is ran, the pointer is probably already freed.
+class ScopedRawPtrExpectation {
+ public:
+ explicit ScopedRawPtrExpectation(void* ptr) : mPtr(ptr) {}
+ ~ScopedRawPtrExpectation() { Mock::VerifyAndClearExpectations(mPtr); }
+
+ private:
+ void* mPtr = nullptr;
+};
+
+class DestroyObjectTests : public DawnMockTest {
+ public:
+ DestroyObjectTests() : DawnMockTest() {
+ // Skipping validation on descriptors as coverage for validation is already present.
+ mDeviceMock->ForceSetToggleForTesting(Toggle::SkipValidation, true);
+ }
+};
+
+TEST_F(DestroyObjectTests, BindGroupNativeExplicit) {
+ BindGroupDescriptor desc = {};
+ desc.layout = mDeviceMock->GetEmptyBindGroupLayoutMock();
+ desc.entryCount = 0;
+ desc.entries = nullptr;
+
+ Ref<BindGroupMock> bindGroupMock = AcquireRef(new BindGroupMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bindGroupMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(bindGroupMock->IsAlive());
+ bindGroupMock->Destroy();
+ EXPECT_FALSE(bindGroupMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, BindGroupImplicit) {
+ BindGroupDescriptor desc = {};
+ desc.layout = mDeviceMock->GetEmptyBindGroupLayoutMock();
+ desc.entryCount = 0;
+ desc.entries = nullptr;
+
+ Ref<BindGroupMock> bindGroupMock = AcquireRef(new BindGroupMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bindGroupMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(bindGroupMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateBindGroupImpl)
+ .WillOnce(Return(ByMove(std::move(bindGroupMock))));
+ wgpu::BindGroup bindGroup = device.CreateBindGroup(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(bindGroup.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, BindGroupLayoutNativeExplicit) {
+ // Use an non-empty bind group layout to avoid hitting the internal empty layout in the cache.
+ BindGroupLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutEntry> entries;
+ entries.push_back(utils::BindingLayoutEntryInitializationHelper(
+ 0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform));
+ desc.entryCount = static_cast<uint32_t>(entries.size());
+ desc.entries = entries.data();
+
+ Ref<BindGroupLayoutMock> bindGroupLayoutMock =
+ AcquireRef(new BindGroupLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bindGroupLayoutMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(bindGroupLayoutMock->IsAlive());
+ bindGroupLayoutMock->Destroy();
+ EXPECT_FALSE(bindGroupLayoutMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, BindGroupLayoutImplicit) {
+ // Use an non-empty bind group layout to avoid hitting the internal empty layout in the cache.
+ BindGroupLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutEntry> entries;
+ entries.push_back(utils::BindingLayoutEntryInitializationHelper(
+ 0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform));
+ desc.entryCount = static_cast<uint32_t>(entries.size());
+ desc.entries = entries.data();
+
+ Ref<BindGroupLayoutMock> bindGroupLayoutMock =
+ AcquireRef(new BindGroupLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bindGroupLayoutMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(bindGroupLayoutMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateBindGroupLayoutImpl)
+ .WillOnce(Return(ByMove(std::move(bindGroupLayoutMock))));
+ wgpu::BindGroupLayout bindGroupLayout = device.CreateBindGroupLayout(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(bindGroupLayout.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(bindGroupLayout.Get())->IsCachedReference());
+ }
+}
+
+TEST_F(DestroyObjectTests, BufferNativeExplicit) {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::Uniform;
+
+ Ref<BufferMock> bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(bufferMock->IsAlive());
+ bufferMock->Destroy();
+ EXPECT_FALSE(bufferMock->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, BufferApiExplicit) {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::Uniform;
+
+ Ref<BufferMock> bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(ByMove(std::move(bufferMock))));
+ wgpu::Buffer buffer = device.CreateBuffer(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(buffer.Get())->IsAlive());
+ buffer.Destroy();
+ EXPECT_FALSE(FromAPI(buffer.Get())->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, BufferImplicit) {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::Uniform;
+
+ Ref<BufferMock> bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(bufferMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(ByMove(std::move(bufferMock))));
+ wgpu::Buffer buffer = device.CreateBuffer(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(buffer.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, MappedBufferApiExplicit) {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::MapRead;
+
+ StrictMock<MockCallback<wgpu::BufferMapCallback>> cb;
+ EXPECT_CALL(cb, Call).Times(1);
+ Ref<BufferMock> bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ {
+ InSequence seq;
+ EXPECT_CALL(*bufferMock.Get(), MapAsyncImpl).WillOnce([]() -> MaybeError { return {}; });
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*bufferMock.Get(), UnmapImpl).Times(1);
+ }
+ {
+ EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(ByMove(std::move(bufferMock))));
+ wgpu::Buffer buffer = device.CreateBuffer(ToCppAPI(&desc));
+ buffer.MapAsync(wgpu::MapMode::Read, 0, 16, cb.Callback(), cb.MakeUserdata(this));
+ device.Tick();
+
+ EXPECT_TRUE(FromAPI(buffer.Get())->IsAlive());
+ buffer.Destroy();
+ EXPECT_FALSE(FromAPI(buffer.Get())->IsAlive());
+ }
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, MappedBufferImplicit) {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::MapRead;
+
+ StrictMock<MockCallback<wgpu::BufferMapCallback>> cb;
+ EXPECT_CALL(cb, Call).Times(1);
+ Ref<BufferMock> bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ {
+ InSequence seq;
+ EXPECT_CALL(*bufferMock.Get(), MapAsyncImpl).WillOnce([]() -> MaybeError { return {}; });
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*bufferMock.Get(), UnmapImpl).Times(1);
+ }
+ {
+ ScopedRawPtrExpectation scoped(bufferMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(ByMove(std::move(bufferMock))));
+ wgpu::Buffer buffer = device.CreateBuffer(ToCppAPI(&desc));
+ buffer.MapAsync(wgpu::MapMode::Read, 0, 16, cb.Callback(), cb.MakeUserdata(this));
+ device.Tick();
+
+ EXPECT_TRUE(FromAPI(buffer.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, CommandBufferNativeExplicit) {
+ CommandEncoderDescriptor commandEncoderDesc = {};
+ Ref<CommandEncoder> commandEncoder = CommandEncoder::Create(mDeviceMock, &commandEncoderDesc);
+
+ CommandBufferDescriptor commandBufferDesc = {};
+
+ Ref<CommandBufferMock> commandBufferMock =
+ AcquireRef(new CommandBufferMock(mDeviceMock, commandEncoder.Get(), &commandBufferDesc));
+ EXPECT_CALL(*commandBufferMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(commandBufferMock->IsAlive());
+ commandBufferMock->Destroy();
+ EXPECT_FALSE(commandBufferMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, CommandBufferImplicit) {
+ CommandEncoderDescriptor commandEncoderDesc = {};
+ wgpu::CommandEncoder commandEncoder =
+ device.CreateCommandEncoder(ToCppAPI(&commandEncoderDesc));
+
+ CommandBufferDescriptor commandBufferDesc = {};
+
+ Ref<CommandBufferMock> commandBufferMock = AcquireRef(
+ new CommandBufferMock(mDeviceMock, FromAPI(commandEncoder.Get()), &commandBufferDesc));
+ EXPECT_CALL(*commandBufferMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(commandBufferMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateCommandBuffer)
+ .WillOnce(Return(ByMove(std::move(commandBufferMock))));
+ wgpu::CommandBuffer commandBuffer = commandEncoder.Finish(ToCppAPI(&commandBufferDesc));
+
+ EXPECT_TRUE(FromAPI(commandBuffer.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, ComputePipelineNativeExplicit) {
+ Ref<ShaderModuleMock> csModuleMock =
+ ShaderModuleMock::Create(mDeviceMock, kComputeShader.data());
+ ComputePipelineDescriptor desc = {};
+ desc.compute.module = csModuleMock.Get();
+ desc.compute.entryPoint = "main";
+
+ Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(computePipelineMock->IsAlive());
+ computePipelineMock->Destroy();
+ EXPECT_FALSE(computePipelineMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, ComputePipelineImplicit) {
+ Ref<ShaderModuleMock> csModuleMock =
+ ShaderModuleMock::Create(mDeviceMock, kComputeShader.data());
+ ComputePipelineDescriptor desc = {};
+ desc.compute.module = csModuleMock.Get();
+ desc.compute.entryPoint = "main";
+
+ // Compute pipelines are initialized during their creation via the device.
+ Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*computePipelineMock.Get(), Initialize).Times(1);
+ EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
+
+ {
+ ScopedRawPtrExpectation scoped(computePipelineMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
+ .WillOnce(Return(ByMove(std::move(computePipelineMock))));
+ wgpu::ComputePipeline computePipeline = device.CreateComputePipeline(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(computePipeline.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(computePipeline.Get())->IsCachedReference());
+ }
+}
+
+TEST_F(DestroyObjectTests, ExternalTextureNativeExplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor textureViewDesc = {};
+ textureViewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new NiceMock<TextureViewMock>(textureMock.Get(), &textureViewDesc));
+
+ ExternalTextureDescriptor desc = {};
+ std::array<float, 12> placeholderConstantArray;
+ desc.yuvToRgbConversionMatrix = placeholderConstantArray.data();
+ desc.gamutConversionMatrix = placeholderConstantArray.data();
+ desc.srcTransferFunctionParameters = placeholderConstantArray.data();
+ desc.dstTransferFunctionParameters = placeholderConstantArray.data();
+ desc.visibleSize = {1, 1};
+ desc.plane0 = textureViewMock.Get();
+
+ Ref<ExternalTextureMock> externalTextureMock = ExternalTextureMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*externalTextureMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(externalTextureMock->IsAlive());
+ externalTextureMock->Destroy();
+ EXPECT_FALSE(externalTextureMock->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, ExternalTextureApiExplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor textureViewDesc = {};
+ textureViewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new NiceMock<TextureViewMock>(textureMock.Get(), &textureViewDesc));
+
+ ExternalTextureDescriptor desc = {};
+ std::array<float, 12> placeholderConstantArray;
+ desc.yuvToRgbConversionMatrix = placeholderConstantArray.data();
+ desc.gamutConversionMatrix = placeholderConstantArray.data();
+ desc.srcTransferFunctionParameters = placeholderConstantArray.data();
+ desc.dstTransferFunctionParameters = placeholderConstantArray.data();
+ desc.visibleSize = {1, 1};
+ desc.plane0 = textureViewMock.Get();
+
+ Ref<ExternalTextureMock> externalTextureMock = ExternalTextureMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*externalTextureMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_CALL(*mDeviceMock, CreateExternalTextureImpl)
+ .WillOnce(Return(ByMove(std::move(externalTextureMock))));
+ wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(externalTexture.Get())->IsAlive());
+ externalTexture.Destroy();
+ EXPECT_FALSE(FromAPI(externalTexture.Get())->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, ExternalTextureImplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor textureViewDesc = {};
+ textureViewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new NiceMock<TextureViewMock>(textureMock.Get(), &textureViewDesc));
+
+ ExternalTextureDescriptor desc = {};
+ std::array<float, 12> placeholderConstantArray;
+ desc.yuvToRgbConversionMatrix = placeholderConstantArray.data();
+ desc.gamutConversionMatrix = placeholderConstantArray.data();
+ desc.srcTransferFunctionParameters = placeholderConstantArray.data();
+ desc.dstTransferFunctionParameters = placeholderConstantArray.data();
+ desc.visibleSize = {1, 1};
+ desc.plane0 = textureViewMock.Get();
+
+ Ref<ExternalTextureMock> externalTextureMock = ExternalTextureMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*externalTextureMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(externalTextureMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateExternalTextureImpl)
+ .WillOnce(Return(ByMove(std::move(externalTextureMock))));
+ wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(externalTexture.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, PipelineLayoutNativeExplicit) {
+ PipelineLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutBase*> bindGroupLayouts;
+ bindGroupLayouts.push_back(mDeviceMock->GetEmptyBindGroupLayoutMock());
+ desc.bindGroupLayoutCount = static_cast<uint32_t>(bindGroupLayouts.size());
+ desc.bindGroupLayouts = bindGroupLayouts.data();
+
+ Ref<PipelineLayoutMock> pipelineLayoutMock =
+ AcquireRef(new PipelineLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*pipelineLayoutMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(pipelineLayoutMock->IsAlive());
+ pipelineLayoutMock->Destroy();
+ EXPECT_FALSE(pipelineLayoutMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, PipelineLayoutImplicit) {
+ PipelineLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutBase*> bindGroupLayouts;
+ bindGroupLayouts.push_back(mDeviceMock->GetEmptyBindGroupLayoutMock());
+ desc.bindGroupLayoutCount = static_cast<uint32_t>(bindGroupLayouts.size());
+ desc.bindGroupLayouts = bindGroupLayouts.data();
+
+ Ref<PipelineLayoutMock> pipelineLayoutMock =
+ AcquireRef(new PipelineLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*pipelineLayoutMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(pipelineLayoutMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreatePipelineLayoutImpl)
+ .WillOnce(Return(ByMove(std::move(pipelineLayoutMock))));
+ wgpu::PipelineLayout pipelineLayout = device.CreatePipelineLayout(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(pipelineLayout.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(pipelineLayout.Get())->IsCachedReference());
+ }
+}
+
+TEST_F(DestroyObjectTests, QuerySetNativeExplicit) {
+ QuerySetDescriptor desc = {};
+ desc.type = wgpu::QueryType::Occlusion;
+ desc.count = 1;
+
+ Ref<QuerySetMock> querySetMock = AcquireRef(new QuerySetMock(mDeviceMock, &desc));
+ EXPECT_CALL(*querySetMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(querySetMock->IsAlive());
+ querySetMock->Destroy();
+ EXPECT_FALSE(querySetMock->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, QuerySetApiExplicit) {
+ QuerySetDescriptor desc = {};
+ desc.type = wgpu::QueryType::Occlusion;
+ desc.count = 1;
+
+ Ref<QuerySetMock> querySetMock = AcquireRef(new QuerySetMock(mDeviceMock, &desc));
+ EXPECT_CALL(*querySetMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_CALL(*mDeviceMock, CreateQuerySetImpl).WillOnce(Return(ByMove(std::move(querySetMock))));
+ wgpu::QuerySet querySet = device.CreateQuerySet(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(querySet.Get())->IsAlive());
+ querySet.Destroy();
+ EXPECT_FALSE(FromAPI(querySet.Get())->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, QuerySetImplicit) {
+ QuerySetDescriptor desc = {};
+ desc.type = wgpu::QueryType::Occlusion;
+ desc.count = 1;
+
+ Ref<QuerySetMock> querySetMock = AcquireRef(new QuerySetMock(mDeviceMock, &desc));
+ EXPECT_CALL(*querySetMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(querySetMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateQuerySetImpl)
+ .WillOnce(Return(ByMove(std::move(querySetMock))));
+ wgpu::QuerySet querySet = device.CreateQuerySet(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(querySet.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, RenderPipelineNativeExplicit) {
+ Ref<ShaderModuleMock> vsModuleMock =
+ ShaderModuleMock::Create(mDeviceMock, kVertexShader.data());
+ RenderPipelineDescriptor desc = {};
+ desc.vertex.module = vsModuleMock.Get();
+ desc.vertex.entryPoint = "main";
+
+ Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*renderPipelineMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(renderPipelineMock->IsAlive());
+ renderPipelineMock->Destroy();
+ EXPECT_FALSE(renderPipelineMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, RenderPipelineImplicit) {
+ Ref<ShaderModuleMock> vsModuleMock =
+ ShaderModuleMock::Create(mDeviceMock, kVertexShader.data());
+ RenderPipelineDescriptor desc = {};
+ desc.vertex.module = vsModuleMock.Get();
+ desc.vertex.entryPoint = "main";
+
+ // Render pipelines are initialized during their creation via the device.
+ Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*renderPipelineMock.Get(), Initialize).Times(1);
+ EXPECT_CALL(*renderPipelineMock.Get(), DestroyImpl).Times(1);
+
+ {
+ ScopedRawPtrExpectation scoped(renderPipelineMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
+ .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
+ wgpu::RenderPipeline renderPipeline = device.CreateRenderPipeline(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(renderPipeline.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(renderPipeline.Get())->IsCachedReference());
+ }
+}
+
+TEST_F(DestroyObjectTests, SamplerNativeExplicit) {
+ SamplerDescriptor desc = {};
+
+ Ref<SamplerMock> samplerMock = AcquireRef(new SamplerMock(mDeviceMock, &desc));
+ EXPECT_CALL(*samplerMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(samplerMock->IsAlive());
+ samplerMock->Destroy();
+ EXPECT_FALSE(samplerMock->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, SamplerImplicit) {
+ SamplerDescriptor desc = {};
+
+ Ref<SamplerMock> samplerMock = AcquireRef(new SamplerMock(mDeviceMock, &desc));
+ EXPECT_CALL(*samplerMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(samplerMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateSamplerImpl)
+ .WillOnce(Return(ByMove(std::move(samplerMock))));
+ wgpu::Sampler sampler = device.CreateSampler(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(sampler.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(sampler.Get())->IsCachedReference());
+ }
+}
+
+TEST_F(DestroyObjectTests, ShaderModuleNativeExplicit) {
+ Ref<ShaderModuleMock> shaderModuleMock =
+ ShaderModuleMock::Create(mDeviceMock, kVertexShader.data());
+ EXPECT_CALL(*shaderModuleMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(shaderModuleMock->IsAlive());
+ shaderModuleMock->Destroy();
+ EXPECT_FALSE(shaderModuleMock->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, ShaderModuleImplicit) {
+ ShaderModuleWGSLDescriptor wgslDesc = {};
+ wgslDesc.source = kVertexShader.data();
+ ShaderModuleDescriptor desc = {};
+ desc.nextInChain = &wgslDesc;
+
+ Ref<ShaderModuleMock> shaderModuleMock = ShaderModuleMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*shaderModuleMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(shaderModuleMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateShaderModuleImpl)
+ .WillOnce(Return(ByMove(std::move(shaderModuleMock))));
+ wgpu::ShaderModule shaderModule = device.CreateShaderModule(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(shaderModule.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, TextureNativeExplicit) {
+ TextureDescriptor desc = {};
+ desc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ desc.size.width = 1;
+ desc.size.height = 1;
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ Ref<TextureMock> textureMock = AcquireRef(new TextureMock(mDeviceMock, &desc));
+ EXPECT_CALL(*textureMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(textureMock->IsAlive());
+ textureMock->Destroy();
+ EXPECT_FALSE(textureMock->IsAlive());
+}
+
+TEST_F(DestroyObjectTests, TextureApiExplicit) {
+ TextureDescriptor desc = {};
+ desc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ desc.size.width = 1;
+ desc.size.height = 1;
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ Ref<TextureMock> textureMock = AcquireRef(new TextureMock(mDeviceMock, &desc));
+ EXPECT_CALL(*textureMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_CALL(*mDeviceMock, CreateTextureImpl).WillOnce(Return(ByMove(std::move(textureMock))));
+ wgpu::Texture texture = device.CreateTexture(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(texture.Get())->IsAlive());
+ texture.Destroy();
+ EXPECT_FALSE(FromAPI(texture.Get())->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, TextureImplicit) {
+ TextureDescriptor desc = {};
+ desc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ desc.size.width = 1;
+ desc.size.height = 1;
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ Ref<TextureMock> textureMock = AcquireRef(new TextureMock(mDeviceMock, &desc));
+ EXPECT_CALL(*textureMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(textureMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateTextureImpl)
+ .WillOnce(Return(ByMove(std::move(textureMock))));
+ wgpu::Texture texture = device.CreateTexture(ToCppAPI(&desc));
+
+ EXPECT_TRUE(FromAPI(texture.Get())->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, TextureViewNativeExplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor desc = {};
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+ {
+ // Explicitly destroy the texture view.
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new TextureViewMock(textureMock.Get(), &desc));
+ EXPECT_CALL(*textureViewMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(textureViewMock->IsAlive());
+ textureViewMock->Destroy();
+ EXPECT_FALSE(textureViewMock->IsAlive());
+ }
+ {
+ // Destroying the owning texture should cause the view to be destroyed as well.
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new TextureViewMock(textureMock.Get(), &desc));
+ EXPECT_CALL(*textureViewMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_TRUE(textureViewMock->IsAlive());
+ textureMock->Destroy();
+ EXPECT_FALSE(textureViewMock->IsAlive());
+ }
+}
+
+TEST_F(DestroyObjectTests, TextureViewApiExplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor viewDesc = {};
+ viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new TextureViewMock(textureMock.Get(), &viewDesc));
+ EXPECT_CALL(*textureViewMock.Get(), DestroyImpl).Times(1);
+
+ EXPECT_CALL(*mDeviceMock, CreateTextureViewImpl(textureMock.Get(), _))
+ .WillOnce(Return(ByMove(std::move(textureViewMock))));
+ EXPECT_CALL(*mDeviceMock, CreateTextureImpl).WillOnce(Return(ByMove(std::move(textureMock))));
+ wgpu::Texture texture = device.CreateTexture(ToCppAPI(&textureDesc));
+ wgpu::TextureView textureView = texture.CreateView(ToCppAPI(&viewDesc));
+
+ EXPECT_TRUE(FromAPI(textureView.Get())->IsAlive());
+ texture.Destroy();
+ EXPECT_FALSE(FromAPI(textureView.Get())->IsAlive());
+}
+
+// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+// will also complain if there is a memory leak.
+TEST_F(DestroyObjectTests, TextureViewImplicit) {
+ TextureDescriptor textureDesc = {};
+ textureDesc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ textureDesc.size.width = 1;
+ textureDesc.size.height = 1;
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+ Ref<TextureMock> textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &textureDesc));
+
+ TextureViewDescriptor viewDesc = {};
+ viewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ Ref<TextureViewMock> textureViewMock =
+ AcquireRef(new TextureViewMock(textureMock.Get(), &viewDesc));
+ EXPECT_CALL(*textureViewMock.Get(), DestroyImpl).Times(1);
+ {
+ ScopedRawPtrExpectation scoped(textureViewMock.Get());
+
+ EXPECT_CALL(*mDeviceMock, CreateTextureViewImpl(textureMock.Get(), _))
+ .WillOnce(Return(ByMove(std::move(textureViewMock))));
+ EXPECT_CALL(*mDeviceMock, CreateTextureImpl)
+ .WillOnce(Return(ByMove(std::move(textureMock))));
+ wgpu::Texture texture = device.CreateTexture(ToCppAPI(&textureDesc));
+ wgpu::TextureView textureView = texture.CreateView(ToCppAPI(&viewDesc));
+
+ EXPECT_TRUE(FromAPI(textureView.Get())->IsAlive());
+ }
+}
+
+// Destroying the objects on the device explicitly should result in all created objects being
+// destroyed in order.
+TEST_F(DestroyObjectTests, DestroyObjectsApiExplicit) {
+ Ref<BindGroupMock> bindGroupMock;
+ wgpu::BindGroup bindGroup;
+ {
+ BindGroupDescriptor desc = {};
+ desc.layout = mDeviceMock->GetEmptyBindGroupLayoutMock();
+ desc.entryCount = 0;
+ desc.entries = nullptr;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ bindGroupMock = AcquireRef(new BindGroupMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateBindGroupImpl).WillOnce(Return(bindGroupMock));
+ bindGroup = device.CreateBindGroup(ToCppAPI(&desc));
+ }
+
+ Ref<BindGroupLayoutMock> bindGroupLayoutMock;
+ wgpu::BindGroupLayout bindGroupLayout;
+ {
+ // Use an non-empty bind group layout to avoid hitting the internal empty layout in the
+ // cache.
+ BindGroupLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutEntry> entries;
+ entries.push_back(utils::BindingLayoutEntryInitializationHelper(
+ 0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform));
+ desc.entryCount = static_cast<uint32_t>(entries.size());
+ desc.entries = entries.data();
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ bindGroupLayoutMock = AcquireRef(new BindGroupLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateBindGroupLayoutImpl).WillOnce(Return(bindGroupLayoutMock));
+ bindGroupLayout = device.CreateBindGroupLayout(ToCppAPI(&desc));
+ }
+
+ Ref<ShaderModuleMock> csModuleMock;
+ wgpu::ShaderModule csModule;
+ {
+ ShaderModuleWGSLDescriptor wgslDesc = {};
+ wgslDesc.source = kComputeShader.data();
+ ShaderModuleDescriptor desc = {};
+ desc.nextInChain = &wgslDesc;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ csModuleMock = ShaderModuleMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*mDeviceMock, CreateShaderModuleImpl).WillOnce(Return(csModuleMock));
+ csModule = device.CreateShaderModule(ToCppAPI(&desc));
+ }
+
+ Ref<ShaderModuleMock> vsModuleMock;
+ wgpu::ShaderModule vsModule;
+ {
+ ShaderModuleWGSLDescriptor wgslDesc = {};
+ wgslDesc.source = kVertexShader.data();
+ ShaderModuleDescriptor desc = {};
+ desc.nextInChain = &wgslDesc;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ vsModuleMock = ShaderModuleMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*mDeviceMock, CreateShaderModuleImpl).WillOnce(Return(vsModuleMock));
+ vsModule = device.CreateShaderModule(ToCppAPI(&desc));
+ }
+
+ Ref<BufferMock> bufferMock;
+ wgpu::Buffer buffer;
+ {
+ BufferDescriptor desc = {};
+ desc.size = 16;
+ desc.usage = wgpu::BufferUsage::Uniform;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ bufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(bufferMock));
+ buffer = device.CreateBuffer(ToCppAPI(&desc));
+ }
+
+ Ref<CommandBufferMock> commandBufferMock;
+ wgpu::CommandBuffer commandBuffer;
+ {
+ CommandEncoderDescriptor commandEncoderDesc = {};
+ wgpu::CommandEncoder commandEncoder =
+ device.CreateCommandEncoder(ToCppAPI(&commandEncoderDesc));
+
+ CommandBufferDescriptor commandBufferDesc = {};
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ commandBufferMock = AcquireRef(
+ new CommandBufferMock(mDeviceMock, FromAPI(commandEncoder.Get()), &commandBufferDesc));
+ EXPECT_CALL(*mDeviceMock, CreateCommandBuffer).WillOnce(Return(commandBufferMock));
+ commandBuffer = commandEncoder.Finish(ToCppAPI(&commandBufferDesc));
+ }
+
+ Ref<ComputePipelineMock> computePipelineMock;
+ wgpu::ComputePipeline computePipeline;
+ {
+ ComputePipelineDescriptor desc = {};
+ desc.compute.module = csModuleMock.Get();
+ desc.compute.entryPoint = "main";
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*computePipelineMock.Get(), Initialize).Times(1);
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
+ .WillOnce(Return(computePipelineMock));
+ computePipeline = device.CreateComputePipeline(ToCppAPI(&desc));
+ }
+
+ Ref<PipelineLayoutMock> pipelineLayoutMock;
+ wgpu::PipelineLayout pipelineLayout;
+ {
+ PipelineLayoutDescriptor desc = {};
+ std::vector<BindGroupLayoutBase*> bindGroupLayouts;
+ bindGroupLayouts.push_back(mDeviceMock->GetEmptyBindGroupLayoutMock());
+ desc.bindGroupLayoutCount = static_cast<uint32_t>(bindGroupLayouts.size());
+ desc.bindGroupLayouts = bindGroupLayouts.data();
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ pipelineLayoutMock = AcquireRef(new PipelineLayoutMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreatePipelineLayoutImpl).WillOnce(Return(pipelineLayoutMock));
+ pipelineLayout = device.CreatePipelineLayout(ToCppAPI(&desc));
+ }
+
+ Ref<QuerySetMock> querySetMock;
+ wgpu::QuerySet querySet;
+ {
+ QuerySetDescriptor desc = {};
+ desc.type = wgpu::QueryType::Occlusion;
+ desc.count = 1;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ querySetMock = AcquireRef(new QuerySetMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateQuerySetImpl).WillOnce(Return(querySetMock));
+ querySet = device.CreateQuerySet(ToCppAPI(&desc));
+ }
+
+ Ref<RenderPipelineMock> renderPipelineMock;
+ wgpu::RenderPipeline renderPipeline;
+ {
+ RenderPipelineDescriptor desc = {};
+ desc.vertex.module = vsModuleMock.Get();
+ desc.vertex.entryPoint = "main";
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*renderPipelineMock.Get(), Initialize).Times(1);
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
+ .WillOnce(Return(renderPipelineMock));
+ renderPipeline = device.CreateRenderPipeline(ToCppAPI(&desc));
+ }
+
+ Ref<SamplerMock> samplerMock;
+ wgpu::Sampler sampler;
+ {
+ SamplerDescriptor desc = {};
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ samplerMock = AcquireRef(new SamplerMock(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateSamplerImpl).WillOnce(Return(samplerMock));
+ sampler = device.CreateSampler(ToCppAPI(&desc));
+ }
+
+ Ref<TextureMock> textureMock;
+ wgpu::Texture texture;
+ {
+ TextureDescriptor desc = {};
+ desc.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ desc.size.width = 1;
+ desc.size.height = 1;
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ textureMock = AcquireRef(new NiceMock<TextureMock>(mDeviceMock, &desc));
+ EXPECT_CALL(*mDeviceMock, CreateTextureImpl).WillOnce(Return(textureMock));
+ texture = device.CreateTexture(ToCppAPI(&desc));
+ }
+
+ Ref<TextureViewMock> textureViewMock;
+ wgpu::TextureView textureView;
+ {
+ TextureViewDescriptor desc = {};
+ desc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ textureViewMock = AcquireRef(new TextureViewMock(textureMock.Get(), &desc));
+ EXPECT_CALL(*mDeviceMock, CreateTextureViewImpl).WillOnce(Return(textureViewMock));
+ textureView = texture.CreateView(ToCppAPI(&desc));
+ }
+
+ Ref<ExternalTextureMock> externalTextureMock;
+ wgpu::ExternalTexture externalTexture;
+ {
+ ExternalTextureDescriptor desc = {};
+ std::array<float, 12> placeholderConstantArray;
+ desc.yuvToRgbConversionMatrix = placeholderConstantArray.data();
+ desc.gamutConversionMatrix = placeholderConstantArray.data();
+ desc.srcTransferFunctionParameters = placeholderConstantArray.data();
+ desc.dstTransferFunctionParameters = placeholderConstantArray.data();
+ desc.visibleSize = {1, 1};
+ desc.plane0 = textureViewMock.Get();
+
+ ScopedRawPtrExpectation scoped(mDeviceMock);
+ externalTextureMock = ExternalTextureMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*mDeviceMock, CreateExternalTextureImpl).WillOnce(Return(externalTextureMock));
+ externalTexture = device.CreateExternalTexture(ToCppAPI(&desc));
+ }
+
+ {
+ InSequence seq;
+ EXPECT_CALL(*commandBufferMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*renderPipelineMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*computePipelineMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*pipelineLayoutMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*bindGroupMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*bindGroupLayoutMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*vsModuleMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*csModuleMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*externalTextureMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*textureMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*textureViewMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*querySetMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*samplerMock.Get(), DestroyImpl).Times(1);
+ EXPECT_CALL(*bufferMock.Get(), DestroyImpl).Times(1);
+ }
+
+ EXPECT_TRUE(FromAPI(bindGroup.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(bindGroupLayout.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(buffer.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(commandBuffer.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(computePipeline.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(externalTexture.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(pipelineLayout.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(querySet.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(renderPipeline.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(sampler.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(vsModule.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(csModule.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(texture.Get())->IsAlive());
+ EXPECT_TRUE(FromAPI(textureView.Get())->IsAlive());
+ device.Destroy();
+ EXPECT_FALSE(FromAPI(bindGroup.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(bindGroupLayout.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(buffer.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(commandBuffer.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(computePipeline.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(externalTexture.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(pipelineLayout.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(querySet.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(renderPipeline.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(sampler.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(vsModule.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(csModule.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(texture.Get())->IsAlive());
+ EXPECT_FALSE(FromAPI(textureView.Get())->IsAlive());
+}
+
class DestroyObjectRegressionTests : public DawnNativeTest {};
// LastRefInCommand* tests are regression test(s) for https://crbug.com/chromium/1318792. The
@@ -780,17 +1044,17 @@
// CommandEncoder, that destroying the device still works as expected (and does not cause
// double-free).
TEST_F(DestroyObjectRegressionTests, LastRefInCommandRenderPipeline) {
- utils::BasicRenderPass pass = utils::CreateBasicRenderPass(device, 1, 1);
+ ::utils::BasicRenderPass pass = ::utils::CreateBasicRenderPass(device, 1, 1);
- utils::ComboRenderPassDescriptor passDesc{};
+ ::utils::ComboRenderPassDescriptor passDesc{};
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder renderEncoder = encoder.BeginRenderPass(&pass.renderPassInfo);
- utils::ComboRenderPipelineDescriptor pipelineDesc;
+ ::utils::ComboRenderPipelineDescriptor pipelineDesc;
pipelineDesc.cTargets[0].writeMask = wgpu::ColorWriteMask::None;
- pipelineDesc.vertex.module = utils::CreateShaderModule(device, kVertexShader.data());
+ pipelineDesc.vertex.module = ::utils::CreateShaderModule(device, kVertexShader.data());
pipelineDesc.vertex.entryPoint = "main";
- pipelineDesc.cFragment.module = utils::CreateShaderModule(device, kFragmentShader.data());
+ pipelineDesc.cFragment.module = ::utils::CreateShaderModule(device, kFragmentShader.data());
pipelineDesc.cFragment.entryPoint = "main";
renderEncoder.SetPipeline(device.CreateRenderPipeline(&pipelineDesc));
@@ -805,7 +1069,7 @@
wgpu::ComputePassEncoder computeEncoder = encoder.BeginComputePass();
wgpu::ComputePipelineDescriptor pipelineDesc;
- pipelineDesc.compute.module = utils::CreateShaderModule(device, kComputeShader.data());
+ pipelineDesc.compute.module = ::utils::CreateShaderModule(device, kComputeShader.data());
pipelineDesc.compute.entryPoint = "main";
computeEncoder.SetPipeline(device.CreateComputePipeline(&pipelineDesc));
diff --git a/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.cpp b/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.cpp
index c2775d7..6a57746 100644
--- a/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.cpp
@@ -16,10 +16,15 @@
namespace dawn::native {
-BindGroupLayoutMock::BindGroupLayoutMock(DeviceBase* device) : BindGroupLayoutBase(device) {
+BindGroupLayoutMock::BindGroupLayoutMock(DeviceMock* device,
+ const BindGroupLayoutDescriptor* descriptor,
+ PipelineCompatibilityToken pipelineCompatibilityToken)
+ : BindGroupLayoutBase(device, descriptor, pipelineCompatibilityToken) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() {
this->BindGroupLayoutBase::DestroyImpl();
});
+
+ SetContentHash(ComputeContentHash());
}
BindGroupLayoutMock::~BindGroupLayoutMock() = default;
diff --git a/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.h b/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.h
index eb0183c..cc38952 100644
--- a/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.h
+++ b/src/dawn/tests/unittests/native/mocks/BindGroupLayoutMock.h
@@ -18,13 +18,16 @@
#include "gmock/gmock.h"
#include "dawn/native/BindGroupLayout.h"
-#include "dawn/native/Device.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
-class BindGroupLayoutMock final : public BindGroupLayoutBase {
+class BindGroupLayoutMock : public BindGroupLayoutBase {
public:
- explicit BindGroupLayoutMock(DeviceBase* device);
+ BindGroupLayoutMock(
+ DeviceMock* device,
+ const BindGroupLayoutDescriptor* descriptor,
+ PipelineCompatibilityToken pipelineCompatibilityToken = PipelineCompatibilityToken(0));
~BindGroupLayoutMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/BindGroupMock.cpp b/src/dawn/tests/unittests/native/mocks/BindGroupMock.cpp
index ca6f851..81e6459 100644
--- a/src/dawn/tests/unittests/native/mocks/BindGroupMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/BindGroupMock.cpp
@@ -16,7 +16,9 @@
namespace dawn::native {
-BindGroupMock::BindGroupMock(DeviceBase* device) : BindGroupBase(device) {
+BindGroupMock::BindGroupMock(DeviceMock* device, const BindGroupDescriptor* descriptor)
+ : BindGroupDataHolder(descriptor->layout->GetBindingDataSize()),
+ BindGroupBase(device, descriptor, mBindingDataAllocation) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->BindGroupBase::DestroyImpl(); });
}
diff --git a/src/dawn/tests/unittests/native/mocks/BindGroupMock.h b/src/dawn/tests/unittests/native/mocks/BindGroupMock.h
index 0dd5e02..9c9efda 100644
--- a/src/dawn/tests/unittests/native/mocks/BindGroupMock.h
+++ b/src/dawn/tests/unittests/native/mocks/BindGroupMock.h
@@ -18,13 +18,14 @@
#include "gmock/gmock.h"
#include "dawn/native/BindGroup.h"
-#include "dawn/native/Device.h"
+#include "dawn/native/null/DeviceNull.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
-class BindGroupMock : public BindGroupBase {
+class BindGroupMock : private null::BindGroupDataHolder, public BindGroupBase {
public:
- explicit BindGroupMock(DeviceBase* device);
+ BindGroupMock(DeviceMock* device, const BindGroupDescriptor* descriptor);
~BindGroupMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/BufferMock.cpp b/src/dawn/tests/unittests/native/mocks/BufferMock.cpp
index 98b345f..788a61b 100644
--- a/src/dawn/tests/unittests/native/mocks/BufferMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/BufferMock.cpp
@@ -16,8 +16,8 @@
namespace dawn::native {
-BufferMock::BufferMock(DeviceBase* device, BufferBase::BufferState state)
- : BufferBase(device, state) {
+BufferMock::BufferMock(DeviceMock* device, const BufferDescriptor* descriptor)
+ : BufferBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->BufferBase::DestroyImpl(); });
}
diff --git a/src/dawn/tests/unittests/native/mocks/BufferMock.h b/src/dawn/tests/unittests/native/mocks/BufferMock.h
index d98f31d..7ddfc1f 100644
--- a/src/dawn/tests/unittests/native/mocks/BufferMock.h
+++ b/src/dawn/tests/unittests/native/mocks/BufferMock.h
@@ -18,13 +18,13 @@
#include "gmock/gmock.h"
#include "dawn/native/Buffer.h"
-#include "dawn/native/Device.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class BufferMock : public BufferBase {
public:
- BufferMock(DeviceBase* device, BufferBase::BufferState state);
+ BufferMock(DeviceMock* device, const BufferDescriptor* descriptor);
~BufferMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/CommandBufferMock.cpp b/src/dawn/tests/unittests/native/mocks/CommandBufferMock.cpp
index 80c0cf3..579cdda 100644
--- a/src/dawn/tests/unittests/native/mocks/CommandBufferMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/CommandBufferMock.cpp
@@ -14,9 +14,18 @@
#include "dawn/tests/unittests/native/mocks/CommandBufferMock.h"
+#include "dawn/native/CommandEncoder.h"
+
namespace dawn::native {
-CommandBufferMock::CommandBufferMock(DeviceBase* device) : CommandBufferBase(device) {
+CommandBufferMock::CommandBufferMock(DeviceMock* device,
+ CommandEncoder* encoder,
+ const CommandBufferDescriptor* descriptor)
+ : CommandBufferBase(encoder, descriptor) {
+ // Make sure that the command encoder was also created using the mock device since it is not
+ // directly passed in.
+ ASSERT(device == encoder->GetDevice());
+
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->CommandBufferBase::DestroyImpl(); });
}
diff --git a/src/dawn/tests/unittests/native/mocks/CommandBufferMock.h b/src/dawn/tests/unittests/native/mocks/CommandBufferMock.h
index f15a46b..04669d5 100644
--- a/src/dawn/tests/unittests/native/mocks/CommandBufferMock.h
+++ b/src/dawn/tests/unittests/native/mocks/CommandBufferMock.h
@@ -18,13 +18,15 @@
#include "gmock/gmock.h"
#include "dawn/native/CommandBuffer.h"
-#include "dawn/native/Device.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class CommandBufferMock : public CommandBufferBase {
public:
- explicit CommandBufferMock(DeviceBase* device);
+ CommandBufferMock(DeviceMock* device,
+ CommandEncoder* encoder,
+ const CommandBufferDescriptor* descriptor);
~CommandBufferMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.cpp b/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.cpp
index 2828456..97280ef 100644
--- a/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.cpp
@@ -16,7 +16,12 @@
namespace dawn::native {
-ComputePipelineMock::ComputePipelineMock(DeviceBase* device) : ComputePipelineBase(device) {
+using ::testing::NiceMock;
+
+ComputePipelineMock::ComputePipelineMock(DeviceBase* device,
+ const ComputePipelineDescriptor* descriptor)
+ : ComputePipelineBase(device, descriptor) {
+ ON_CALL(*this, Initialize).WillByDefault([]() -> MaybeError { return {}; });
ON_CALL(*this, DestroyImpl).WillByDefault([this]() {
this->ComputePipelineBase::DestroyImpl();
});
@@ -24,4 +29,14 @@
ComputePipelineMock::~ComputePipelineMock() = default;
+// static
+Ref<ComputePipelineMock> ComputePipelineMock::Create(DeviceMock* device,
+ const ComputePipelineDescriptor* descriptor) {
+ ComputePipelineDescriptor appliedDescriptor;
+ Ref<PipelineLayoutBase> layoutRef = ValidateLayoutAndGetComputePipelineDescriptorWithDefaults(
+ device, *descriptor, &appliedDescriptor)
+ .AcquireSuccess();
+ return AcquireRef(new NiceMock<ComputePipelineMock>(device, &appliedDescriptor));
+}
+
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.h b/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.h
index 404359a..d624a55 100644
--- a/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.h
+++ b/src/dawn/tests/unittests/native/mocks/ComputePipelineMock.h
@@ -18,18 +18,23 @@
#include "gmock/gmock.h"
#include "dawn/native/ComputePipeline.h"
-#include "dawn/native/Device.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class ComputePipelineMock : public ComputePipelineBase {
public:
- explicit ComputePipelineMock(DeviceBase* device);
+ // Creates a compute pipeline given the descriptor.
+ static Ref<ComputePipelineMock> Create(DeviceMock* device,
+ const ComputePipelineDescriptor* descriptor);
+
~ComputePipelineMock() override;
MOCK_METHOD(MaybeError, Initialize, (), (override));
- MOCK_METHOD(size_t, ComputeContentHash, (), (override));
MOCK_METHOD(void, DestroyImpl, (), (override));
+
+ protected:
+ ComputePipelineMock(DeviceBase* device, const ComputePipelineDescriptor* descriptor);
};
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
new file mode 100644
index 0000000..3acd5b5
--- /dev/null
+++ b/src/dawn/tests/unittests/native/mocks/DawnMockTest.cpp
@@ -0,0 +1,33 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/tests/unittests/native/mocks/DawnMockTest.h"
+
+#include "dawn/dawn_proc.h"
+
+namespace dawn::native {
+
+DawnMockTest::DawnMockTest() {
+ dawnProcSetProcs(&dawn::native::GetProcs());
+
+ mDeviceMock = new ::testing::NiceMock<DeviceMock>();
+ device = wgpu::Device::Acquire(ToAPI(mDeviceMock));
+}
+
+DawnMockTest::~DawnMockTest() {
+ device = wgpu::Device();
+ dawnProcSetProcs(nullptr);
+}
+
+} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DawnMockTest.h b/src/dawn/tests/unittests/native/mocks/DawnMockTest.h
new file mode 100644
index 0000000..e84662d
--- /dev/null
+++ b/src/dawn/tests/unittests/native/mocks/DawnMockTest.h
@@ -0,0 +1,32 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
+#include "dawn/webgpu_cpp.h"
+
+namespace dawn::native {
+
+class DawnMockTest : public ::testing::Test {
+ public:
+ DawnMockTest();
+ ~DawnMockTest() override;
+
+ protected:
+ ::testing::NiceMock<DeviceMock>* mDeviceMock;
+ wgpu::Device device;
+};
+
+} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp b/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
new file mode 100644
index 0000000..e701c8b
--- /dev/null
+++ b/src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
@@ -0,0 +1,125 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
+
+#include "dawn/tests/unittests/native/mocks/BindGroupLayoutMock.h"
+#include "dawn/tests/unittests/native/mocks/BindGroupMock.h"
+#include "dawn/tests/unittests/native/mocks/BufferMock.h"
+#include "dawn/tests/unittests/native/mocks/ComputePipelineMock.h"
+#include "dawn/tests/unittests/native/mocks/ExternalTextureMock.h"
+#include "dawn/tests/unittests/native/mocks/PipelineLayoutMock.h"
+#include "dawn/tests/unittests/native/mocks/QuerySetMock.h"
+#include "dawn/tests/unittests/native/mocks/QueueMock.h"
+#include "dawn/tests/unittests/native/mocks/RenderPipelineMock.h"
+#include "dawn/tests/unittests/native/mocks/SamplerMock.h"
+#include "dawn/tests/unittests/native/mocks/ShaderModuleMock.h"
+#include "dawn/tests/unittests/native/mocks/TextureMock.h"
+
+namespace dawn::native {
+
+using ::testing::NiceMock;
+using ::testing::WithArgs;
+
+DeviceMock::DeviceMock() {
+ mInstance = InstanceBase::Create();
+
+ // Set all default creation functions to return nice mock objects.
+ ON_CALL(*this, CreateBindGroupImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const BindGroupDescriptor* descriptor) -> ResultOrError<Ref<BindGroupBase>> {
+ return AcquireRef(new NiceMock<BindGroupMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateBindGroupLayoutImpl)
+ .WillByDefault(WithArgs<0, 1>([this](const BindGroupLayoutDescriptor* descriptor,
+ PipelineCompatibilityToken pipelineCompatibilityToken)
+ -> ResultOrError<Ref<BindGroupLayoutBase>> {
+ return AcquireRef(
+ new NiceMock<BindGroupLayoutMock>(this, descriptor, pipelineCompatibilityToken));
+ }));
+ ON_CALL(*this, CreateBufferImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const BufferDescriptor* descriptor) -> ResultOrError<Ref<BufferBase>> {
+ return AcquireRef(new NiceMock<BufferMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateExternalTextureImpl)
+ .WillByDefault(WithArgs<0>([this](const ExternalTextureDescriptor* descriptor)
+ -> ResultOrError<Ref<ExternalTextureBase>> {
+ return ExternalTextureMock::Create(this, descriptor);
+ }));
+ ON_CALL(*this, CreatePipelineLayoutImpl)
+ .WillByDefault(WithArgs<0>([this](const PipelineLayoutDescriptor* descriptor)
+ -> ResultOrError<Ref<PipelineLayoutBase>> {
+ return AcquireRef(new NiceMock<PipelineLayoutMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateQuerySetImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const QuerySetDescriptor* descriptor) -> ResultOrError<Ref<QuerySetBase>> {
+ return AcquireRef(new NiceMock<QuerySetMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateSamplerImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const SamplerDescriptor* descriptor) -> ResultOrError<Ref<SamplerBase>> {
+ return AcquireRef(new NiceMock<SamplerMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateShaderModuleImpl)
+ .WillByDefault(WithArgs<0>([this](const ShaderModuleDescriptor* descriptor)
+ -> ResultOrError<Ref<ShaderModuleBase>> {
+ return ShaderModuleMock::Create(this, descriptor);
+ }));
+ ON_CALL(*this, CreateTextureImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const TextureDescriptor* descriptor) -> ResultOrError<Ref<TextureBase>> {
+ return AcquireRef(new NiceMock<TextureMock>(this, descriptor));
+ }));
+ ON_CALL(*this, CreateTextureViewImpl)
+ .WillByDefault(WithArgs<0, 1>(
+ [](TextureBase* texture,
+ const TextureViewDescriptor* descriptor) -> ResultOrError<Ref<TextureViewBase>> {
+ return AcquireRef(new NiceMock<TextureViewMock>(texture, descriptor));
+ }));
+ ON_CALL(*this, CreateUninitializedComputePipelineImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const ComputePipelineDescriptor* descriptor) -> Ref<ComputePipelineBase> {
+ return ComputePipelineMock::Create(this, descriptor);
+ }));
+ ON_CALL(*this, CreateUninitializedRenderPipelineImpl)
+ .WillByDefault(WithArgs<0>(
+ [this](const RenderPipelineDescriptor* descriptor) -> Ref<RenderPipelineBase> {
+ return RenderPipelineMock::Create(this, descriptor);
+ }));
+
+ // By default, the mock's TickImpl will succeed.
+ ON_CALL(*this, TickImpl).WillByDefault([]() -> MaybeError { return {}; });
+
+ // Initialize the device.
+ QueueDescriptor desc = {};
+ EXPECT_FALSE(Initialize(AcquireRef(new NiceMock<QueueMock>(this, &desc))).IsError());
+}
+
+DeviceMock::~DeviceMock() = default;
+
+dawn::platform::Platform* DeviceMock::GetPlatform() const {
+ return mInstance->GetPlatform();
+}
+
+QueueMock* DeviceMock::GetQueueMock() {
+ return reinterpret_cast<QueueMock*>(GetQueue());
+}
+
+BindGroupLayoutMock* DeviceMock::GetEmptyBindGroupLayoutMock() {
+ return reinterpret_cast<BindGroupLayoutMock*>(GetEmptyBindGroupLayout());
+}
+
+} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/DeviceMock.h b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
index d4aa224..681a936 100644
--- a/src/dawn/tests/unittests/native/mocks/DeviceMock.h
+++ b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
@@ -18,17 +18,34 @@
#include <memory>
#include "dawn/native/Device.h"
+#include "dawn/native/Instance.h"
#include "dawn/native/RenderPipeline.h"
+#include "dawn/platform/DawnPlatform.h"
+#include "dawn/tests/unittests/native/mocks/QueueMock.h"
#include "gmock/gmock.h"
namespace dawn::native {
+class BindGroupLayoutMock;
+
class DeviceMock : public DeviceBase {
public:
// Exposes some protected functions for testing purposes.
using DeviceBase::DestroyObjects;
using DeviceBase::ForceSetToggleForTesting;
+ // TODO(lokokung): Use real DeviceBase constructor instead of mock specific one.
+ // - Requires AdapterMock.
+ // - Can probably remove GetPlatform overload.
+ // - Allows removing ForceSetToggleForTesting calls.
+ DeviceMock();
+ ~DeviceMock() override;
+ dawn::platform::Platform* GetPlatform() const override;
+
+ // Mock specific functionality.
+ QueueMock* GetQueueMock();
+ BindGroupLayoutMock* GetEmptyBindGroupLayoutMock();
+
MOCK_METHOD(ResultOrError<Ref<CommandBufferBase>>,
CreateCommandBuffer,
(CommandEncoder*, const CommandBufferDescriptor*),
@@ -114,6 +131,9 @@
MOCK_METHOD(void, DestroyImpl, (), (override));
MOCK_METHOD(MaybeError, WaitForIdleForDestruction, (), (override));
MOCK_METHOD(bool, HasPendingCommands, (), (const, override));
+
+ private:
+ Ref<InstanceBase> mInstance;
};
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.cpp b/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.cpp
index d0e0f23..0b96a84 100644
--- a/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.cpp
@@ -16,7 +16,11 @@
namespace dawn::native {
-ExternalTextureMock::ExternalTextureMock(DeviceBase* device) : ExternalTextureBase(device) {
+using ::testing::NiceMock;
+
+ExternalTextureMock::ExternalTextureMock(DeviceMock* device,
+ const ExternalTextureDescriptor* descriptor)
+ : ExternalTextureBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() {
this->ExternalTextureBase::DestroyImpl();
});
@@ -24,4 +28,14 @@
ExternalTextureMock::~ExternalTextureMock() = default;
+// static
+Ref<ExternalTextureMock> ExternalTextureMock::Create(DeviceMock* device,
+ const ExternalTextureDescriptor* descriptor) {
+ Ref<ExternalTextureMock> externalTexture =
+ AcquireRef(new NiceMock<ExternalTextureMock>(device, descriptor));
+
+ externalTexture->Initialize(device, descriptor).AcquireSuccess();
+ return externalTexture;
+}
+
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.h b/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.h
index 55096da..b8a4f5c 100644
--- a/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.h
+++ b/src/dawn/tests/unittests/native/mocks/ExternalTextureMock.h
@@ -17,17 +17,23 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/ExternalTexture.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class ExternalTextureMock : public ExternalTextureBase {
public:
- explicit ExternalTextureMock(DeviceBase* device);
+ // Creates an external texture mock based on a descriptor.
+ static Ref<ExternalTextureMock> Create(DeviceMock* device,
+ const ExternalTextureDescriptor* descriptor);
+
~ExternalTextureMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
+
+ protected:
+ ExternalTextureMock(DeviceMock* device, const ExternalTextureDescriptor* descriptor);
};
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.cpp b/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.cpp
index 191a03f..091450f 100644
--- a/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.cpp
@@ -16,10 +16,14 @@
namespace dawn::native {
-PipelineLayoutMock::PipelineLayoutMock(DeviceBase* device) : PipelineLayoutBase(device) {
+PipelineLayoutMock::PipelineLayoutMock(DeviceMock* device,
+ const PipelineLayoutDescriptor* descriptor)
+ : PipelineLayoutBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() {
this->PipelineLayoutBase::DestroyImpl();
});
+
+ SetContentHash(ComputeContentHash());
}
PipelineLayoutMock::~PipelineLayoutMock() = default;
diff --git a/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.h b/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.h
index f00bcf4..30cda7c 100644
--- a/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.h
+++ b/src/dawn/tests/unittests/native/mocks/PipelineLayoutMock.h
@@ -17,14 +17,14 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/PipelineLayout.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class PipelineLayoutMock : public PipelineLayoutBase {
public:
- explicit PipelineLayoutMock(DeviceBase* device);
+ PipelineLayoutMock(DeviceMock* device, const PipelineLayoutDescriptor* descriptor);
~PipelineLayoutMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/QuerySetMock.cpp b/src/dawn/tests/unittests/native/mocks/QuerySetMock.cpp
index 5657f86..6ba771e 100644
--- a/src/dawn/tests/unittests/native/mocks/QuerySetMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/QuerySetMock.cpp
@@ -16,7 +16,8 @@
namespace dawn::native {
-QuerySetMock::QuerySetMock(DeviceBase* device) : QuerySetBase(device) {
+QuerySetMock::QuerySetMock(DeviceMock* device, const QuerySetDescriptor* descriptor)
+ : QuerySetBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->QuerySetBase::DestroyImpl(); });
}
diff --git a/src/dawn/tests/unittests/native/mocks/QuerySetMock.h b/src/dawn/tests/unittests/native/mocks/QuerySetMock.h
index 62ba31b..3af393f 100644
--- a/src/dawn/tests/unittests/native/mocks/QuerySetMock.h
+++ b/src/dawn/tests/unittests/native/mocks/QuerySetMock.h
@@ -17,14 +17,14 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/QuerySet.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class QuerySetMock : public QuerySetBase {
public:
- explicit QuerySetMock(DeviceBase* device);
+ QuerySetMock(DeviceMock* device, const QuerySetDescriptor* descriptor);
~QuerySetMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/QueueMock.cpp b/src/dawn/tests/unittests/native/mocks/QueueMock.cpp
new file mode 100644
index 0000000..f95d055
--- /dev/null
+++ b/src/dawn/tests/unittests/native/mocks/QueueMock.cpp
@@ -0,0 +1,28 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/tests/unittests/native/mocks/QueueMock.h"
+
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
+
+namespace dawn::native {
+
+QueueMock::QueueMock(DeviceMock* device, const QueueDescriptor* descriptor)
+ : QueueBase(device, descriptor) {
+ ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->QueueBase::DestroyImpl(); });
+}
+
+QueueMock::~QueueMock() = default;
+
+} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/QueueMock.h b/src/dawn/tests/unittests/native/mocks/QueueMock.h
new file mode 100644
index 0000000..02b0c17
--- /dev/null
+++ b/src/dawn/tests/unittests/native/mocks/QueueMock.h
@@ -0,0 +1,45 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_TESTS_UNITTESTS_NATIVE_MOCKS_QUEUEMOCK_H_
+#define SRC_DAWN_TESTS_UNITTESTS_NATIVE_MOCKS_QUEUEMOCK_H_
+
+#include "gmock/gmock.h"
+
+#include "dawn/native/Queue.h"
+
+namespace dawn::native {
+
+class DeviceMock;
+
+class QueueMock : public QueueBase {
+ public:
+ QueueMock(DeviceMock* device, const QueueDescriptor* descriptor);
+ ~QueueMock() override;
+
+ MOCK_METHOD(MaybeError, SubmitImpl, (uint32_t, CommandBufferBase* const*), (override));
+ MOCK_METHOD(MaybeError,
+ WriteBufferImpl,
+ (BufferBase*, uint64_t, const void*, size_t),
+ (override));
+ MOCK_METHOD(MaybeError,
+ WriteTextureImpl,
+ (const ImageCopyTexture&, const void*, const TextureDataLayout&, const Extent3D&),
+ (override));
+ MOCK_METHOD(void, DestroyImpl, (), (override));
+};
+
+} // namespace dawn::native
+
+#endif // SRC_DAWN_TESTS_UNITTESTS_NATIVE_MOCKS_QUEUEMOCK_H_
diff --git a/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.cpp b/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.cpp
index cf8a861..e2c500e 100644
--- a/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.cpp
@@ -16,7 +16,12 @@
namespace dawn::native {
-RenderPipelineMock::RenderPipelineMock(DeviceBase* device) : RenderPipelineBase(device) {
+using ::testing::NiceMock;
+
+RenderPipelineMock::RenderPipelineMock(DeviceMock* device,
+ const RenderPipelineDescriptor* descriptor)
+ : RenderPipelineBase(device, descriptor) {
+ ON_CALL(*this, Initialize).WillByDefault([]() -> MaybeError { return {}; });
ON_CALL(*this, DestroyImpl).WillByDefault([this]() {
this->RenderPipelineBase::DestroyImpl();
});
@@ -24,4 +29,14 @@
RenderPipelineMock::~RenderPipelineMock() = default;
+// static
+Ref<RenderPipelineMock> RenderPipelineMock::Create(DeviceMock* device,
+ const RenderPipelineDescriptor* descriptor) {
+ RenderPipelineDescriptor appliedDescriptor;
+ Ref<PipelineLayoutBase> layoutRef = ValidateLayoutAndGetRenderPipelineDescriptorWithDefaults(
+ device, *descriptor, &appliedDescriptor)
+ .AcquireSuccess();
+ return AcquireRef(new NiceMock<RenderPipelineMock>(device, &appliedDescriptor));
+}
+
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.h b/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.h
index 1558b4b..14fe2c8 100644
--- a/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.h
+++ b/src/dawn/tests/unittests/native/mocks/RenderPipelineMock.h
@@ -17,19 +17,24 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/RenderPipeline.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class RenderPipelineMock : public RenderPipelineBase {
public:
- explicit RenderPipelineMock(DeviceBase* device);
+ // Creates a compute pipeline given the descriptor.
+ static Ref<RenderPipelineMock> Create(DeviceMock* device,
+ const RenderPipelineDescriptor* descriptor);
+
~RenderPipelineMock() override;
MOCK_METHOD(MaybeError, Initialize, (), (override));
- MOCK_METHOD(size_t, ComputeContentHash, (), (override));
MOCK_METHOD(void, DestroyImpl, (), (override));
+
+ protected:
+ RenderPipelineMock(DeviceMock* device, const RenderPipelineDescriptor* descriptor);
};
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/SamplerMock.cpp b/src/dawn/tests/unittests/native/mocks/SamplerMock.cpp
index 191addb..c4249cd 100644
--- a/src/dawn/tests/unittests/native/mocks/SamplerMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/SamplerMock.cpp
@@ -16,8 +16,11 @@
namespace dawn::native {
-SamplerMock::SamplerMock(DeviceBase* device) : SamplerBase(device) {
+SamplerMock::SamplerMock(DeviceMock* device, const SamplerDescriptor* descriptor)
+ : SamplerBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->SamplerBase::DestroyImpl(); });
+
+ SetContentHash(ComputeContentHash());
}
SamplerMock::~SamplerMock() = default;
diff --git a/src/dawn/tests/unittests/native/mocks/SamplerMock.h b/src/dawn/tests/unittests/native/mocks/SamplerMock.h
index fc378e8..c0ff32e 100644
--- a/src/dawn/tests/unittests/native/mocks/SamplerMock.h
+++ b/src/dawn/tests/unittests/native/mocks/SamplerMock.h
@@ -17,14 +17,14 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/Sampler.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class SamplerMock : public SamplerBase {
public:
- explicit SamplerMock(DeviceBase* device);
+ SamplerMock(DeviceMock* device, const SamplerDescriptor* descriptor);
~SamplerMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
diff --git a/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.cpp b/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.cpp
index 6cf6a13..e21add2 100644
--- a/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.cpp
@@ -14,27 +14,39 @@
#include "dawn/tests/unittests/native/mocks/ShaderModuleMock.h"
+#include "dawn/native/ChainUtils_autogen.h"
+
namespace dawn::native {
-ShaderModuleMock::ShaderModuleMock(DeviceBase* device) : ShaderModuleBase(device) {
+using ::testing::NiceMock;
+
+ShaderModuleMock::ShaderModuleMock(DeviceMock* device, const ShaderModuleDescriptor* descriptor)
+ : ShaderModuleBase(device, descriptor) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->ShaderModuleBase::DestroyImpl(); });
+
+ SetContentHash(ComputeContentHash());
}
ShaderModuleMock::~ShaderModuleMock() = default;
-ResultOrError<Ref<ShaderModuleMock>> ShaderModuleMock::Create(DeviceBase* device,
- const char* source) {
- ShaderModuleMock* mock = new ShaderModuleMock(device);
-
- ShaderModuleWGSLDescriptor wgslDesc;
- wgslDesc.source = source;
- ShaderModuleDescriptor desc;
- desc.nextInChain = &wgslDesc;
-
+// static
+Ref<ShaderModuleMock> ShaderModuleMock::Create(DeviceMock* device,
+ const ShaderModuleDescriptor* descriptor) {
+ Ref<ShaderModuleMock> shaderModule =
+ AcquireRef(new NiceMock<ShaderModuleMock>(device, descriptor));
ShaderModuleParseResult parseResult;
- DAWN_TRY(ValidateAndParseShaderModule(device, &desc, &parseResult, nullptr));
- DAWN_TRY(mock->InitializeBase(&parseResult, nullptr));
- return AcquireRef(mock);
+ ValidateAndParseShaderModule(device, descriptor, &parseResult, nullptr).AcquireSuccess();
+ shaderModule->InitializeBase(&parseResult, nullptr).AcquireSuccess();
+ return shaderModule;
+}
+
+// static
+Ref<ShaderModuleMock> ShaderModuleMock::Create(DeviceMock* device, const char* source) {
+ ShaderModuleWGSLDescriptor wgslDesc = {};
+ wgslDesc.source = source;
+ ShaderModuleDescriptor desc = {};
+ desc.nextInChain = &wgslDesc;
+ return Create(device, &desc);
}
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.h b/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.h
index 3281e07..6eaa57f 100644
--- a/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.h
+++ b/src/dawn/tests/unittests/native/mocks/ShaderModuleMock.h
@@ -15,25 +15,26 @@
#ifndef SRC_DAWN_TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULEMOCK_H_
#define SRC_DAWN_TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULEMOCK_H_
-#include <memory>
-
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
-#include "dawn/native/Error.h"
#include "dawn/native/ShaderModule.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class ShaderModuleMock : public ShaderModuleBase {
public:
- explicit ShaderModuleMock(DeviceBase* device);
+ // Creates a shader module mock based on a descriptor or wgsl source.
+ static Ref<ShaderModuleMock> Create(DeviceMock* device,
+ const ShaderModuleDescriptor* descriptor);
+ static Ref<ShaderModuleMock> Create(DeviceMock* device, const char* source);
+
~ShaderModuleMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
- // Creates a shader module mock based on the wgsl source.
- static ResultOrError<Ref<ShaderModuleMock>> Create(DeviceBase* device, const char* source);
+ protected:
+ ShaderModuleMock(DeviceMock* device, const ShaderModuleDescriptor* descriptor);
};
} // namespace dawn::native
diff --git a/src/dawn/tests/unittests/native/mocks/TextureMock.cpp b/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
index ce782a6..0980509 100644
--- a/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
@@ -16,14 +16,19 @@
namespace dawn::native {
-TextureMock::TextureMock(DeviceBase* device, TextureBase::TextureState state)
- : TextureBase(device, state) {
+TextureMock::TextureMock(DeviceMock* device,
+ const TextureDescriptor* descriptor,
+ TextureBase::TextureState state)
+ : TextureBase(device, descriptor, state) {
ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->TextureBase::DestroyImpl(); });
}
TextureMock::~TextureMock() = default;
-TextureViewMock::TextureViewMock(TextureBase* texture) : TextureViewBase(texture) {}
+TextureViewMock::TextureViewMock(TextureBase* texture, const TextureViewDescriptor* descriptor)
+ : TextureViewBase(texture, descriptor) {
+ ON_CALL(*this, DestroyImpl).WillByDefault([this]() { this->TextureViewBase::DestroyImpl(); });
+}
TextureViewMock::~TextureViewMock() = default;
diff --git a/src/dawn/tests/unittests/native/mocks/TextureMock.h b/src/dawn/tests/unittests/native/mocks/TextureMock.h
index 20bd928..93a819f 100644
--- a/src/dawn/tests/unittests/native/mocks/TextureMock.h
+++ b/src/dawn/tests/unittests/native/mocks/TextureMock.h
@@ -17,14 +17,16 @@
#include "gmock/gmock.h"
-#include "dawn/native/Device.h"
#include "dawn/native/Texture.h"
+#include "dawn/tests/unittests/native/mocks/DeviceMock.h"
namespace dawn::native {
class TextureMock : public TextureBase {
public:
- TextureMock(DeviceBase* device, TextureBase::TextureState state);
+ TextureMock(DeviceMock* device,
+ const TextureDescriptor* descriptor,
+ TextureBase::TextureState state = TextureBase::TextureState::OwnedInternal);
~TextureMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));
@@ -32,7 +34,7 @@
class TextureViewMock : public TextureViewBase {
public:
- explicit TextureViewMock(TextureBase* texture);
+ TextureViewMock(TextureBase* texture, const TextureViewDescriptor* descriptor);
~TextureViewMock() override;
MOCK_METHOD(void, DestroyImpl, (), (override));