Reland "Adds destroy handling for simple objects without new backend changes yet."
This is a reland of 9901c710d1
Original change's description:
> Adds destroy handling for simple objects without new backend changes yet.
>
> Simple objects are defined here as objects that do not already have a destroy or destroy-like API available. They include:
> - BindGroups
> - ComputePipelines
> - PipelineLayouts
> - RenderPipelines
> - Samplers
> - ShaderModules
> - SwapChains
>
> Changes include:
> - Adds necessary constructors for testing and caching
> - Adding mock objects, mock constructors, and tests
>
> Bug: dawn:628
> Change-Id: I26a5e37bc5580b9064db299a75ef1243521b266a
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65864
> Commit-Queue: Loko Kung <lokokung@google.com>
> Reviewed-by: Austin Eng <enga@chromium.org>
Bug: dawn:628
Change-Id: I19492ad6b1660e205d123b2d1fdf53c772564cfe
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67961
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
This commit is contained in:
parent
1722f9e78e
commit
e1e9fd0722
|
@ -391,6 +391,12 @@ namespace dawn_native {
|
||||||
++packedIdx;
|
++packedIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase::~BindGroupBase() {
|
BindGroupBase::~BindGroupBase() {
|
||||||
|
@ -407,7 +413,7 @@ namespace dawn_native {
|
||||||
// is destroyed after the bind group. The bind group is slab-allocated inside
|
// is destroyed after the bind group. The bind group is slab-allocated inside
|
||||||
// memory owned by the layout (except for the null backend).
|
// memory owned by the layout (except for the null backend).
|
||||||
Ref<BindGroupLayoutBase> layout = mLayout;
|
Ref<BindGroupLayoutBase> layout = mLayout;
|
||||||
RefCounted::DeleteThis();
|
ApiObjectBase::DeleteThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -73,7 +73,9 @@ namespace dawn_native {
|
||||||
static_assert(std::is_base_of<BindGroupBase, Derived>::value, "");
|
static_assert(std::is_base_of<BindGroupBase, Derived>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
// Constructor used only for mocking and testing.
|
||||||
|
BindGroupBase(DeviceBase* device);
|
||||||
|
|
||||||
~BindGroupBase() override;
|
~BindGroupBase() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -416,13 +416,13 @@ namespace dawn_native {
|
||||||
TrackInDevice();
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BindGroupLayoutBase::~BindGroupLayoutBase() = default;
|
||||||
|
|
||||||
bool BindGroupLayoutBase::DestroyApiObject() {
|
bool BindGroupLayoutBase::DestroyApiObject() {
|
||||||
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
if (wasDestroyed) {
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
// Do not uncache the actual cached object if we are a blueprint
|
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||||
if (IsCachedReference()) {
|
GetDevice()->UncacheBindGroupLayout(this);
|
||||||
GetDevice()->UncacheBindGroupLayout(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return wasDestroyed;
|
return wasDestroyed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace dawn_native {
|
||||||
BindGroupLayoutBase(DeviceBase* device,
|
BindGroupLayoutBase(DeviceBase* device,
|
||||||
const BindGroupLayoutDescriptor* descriptor,
|
const BindGroupLayoutDescriptor* descriptor,
|
||||||
PipelineCompatibilityToken pipelineCompatibilityToken);
|
PipelineCompatibilityToken pipelineCompatibilityToken);
|
||||||
|
~BindGroupLayoutBase() override;
|
||||||
|
|
||||||
static BindGroupLayoutBase* MakeError(DeviceBase* device);
|
static BindGroupLayoutBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
|
|
@ -47,17 +47,26 @@ namespace dawn_native {
|
||||||
descriptor->compute.entryPoint, descriptor->compute.constantCount,
|
descriptor->compute.entryPoint, descriptor->compute.constantCount,
|
||||||
descriptor->compute.constants}}) {
|
descriptor->compute.constants}}) {
|
||||||
SetContentHash(ComputeContentHash());
|
SetContentHash(ComputeContentHash());
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: PipelineBase(device, tag) {
|
: PipelineBase(device, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipelineBase::~ComputePipelineBase() {
|
ComputePipelineBase::~ComputePipelineBase() = default;
|
||||||
// Do not uncache the actual cached object if we are a blueprint
|
|
||||||
if (IsCachedReference()) {
|
bool ComputePipelineBase::DestroyApiObject() {
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
|
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||||
GetDevice()->UncacheComputePipeline(this);
|
GetDevice()->UncacheComputePipeline(this);
|
||||||
}
|
}
|
||||||
|
return wasDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
static ComputePipelineBase* MakeError(DeviceBase* device);
|
static ComputePipelineBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
// Functors necessary for the unordered_set<ComputePipelineBase*>-based cache.
|
// Functors necessary for the unordered_set<ComputePipelineBase*>-based cache.
|
||||||
|
@ -41,6 +42,10 @@ namespace dawn_native {
|
||||||
bool operator()(const ComputePipelineBase* a, const ComputePipelineBase* b) const;
|
bool operator()(const ComputePipelineBase* a, const ComputePipelineBase* b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
ComputePipelineBase(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "dawn_native/QuerySet.h"
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/Queue.h"
|
#include "dawn_native/Queue.h"
|
||||||
#include "dawn_native/RenderBundleEncoder.h"
|
#include "dawn_native/RenderBundleEncoder.h"
|
||||||
|
#include "dawn_native/RenderPipeline.h"
|
||||||
#include "dawn_native/Sampler.h"
|
#include "dawn_native/Sampler.h"
|
||||||
#include "dawn_native/Surface.h"
|
#include "dawn_native/Surface.h"
|
||||||
#include "dawn_native/SwapChain.h"
|
#include "dawn_native/SwapChain.h"
|
||||||
|
@ -265,9 +266,19 @@ namespace dawn_native {
|
||||||
// that this only considers the immediate frontend dependencies, while backend objects could
|
// that this only considers the immediate frontend dependencies, while backend objects could
|
||||||
// add complications and extra dependencies.
|
// add complications and extra dependencies.
|
||||||
// TODO(dawn/628) Add types into the array as they are implemented.
|
// TODO(dawn/628) Add types into the array as they are implemented.
|
||||||
static constexpr std::array<ObjectType, 1> kObjectTypeDependencyOrder = {
|
|
||||||
|
// clang-format off
|
||||||
|
static constexpr std::array<ObjectType, 8> kObjectTypeDependencyOrder = {
|
||||||
|
ObjectType::RenderPipeline,
|
||||||
|
ObjectType::ComputePipeline,
|
||||||
|
ObjectType::PipelineLayout,
|
||||||
|
ObjectType::SwapChain,
|
||||||
|
ObjectType::BindGroup,
|
||||||
ObjectType::BindGroupLayout,
|
ObjectType::BindGroupLayout,
|
||||||
|
ObjectType::ShaderModule,
|
||||||
|
ObjectType::Sampler,
|
||||||
};
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
// We first move all objects out from the tracking list into a separate list so that we can
|
// We first move all objects out from the tracking list into a separate list so that we can
|
||||||
// avoid locking the same mutex twice. We can then iterate across the separate list to call
|
// avoid locking the same mutex twice. We can then iterate across the separate list to call
|
||||||
|
@ -714,7 +725,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::GetOrCreatePipelineLayout(
|
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::GetOrCreatePipelineLayout(
|
||||||
const PipelineLayoutDescriptor* descriptor) {
|
const PipelineLayoutDescriptor* descriptor) {
|
||||||
PipelineLayoutBase blueprint(this, descriptor);
|
PipelineLayoutBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||||
|
|
||||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||||
blueprint.SetContentHash(blueprintHash);
|
blueprint.SetContentHash(blueprintHash);
|
||||||
|
@ -747,7 +758,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
ResultOrError<Ref<SamplerBase>> DeviceBase::GetOrCreateSampler(
|
ResultOrError<Ref<SamplerBase>> DeviceBase::GetOrCreateSampler(
|
||||||
const SamplerDescriptor* descriptor) {
|
const SamplerDescriptor* descriptor) {
|
||||||
SamplerBase blueprint(this, descriptor);
|
SamplerBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||||
|
|
||||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||||
blueprint.SetContentHash(blueprintHash);
|
blueprint.SetContentHash(blueprintHash);
|
||||||
|
@ -778,7 +789,7 @@ namespace dawn_native {
|
||||||
OwnedCompilationMessages* compilationMessages) {
|
OwnedCompilationMessages* compilationMessages) {
|
||||||
ASSERT(parseResult != nullptr);
|
ASSERT(parseResult != nullptr);
|
||||||
|
|
||||||
ShaderModuleBase blueprint(this, descriptor);
|
ShaderModuleBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||||
|
|
||||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||||
blueprint.SetContentHash(blueprintHash);
|
blueprint.SetContentHash(blueprintHash);
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "dawn_native/Limits.h"
|
#include "dawn_native/Limits.h"
|
||||||
#include "dawn_native/ObjectBase.h"
|
#include "dawn_native/ObjectBase.h"
|
||||||
#include "dawn_native/ObjectType_autogen.h"
|
#include "dawn_native/ObjectType_autogen.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
|
||||||
#include "dawn_native/StagingBuffer.h"
|
#include "dawn_native/StagingBuffer.h"
|
||||||
#include "dawn_native/Toggles.h"
|
#include "dawn_native/Toggles.h"
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace dawn_native {
|
||||||
ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
|
ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
|
||||||
ApiObjectBase(DeviceBase* device, const char* label);
|
ApiObjectBase(DeviceBase* device, const char* label);
|
||||||
ApiObjectBase(DeviceBase* device, ErrorTag tag);
|
ApiObjectBase(DeviceBase* device, ErrorTag tag);
|
||||||
virtual ~ApiObjectBase() override;
|
~ApiObjectBase() override;
|
||||||
|
|
||||||
virtual ObjectType GetType() const = 0;
|
virtual ObjectType GetType() const = 0;
|
||||||
const std::string& GetLabel() const;
|
const std::string& GetLabel() const;
|
||||||
|
|
|
@ -142,10 +142,15 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PipelineBase::PipelineBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
}
|
||||||
|
|
||||||
PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: ApiObjectBase(device, tag) {
|
: ApiObjectBase(device, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PipelineBase::~PipelineBase() = default;
|
||||||
|
|
||||||
PipelineLayoutBase* PipelineBase::GetLayout() {
|
PipelineLayoutBase* PipelineBase::GetLayout() {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mLayout.Get();
|
return mLayout.Get();
|
||||||
|
|
|
@ -50,6 +50,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
class PipelineBase : public ApiObjectBase, public CachedObject {
|
class PipelineBase : public ApiObjectBase, public CachedObject {
|
||||||
public:
|
public:
|
||||||
|
~PipelineBase() override;
|
||||||
|
|
||||||
PipelineLayoutBase* GetLayout();
|
PipelineLayoutBase* GetLayout();
|
||||||
const PipelineLayoutBase* GetLayout() const;
|
const PipelineLayoutBase* GetLayout() const;
|
||||||
const RequiredBufferSizes& GetMinBufferSizes() const;
|
const RequiredBufferSizes& GetMinBufferSizes() const;
|
||||||
|
@ -76,6 +78,9 @@ namespace dawn_native {
|
||||||
std::vector<StageAndDescriptor> stages);
|
std::vector<StageAndDescriptor> stages);
|
||||||
PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
PipelineBase(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MaybeError ValidateGetBindGroupLayout(uint32_t group);
|
MaybeError ValidateGetBindGroupLayout(uint32_t group);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,8 @@ namespace dawn_native {
|
||||||
// PipelineLayoutBase
|
// PipelineLayoutBase
|
||||||
|
|
||||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
||||||
const PipelineLayoutDescriptor* descriptor)
|
const PipelineLayoutDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
ASSERT(descriptor->bindGroupLayoutCount <= kMaxBindGroups);
|
ASSERT(descriptor->bindGroupLayoutCount <= kMaxBindGroups);
|
||||||
for (BindGroupIndex group(0); group < BindGroupIndex(descriptor->bindGroupLayoutCount);
|
for (BindGroupIndex group(0); group < BindGroupIndex(descriptor->bindGroupLayoutCount);
|
||||||
|
@ -67,15 +68,30 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
||||||
|
const PipelineLayoutDescriptor* descriptor)
|
||||||
|
: PipelineLayoutBase(device, descriptor, kUntrackedByDevice) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device)
|
||||||
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: ApiObjectBase(device, tag) {
|
: ApiObjectBase(device, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineLayoutBase::~PipelineLayoutBase() {
|
PipelineLayoutBase::~PipelineLayoutBase() = default;
|
||||||
// Do not uncache the actual cached object if we are a blueprint
|
|
||||||
if (IsCachedReference()) {
|
bool PipelineLayoutBase::DestroyApiObject() {
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
|
// Do not uncache the actual cached object if we are a blueprint
|
||||||
GetDevice()->UncachePipelineLayout(this);
|
GetDevice()->UncachePipelineLayout(this);
|
||||||
}
|
}
|
||||||
|
return wasDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -50,6 +50,9 @@ namespace dawn_native {
|
||||||
|
|
||||||
class PipelineLayoutBase : public ApiObjectBase, public CachedObject {
|
class PipelineLayoutBase : public ApiObjectBase, public CachedObject {
|
||||||
public:
|
public:
|
||||||
|
PipelineLayoutBase(DeviceBase* device,
|
||||||
|
const PipelineLayoutDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||||
PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor);
|
PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor);
|
||||||
~PipelineLayoutBase() override;
|
~PipelineLayoutBase() override;
|
||||||
|
|
||||||
|
@ -58,6 +61,7 @@ namespace dawn_native {
|
||||||
DeviceBase* device,
|
DeviceBase* device,
|
||||||
std::vector<StageAndDescriptor> stages);
|
std::vector<StageAndDescriptor> stages);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
const BindGroupLayoutBase* GetBindGroupLayout(BindGroupIndex group) const;
|
const BindGroupLayoutBase* GetBindGroupLayout(BindGroupIndex group) const;
|
||||||
|
@ -80,6 +84,8 @@ namespace dawn_native {
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
PipelineLayoutBase(DeviceBase* device);
|
||||||
PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
BindGroupLayoutArray mBindGroupLayouts;
|
BindGroupLayoutArray mBindGroupLayouts;
|
||||||
|
|
|
@ -670,12 +670,28 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
SetContentHash(ComputeContentHash());
|
SetContentHash(ComputeContentHash());
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: PipelineBase(device, tag) {
|
: PipelineBase(device, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderPipelineBase::~RenderPipelineBase() = default;
|
||||||
|
|
||||||
|
bool RenderPipelineBase::DestroyApiObject() {
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
|
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||||
|
GetDevice()->UncacheRenderPipeline(this);
|
||||||
|
}
|
||||||
|
return wasDestroyed;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
|
RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
|
||||||
class ErrorRenderPipeline final : public RenderPipelineBase {
|
class ErrorRenderPipeline final : public RenderPipelineBase {
|
||||||
|
@ -697,12 +713,6 @@ namespace dawn_native {
|
||||||
return ObjectType::RenderPipeline;
|
return ObjectType::RenderPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipelineBase::~RenderPipelineBase() {
|
|
||||||
if (IsCachedReference()) {
|
|
||||||
GetDevice()->UncacheRenderPipeline(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
||||||
RenderPipelineBase::GetAttributeLocationsUsed() const {
|
RenderPipelineBase::GetAttributeLocationsUsed() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
|
@ -928,62 +938,64 @@ namespace dawn_native {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ColorAttachmentIndex i :
|
if (a->mAttachmentState.Get() != nullptr) {
|
||||||
IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
|
for (ColorAttachmentIndex i :
|
||||||
const ColorTargetState& descA = *a->GetColorTargetState(i);
|
IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
|
||||||
const ColorTargetState& descB = *b->GetColorTargetState(i);
|
const ColorTargetState& descA = *a->GetColorTargetState(i);
|
||||||
if (descA.writeMask != descB.writeMask) {
|
const ColorTargetState& descB = *b->GetColorTargetState(i);
|
||||||
return false;
|
if (descA.writeMask != descB.writeMask) {
|
||||||
}
|
|
||||||
if ((descA.blend == nullptr) != (descB.blend == nullptr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (descA.blend != nullptr) {
|
|
||||||
if (descA.blend->color.operation != descB.blend->color.operation ||
|
|
||||||
descA.blend->color.srcFactor != descB.blend->color.srcFactor ||
|
|
||||||
descA.blend->color.dstFactor != descB.blend->color.dstFactor) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (descA.blend->alpha.operation != descB.blend->alpha.operation ||
|
if ((descA.blend == nullptr) != (descB.blend == nullptr)) {
|
||||||
descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor ||
|
|
||||||
descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (descA.blend != nullptr) {
|
||||||
|
if (descA.blend->color.operation != descB.blend->color.operation ||
|
||||||
|
descA.blend->color.srcFactor != descB.blend->color.srcFactor ||
|
||||||
|
descA.blend->color.dstFactor != descB.blend->color.dstFactor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (descA.blend->alpha.operation != descB.blend->alpha.operation ||
|
||||||
|
descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor ||
|
||||||
|
descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check depth/stencil state
|
// Check depth/stencil state
|
||||||
if (a->mAttachmentState->HasDepthStencilAttachment()) {
|
if (a->mAttachmentState->HasDepthStencilAttachment()) {
|
||||||
const DepthStencilState& stateA = a->mDepthStencil;
|
const DepthStencilState& stateA = a->mDepthStencil;
|
||||||
const DepthStencilState& stateB = b->mDepthStencil;
|
const DepthStencilState& stateB = b->mDepthStencil;
|
||||||
|
|
||||||
ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
|
ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
|
||||||
ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
|
ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
|
||||||
ASSERT(!std::isnan(stateA.depthBiasClamp));
|
ASSERT(!std::isnan(stateA.depthBiasClamp));
|
||||||
ASSERT(!std::isnan(stateB.depthBiasClamp));
|
ASSERT(!std::isnan(stateB.depthBiasClamp));
|
||||||
|
|
||||||
if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
|
if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
|
||||||
stateA.depthCompare != stateB.depthCompare ||
|
stateA.depthCompare != stateB.depthCompare ||
|
||||||
stateA.depthBias != stateB.depthBias ||
|
stateA.depthBias != stateB.depthBias ||
|
||||||
stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
|
stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
|
||||||
stateA.depthBiasClamp != stateB.depthBiasClamp) {
|
stateA.depthBiasClamp != stateB.depthBiasClamp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
|
if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
|
||||||
stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
|
stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
|
||||||
stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
|
stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
|
||||||
stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
|
stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
|
if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
|
||||||
stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
|
stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
|
||||||
stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
|
stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
|
||||||
stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
|
stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (stateA.stencilReadMask != stateB.stencilReadMask ||
|
if (stateA.stencilReadMask != stateB.stencilReadMask ||
|
||||||
stateA.stencilWriteMask != stateB.stencilWriteMask) {
|
stateA.stencilWriteMask != stateB.stencilWriteMask) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
static RenderPipelineBase* MakeError(DeviceBase* device);
|
static RenderPipelineBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
||||||
|
@ -107,6 +108,10 @@ namespace dawn_native {
|
||||||
bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
|
bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
RenderPipelineBase(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,9 @@ namespace dawn_native {
|
||||||
|
|
||||||
// SamplerBase
|
// SamplerBase
|
||||||
|
|
||||||
SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
|
SamplerBase::SamplerBase(DeviceBase* device,
|
||||||
|
const SamplerDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented),
|
: ApiObjectBase(device, kLabelNotImplemented),
|
||||||
mAddressModeU(descriptor->addressModeU),
|
mAddressModeU(descriptor->addressModeU),
|
||||||
mAddressModeV(descriptor->addressModeV),
|
mAddressModeV(descriptor->addressModeV),
|
||||||
|
@ -83,14 +85,28 @@ namespace dawn_native {
|
||||||
mMaxAnisotropy(descriptor->maxAnisotropy) {
|
mMaxAnisotropy(descriptor->maxAnisotropy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
|
||||||
|
: SamplerBase(device, descriptor, kUntrackedByDevice) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
SamplerBase::SamplerBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: ApiObjectBase(device, tag) {
|
: ApiObjectBase(device, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerBase::~SamplerBase() {
|
SamplerBase::~SamplerBase() = default;
|
||||||
if (IsCachedReference()) {
|
|
||||||
|
bool SamplerBase::DestroyApiObject() {
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
|
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||||
GetDevice()->UncacheSampler(this);
|
GetDevice()->UncacheSampler(this);
|
||||||
}
|
}
|
||||||
|
return wasDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -30,11 +30,15 @@ namespace dawn_native {
|
||||||
|
|
||||||
class SamplerBase : public ApiObjectBase, public CachedObject {
|
class SamplerBase : public ApiObjectBase, public CachedObject {
|
||||||
public:
|
public:
|
||||||
|
SamplerBase(DeviceBase* device,
|
||||||
|
const SamplerDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||||
SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
|
SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
|
||||||
~SamplerBase() override;
|
~SamplerBase() override;
|
||||||
|
|
||||||
static SamplerBase* MakeError(DeviceBase* device);
|
static SamplerBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
bool IsComparison() const;
|
bool IsComparison() const;
|
||||||
|
@ -51,6 +55,10 @@ namespace dawn_native {
|
||||||
return mMaxAnisotropy;
|
return mMaxAnisotropy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
SamplerBase(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
|
|
@ -1145,7 +1145,9 @@ namespace dawn_native {
|
||||||
|
|
||||||
// ShaderModuleBase
|
// ShaderModuleBase
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device,
|
||||||
|
const ShaderModuleDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag)
|
||||||
: ApiObjectBase(device, descriptor->label), mType(Type::Undefined) {
|
: ApiObjectBase(device, descriptor->label), mType(Type::Undefined) {
|
||||||
ASSERT(descriptor->nextInChain != nullptr);
|
ASSERT(descriptor->nextInChain != nullptr);
|
||||||
const ShaderModuleSPIRVDescriptor* spirvDesc = nullptr;
|
const ShaderModuleSPIRVDescriptor* spirvDesc = nullptr;
|
||||||
|
@ -1163,14 +1165,29 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
|
||||||
|
: ShaderModuleBase(device, descriptor, kUntrackedByDevice) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device)
|
||||||
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: ApiObjectBase(device, tag), mType(Type::Undefined) {
|
: ApiObjectBase(device, tag), mType(Type::Undefined) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBase::~ShaderModuleBase() {
|
ShaderModuleBase::~ShaderModuleBase() = default;
|
||||||
if (IsCachedReference()) {
|
|
||||||
|
bool ShaderModuleBase::DestroyApiObject() {
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
if (wasDestroyed && IsCachedReference()) {
|
||||||
|
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||||
GetDevice()->UncacheShaderModule(this);
|
GetDevice()->UncacheShaderModule(this);
|
||||||
}
|
}
|
||||||
|
return wasDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -221,11 +221,15 @@ namespace dawn_native {
|
||||||
|
|
||||||
class ShaderModuleBase : public ApiObjectBase, public CachedObject {
|
class ShaderModuleBase : public ApiObjectBase, public CachedObject {
|
||||||
public:
|
public:
|
||||||
|
ShaderModuleBase(DeviceBase* device,
|
||||||
|
const ShaderModuleDescriptor* descriptor,
|
||||||
|
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||||
ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
|
ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
|
||||||
~ShaderModuleBase() override;
|
~ShaderModuleBase() override;
|
||||||
|
|
||||||
static Ref<ShaderModuleBase> MakeError(DeviceBase* device);
|
static Ref<ShaderModuleBase> MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
// Return true iff the program has an entrypoint called `entryPoint`.
|
// Return true iff the program has an entrypoint called `entryPoint`.
|
||||||
|
@ -252,6 +256,9 @@ namespace dawn_native {
|
||||||
OwnedCompilationMessages* GetCompilationMessages() const;
|
OwnedCompilationMessages* GetCompilationMessages() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
ShaderModuleBase(DeviceBase* device);
|
||||||
|
|
||||||
MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
|
MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -115,6 +115,7 @@ namespace dawn_native {
|
||||||
// SwapChainBase
|
// SwapChainBase
|
||||||
|
|
||||||
SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -138,9 +138,20 @@ source_set("dawn_native_mocks_sources") {
|
||||||
"${dawn_root}/src/utils:dawn_utils",
|
"${dawn_root}/src/utils:dawn_utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Add internal dawn_native config for internal unittests.
|
||||||
|
configs += [ "${dawn_root}/src/dawn_native:dawn_native_internal" ]
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
"unittests/native/mocks/BindGroupLayoutMock.h",
|
"unittests/native/mocks/BindGroupLayoutMock.h",
|
||||||
|
"unittests/native/mocks/BindGroupMock.h",
|
||||||
|
"unittests/native/mocks/ComputePipelineMock.h",
|
||||||
"unittests/native/mocks/DeviceMock.h",
|
"unittests/native/mocks/DeviceMock.h",
|
||||||
|
"unittests/native/mocks/PipelineLayoutMock.h",
|
||||||
|
"unittests/native/mocks/RenderPipelineMock.h",
|
||||||
|
"unittests/native/mocks/SamplerMock.h",
|
||||||
|
"unittests/native/mocks/ShaderModuleMock.cpp",
|
||||||
|
"unittests/native/mocks/ShaderModuleMock.h",
|
||||||
|
"unittests/native/mocks/SwapChainMock.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,80 +16,453 @@
|
||||||
|
|
||||||
#include "dawn_native/Toggles.h"
|
#include "dawn_native/Toggles.h"
|
||||||
#include "mocks/BindGroupLayoutMock.h"
|
#include "mocks/BindGroupLayoutMock.h"
|
||||||
|
#include "mocks/BindGroupMock.h"
|
||||||
|
#include "mocks/ComputePipelineMock.h"
|
||||||
#include "mocks/DeviceMock.h"
|
#include "mocks/DeviceMock.h"
|
||||||
|
#include "mocks/PipelineLayoutMock.h"
|
||||||
|
#include "mocks/RenderPipelineMock.h"
|
||||||
|
#include "mocks/SamplerMock.h"
|
||||||
|
#include "mocks/ShaderModuleMock.h"
|
||||||
|
#include "mocks/SwapChainMock.h"
|
||||||
#include "tests/DawnNativeTest.h"
|
#include "tests/DawnNativeTest.h"
|
||||||
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
|
||||||
namespace dawn_native { namespace {
|
namespace dawn_native { namespace {
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
using ::testing::ByMove;
|
using ::testing::ByMove;
|
||||||
using ::testing::InSequence;
|
using ::testing::InSequence;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
TEST(DestroyObjectTests, BindGroupLayoutExplicit) {
|
class DestroyObjectTests : public Test {
|
||||||
// Skipping validation on descriptors as coverage for validation is already present.
|
public:
|
||||||
DeviceMock device;
|
DestroyObjectTests() : Test() {
|
||||||
device.SetToggle(Toggle::SkipValidation, true);
|
// Skipping validation on descriptors as coverage for validation is already present.
|
||||||
|
mDevice.SetToggle(Toggle::SkipValidation, true);
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
|
Ref<PipelineLayoutMock> GetPipelineLayout() {
|
||||||
EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
if (mPipelineLayout != nullptr) {
|
||||||
|
return mPipelineLayout;
|
||||||
|
}
|
||||||
|
mPipelineLayout = AcquireRef(new PipelineLayoutMock(&mDevice));
|
||||||
|
EXPECT_CALL(*mPipelineLayout.Get(), DestroyApiObjectImpl).Times(1);
|
||||||
|
return mPipelineLayout;
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupLayoutDescriptor desc = {};
|
Ref<ShaderModuleMock> GetVertexShaderModule() {
|
||||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
if (mVsModule != nullptr) {
|
||||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
return mVsModule;
|
||||||
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
}
|
||||||
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
|
DAWN_TRY_ASSIGN_WITH_CLEANUP(
|
||||||
|
mVsModule, ShaderModuleMock::Create(&mDevice, R"(
|
||||||
|
[[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {
|
||||||
|
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||||
|
})"),
|
||||||
|
{ ASSERT(false); }, mVsModule);
|
||||||
|
EXPECT_CALL(*mVsModule.Get(), DestroyApiObjectImpl).Times(1);
|
||||||
|
return mVsModule;
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(bindGroupLayout->IsAlive());
|
Ref<ShaderModuleMock> GetComputeShaderModule() {
|
||||||
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
if (mCsModule != nullptr) {
|
||||||
|
return mCsModule;
|
||||||
|
}
|
||||||
|
DAWN_TRY_ASSIGN_WITH_CLEANUP(
|
||||||
|
mCsModule, ShaderModuleMock::Create(&mDevice, R"(
|
||||||
|
[[stage(compute), workgroup_size(1)]] fn main() {
|
||||||
|
})"),
|
||||||
|
{ ASSERT(false); }, mCsModule);
|
||||||
|
EXPECT_CALL(*mCsModule.Get(), DestroyApiObjectImpl).Times(1);
|
||||||
|
return mCsModule;
|
||||||
|
}
|
||||||
|
|
||||||
bindGroupLayout->DestroyApiObject();
|
protected:
|
||||||
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
DeviceMock mDevice;
|
||||||
|
|
||||||
|
// The following lazy-initialized objects are used to facilitate creation of dependent
|
||||||
|
// objects under test.
|
||||||
|
Ref<PipelineLayoutMock> mPipelineLayout;
|
||||||
|
Ref<ShaderModuleMock> mVsModule;
|
||||||
|
Ref<ShaderModuleMock> mCsModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(DestroyObjectTests, BindGroupExplicit) {
|
||||||
|
BindGroupMock bindGroupMock(&mDevice);
|
||||||
|
EXPECT_CALL(bindGroupMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(bindGroupMock.IsAlive());
|
||||||
|
bindGroupMock.DestroyApiObject();
|
||||||
|
EXPECT_FALSE(bindGroupMock.IsAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
|
// 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.
|
// will also complain if there is a memory leak.
|
||||||
TEST(DestroyObjectTests, BindGroupLayoutImplicit) {
|
TEST_F(DestroyObjectTests, BindGroupImplicit) {
|
||||||
// Skipping validation on descriptors as coverage for validation is already present.
|
BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
|
||||||
DeviceMock device;
|
EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
|
||||||
device.SetToggle(Toggle::SkipValidation, true);
|
{
|
||||||
|
BindGroupDescriptor desc = {};
|
||||||
|
Ref<BindGroupBase> bindGroup;
|
||||||
|
EXPECT_CALL(mDevice, CreateBindGroupImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
|
||||||
|
|
||||||
BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
|
EXPECT_TRUE(bindGroup->IsAlive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyObjectTests, BindGroupLayoutExplicit) {
|
||||||
|
BindGroupLayoutMock bindGroupLayoutMock(&mDevice);
|
||||||
|
EXPECT_CALL(bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(bindGroupLayoutMock.IsAlive());
|
||||||
|
bindGroupLayoutMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
{
|
{
|
||||||
BindGroupLayoutDescriptor desc = {};
|
BindGroupLayoutDescriptor desc = {};
|
||||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
|
||||||
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
||||||
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
|
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, mDevice.CreateBindGroupLayout(&desc));
|
||||||
|
|
||||||
EXPECT_TRUE(bindGroupLayout->IsAlive());
|
EXPECT_TRUE(bindGroupLayout->IsAlive());
|
||||||
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroying the objects on the device should result in all created objects being destroyed in
|
TEST_F(DestroyObjectTests, ComputePipelineExplicit) {
|
||||||
// order.
|
ComputePipelineMock computePipelineMock(&mDevice);
|
||||||
TEST(DestroyObjectTests, DestroyObjects) {
|
EXPECT_CALL(computePipelineMock, DestroyApiObjectImpl).Times(1);
|
||||||
DeviceMock device;
|
|
||||||
device.SetToggle(Toggle::SkipValidation, true);
|
|
||||||
|
|
||||||
BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
|
EXPECT_TRUE(computePipelineMock.IsAlive());
|
||||||
|
computePipelineMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).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, PipelineLayoutExplicit) {
|
||||||
|
PipelineLayoutMock pipelineLayoutMock(&mDevice);
|
||||||
|
EXPECT_CALL(pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(pipelineLayoutMock.IsAlive());
|
||||||
|
pipelineLayoutMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).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, RenderPipelineExplicit) {
|
||||||
|
RenderPipelineMock renderPipelineMock(&mDevice);
|
||||||
|
EXPECT_CALL(renderPipelineMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(renderPipelineMock.IsAlive());
|
||||||
|
renderPipelineMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).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, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(samplerMock.IsAlive());
|
||||||
|
samplerMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).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, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(shaderModuleMock.IsAlive());
|
||||||
|
shaderModuleMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).Times(1);
|
||||||
|
{
|
||||||
|
ShaderModuleWGSLDescriptor wgslDesc;
|
||||||
|
wgslDesc.source = R"(
|
||||||
|
[[stage(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, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(swapChainMock.IsAlive());
|
||||||
|
swapChainMock.DestroyApiObject();
|
||||||
|
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, DestroyApiObjectImpl).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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
|
||||||
|
PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
|
||||||
|
RenderPipelineMock* renderPipelineMock = new RenderPipelineMock(&mDevice);
|
||||||
|
SamplerMock* samplerMock = new SamplerMock(&mDevice);
|
||||||
|
ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
|
||||||
|
SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
|
||||||
{
|
{
|
||||||
InSequence seq;
|
InSequence seq;
|
||||||
|
EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*computePipelineMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*swapChainMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
|
||||||
EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutDescriptor desc = {};
|
Ref<BindGroupBase> bindGroup;
|
||||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
{
|
||||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
BindGroupDescriptor desc = {};
|
||||||
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
EXPECT_CALL(mDevice, CreateBindGroupImpl)
|
||||||
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
|
.WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
|
||||||
EXPECT_TRUE(bindGroupLayout->IsAlive());
|
DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
|
||||||
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
EXPECT_TRUE(bindGroup->IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
device.DestroyObjects();
|
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<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<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<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"(
|
||||||
|
[[stage(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());
|
||||||
|
}
|
||||||
|
|
||||||
|
mDevice.DestroyObjects();
|
||||||
|
EXPECT_FALSE(bindGroup->IsAlive());
|
||||||
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
||||||
|
EXPECT_FALSE(computePipeline->IsAlive());
|
||||||
|
EXPECT_FALSE(pipelineLayout->IsAlive());
|
||||||
|
EXPECT_FALSE(renderPipeline->IsAlive());
|
||||||
|
EXPECT_FALSE(sampler->IsAlive());
|
||||||
|
EXPECT_FALSE(shaderModule->IsAlive());
|
||||||
|
EXPECT_FALSE(swapChain->IsAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::
|
}} // namespace dawn_native::
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/BindGroup.h"
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class BindGroupMock : public BindGroupBase {
|
||||||
|
public:
|
||||||
|
BindGroupMock(DeviceBase* device) : BindGroupBase(device) {
|
||||||
|
}
|
||||||
|
~BindGroupMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/ComputePipeline.h"
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class ComputePipelineMock : public ComputePipelineBase {
|
||||||
|
public:
|
||||||
|
ComputePipelineMock(DeviceBase* device) : ComputePipelineBase(device) {
|
||||||
|
}
|
||||||
|
~ComputePipelineMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(MaybeError, Initialize, (), (override));
|
||||||
|
MOCK_METHOD(size_t, ComputeContentHash, (), (override));
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/PipelineLayout.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class PipelineLayoutMock : public PipelineLayoutBase {
|
||||||
|
public:
|
||||||
|
PipelineLayoutMock(DeviceBase* device) : PipelineLayoutBase(device) {
|
||||||
|
}
|
||||||
|
~PipelineLayoutMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class RenderPipelineMock : public RenderPipelineBase {
|
||||||
|
public:
|
||||||
|
RenderPipelineMock(DeviceBase* device) : RenderPipelineBase(device) {
|
||||||
|
}
|
||||||
|
~RenderPipelineMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(MaybeError, Initialize, (), (override));
|
||||||
|
MOCK_METHOD(size_t, ComputeContentHash, (), (override));
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/Sampler.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class SamplerMock : public SamplerBase {
|
||||||
|
public:
|
||||||
|
SamplerMock(DeviceBase* device) : SamplerBase(device) {
|
||||||
|
}
|
||||||
|
~SamplerMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2021 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 "ShaderModuleMock.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ShaderModuleParseResult parseResult;
|
||||||
|
DAWN_TRY(ValidateShaderModuleDescriptor(device, &desc, &parseResult, nullptr));
|
||||||
|
DAWN_TRY(mock->InitializeBase(&parseResult));
|
||||||
|
return AcquireRef(mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/Error.h"
|
||||||
|
#include "dawn_native/ShaderModule.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class ShaderModuleMock : public ShaderModuleBase {
|
||||||
|
public:
|
||||||
|
ShaderModuleMock(DeviceBase* device) : ShaderModuleBase(device) {
|
||||||
|
}
|
||||||
|
~ShaderModuleMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
|
||||||
|
// Creates a shader module mock based on the wgsl source.
|
||||||
|
static ResultOrError<Ref<ShaderModuleMock>> Create(DeviceBase* device, const char* source);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2021 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 TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/SwapChain.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class SwapChainMock : public SwapChainBase {
|
||||||
|
public:
|
||||||
|
SwapChainMock(DeviceBase* device) : SwapChainBase(device) {
|
||||||
|
}
|
||||||
|
~SwapChainMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
APIConfigure,
|
||||||
|
(wgpu::TextureFormat, wgpu::TextureUsage, uint32_t, uint32_t),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(TextureViewBase*, APIGetCurrentTextureView, (), (override));
|
||||||
|
MOCK_METHOD(void, APIPresent, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_
|
Loading…
Reference in New Issue