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;
|
||||
}
|
||||
}
|
||||
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
BindGroupBase::~BindGroupBase() {
|
||||
|
@ -407,7 +413,7 @@ namespace dawn_native {
|
|||
// is destroyed after the bind group. The bind group is slab-allocated inside
|
||||
// memory owned by the layout (except for the null backend).
|
||||
Ref<BindGroupLayoutBase> layout = mLayout;
|
||||
RefCounted::DeleteThis();
|
||||
ApiObjectBase::DeleteThis();
|
||||
}
|
||||
|
||||
BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||
|
|
|
@ -73,7 +73,9 @@ namespace dawn_native {
|
|||
static_assert(std::is_base_of<BindGroupBase, Derived>::value, "");
|
||||
}
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
BindGroupBase(DeviceBase* device);
|
||||
|
||||
~BindGroupBase() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -416,13 +416,13 @@ namespace dawn_native {
|
|||
TrackInDevice();
|
||||
}
|
||||
|
||||
BindGroupLayoutBase::~BindGroupLayoutBase() = default;
|
||||
|
||||
bool BindGroupLayoutBase::DestroyApiObject() {
|
||||
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||
if (wasDestroyed) {
|
||||
// Do not uncache the actual cached object if we are a blueprint
|
||||
if (IsCachedReference()) {
|
||||
GetDevice()->UncacheBindGroupLayout(this);
|
||||
}
|
||||
if (wasDestroyed && IsCachedReference()) {
|
||||
// Do not uncache the actual cached object if we are a blueprint or already destroyed.
|
||||
GetDevice()->UncacheBindGroupLayout(this);
|
||||
}
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace dawn_native {
|
|||
BindGroupLayoutBase(DeviceBase* device,
|
||||
const BindGroupLayoutDescriptor* descriptor,
|
||||
PipelineCompatibilityToken pipelineCompatibilityToken);
|
||||
~BindGroupLayoutBase() override;
|
||||
|
||||
static BindGroupLayoutBase* MakeError(DeviceBase* device);
|
||||
|
||||
|
|
|
@ -47,17 +47,26 @@ namespace dawn_native {
|
|||
descriptor->compute.entryPoint, descriptor->compute.constantCount,
|
||||
descriptor->compute.constants}}) {
|
||||
SetContentHash(ComputeContentHash());
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||
: PipelineBase(device, tag) {
|
||||
}
|
||||
|
||||
ComputePipelineBase::~ComputePipelineBase() {
|
||||
// Do not uncache the actual cached object if we are a blueprint
|
||||
if (IsCachedReference()) {
|
||||
ComputePipelineBase::~ComputePipelineBase() = default;
|
||||
|
||||
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);
|
||||
}
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace dawn_native {
|
|||
|
||||
static ComputePipelineBase* MakeError(DeviceBase* device);
|
||||
|
||||
bool DestroyApiObject() override;
|
||||
ObjectType GetType() const override;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
ComputePipelineBase(DeviceBase* device);
|
||||
|
||||
private:
|
||||
ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/Queue.h"
|
||||
#include "dawn_native/RenderBundleEncoder.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
#include "dawn_native/Sampler.h"
|
||||
#include "dawn_native/Surface.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
|
||||
// add complications and extra dependencies.
|
||||
// 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::ShaderModule,
|
||||
ObjectType::Sampler,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// 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
|
||||
|
@ -714,7 +725,7 @@ namespace dawn_native {
|
|||
|
||||
ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::GetOrCreatePipelineLayout(
|
||||
const PipelineLayoutDescriptor* descriptor) {
|
||||
PipelineLayoutBase blueprint(this, descriptor);
|
||||
PipelineLayoutBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
@ -747,7 +758,7 @@ namespace dawn_native {
|
|||
|
||||
ResultOrError<Ref<SamplerBase>> DeviceBase::GetOrCreateSampler(
|
||||
const SamplerDescriptor* descriptor) {
|
||||
SamplerBase blueprint(this, descriptor);
|
||||
SamplerBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
@ -778,7 +789,7 @@ namespace dawn_native {
|
|||
OwnedCompilationMessages* compilationMessages) {
|
||||
ASSERT(parseResult != nullptr);
|
||||
|
||||
ShaderModuleBase blueprint(this, descriptor);
|
||||
ShaderModuleBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "dawn_native/Limits.h"
|
||||
#include "dawn_native/ObjectBase.h"
|
||||
#include "dawn_native/ObjectType_autogen.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
#include "dawn_native/StagingBuffer.h"
|
||||
#include "dawn_native/Toggles.h"
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace dawn_native {
|
|||
ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
|
||||
ApiObjectBase(DeviceBase* device, const char* label);
|
||||
ApiObjectBase(DeviceBase* device, ErrorTag tag);
|
||||
virtual ~ApiObjectBase() override;
|
||||
~ApiObjectBase() override;
|
||||
|
||||
virtual ObjectType GetType() const = 0;
|
||||
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)
|
||||
: ApiObjectBase(device, tag) {
|
||||
}
|
||||
|
||||
PipelineBase::~PipelineBase() = default;
|
||||
|
||||
PipelineLayoutBase* PipelineBase::GetLayout() {
|
||||
ASSERT(!IsError());
|
||||
return mLayout.Get();
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace dawn_native {
|
|||
|
||||
class PipelineBase : public ApiObjectBase, public CachedObject {
|
||||
public:
|
||||
~PipelineBase() override;
|
||||
|
||||
PipelineLayoutBase* GetLayout();
|
||||
const PipelineLayoutBase* GetLayout() const;
|
||||
const RequiredBufferSizes& GetMinBufferSizes() const;
|
||||
|
@ -76,6 +78,9 @@ namespace dawn_native {
|
|||
std::vector<StageAndDescriptor> stages);
|
||||
PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
|
||||
// Constructor used only for mocking and testing.
|
||||
PipelineBase(DeviceBase* device);
|
||||
|
||||
private:
|
||||
MaybeError ValidateGetBindGroupLayout(uint32_t group);
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ namespace dawn_native {
|
|||
// PipelineLayoutBase
|
||||
|
||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
||||
const PipelineLayoutDescriptor* descriptor)
|
||||
const PipelineLayoutDescriptor* descriptor,
|
||||
ApiObjectBase::UntrackedByDeviceTag tag)
|
||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||
ASSERT(descriptor->bindGroupLayoutCount <= kMaxBindGroups);
|
||||
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)
|
||||
: ApiObjectBase(device, tag) {
|
||||
}
|
||||
|
||||
PipelineLayoutBase::~PipelineLayoutBase() {
|
||||
// Do not uncache the actual cached object if we are a blueprint
|
||||
if (IsCachedReference()) {
|
||||
PipelineLayoutBase::~PipelineLayoutBase() = default;
|
||||
|
||||
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);
|
||||
}
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -50,6 +50,9 @@ namespace dawn_native {
|
|||
|
||||
class PipelineLayoutBase : public ApiObjectBase, public CachedObject {
|
||||
public:
|
||||
PipelineLayoutBase(DeviceBase* device,
|
||||
const PipelineLayoutDescriptor* descriptor,
|
||||
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||
PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor);
|
||||
~PipelineLayoutBase() override;
|
||||
|
||||
|
@ -58,6 +61,7 @@ namespace dawn_native {
|
|||
DeviceBase* device,
|
||||
std::vector<StageAndDescriptor> stages);
|
||||
|
||||
bool DestroyApiObject() override;
|
||||
ObjectType GetType() const override;
|
||||
|
||||
const BindGroupLayoutBase* GetBindGroupLayout(BindGroupIndex group) const;
|
||||
|
@ -80,6 +84,8 @@ namespace dawn_native {
|
|||
};
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
PipelineLayoutBase(DeviceBase* device);
|
||||
PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
|
||||
BindGroupLayoutArray mBindGroupLayouts;
|
||||
|
|
|
@ -670,12 +670,28 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
SetContentHash(ComputeContentHash());
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag 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
|
||||
RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
|
||||
class ErrorRenderPipeline final : public RenderPipelineBase {
|
||||
|
@ -697,12 +713,6 @@ namespace dawn_native {
|
|||
return ObjectType::RenderPipeline;
|
||||
}
|
||||
|
||||
RenderPipelineBase::~RenderPipelineBase() {
|
||||
if (IsCachedReference()) {
|
||||
GetDevice()->UncacheRenderPipeline(this);
|
||||
}
|
||||
}
|
||||
|
||||
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
||||
RenderPipelineBase::GetAttributeLocationsUsed() const {
|
||||
ASSERT(!IsError());
|
||||
|
@ -928,62 +938,64 @@ namespace dawn_native {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (ColorAttachmentIndex i :
|
||||
IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
|
||||
const ColorTargetState& descA = *a->GetColorTargetState(i);
|
||||
const ColorTargetState& descB = *b->GetColorTargetState(i);
|
||||
if (descA.writeMask != descB.writeMask) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
if (a->mAttachmentState.Get() != nullptr) {
|
||||
for (ColorAttachmentIndex i :
|
||||
IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
|
||||
const ColorTargetState& descA = *a->GetColorTargetState(i);
|
||||
const ColorTargetState& descB = *b->GetColorTargetState(i);
|
||||
if (descA.writeMask != descB.writeMask) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
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
|
||||
if (a->mAttachmentState->HasDepthStencilAttachment()) {
|
||||
const DepthStencilState& stateA = a->mDepthStencil;
|
||||
const DepthStencilState& stateB = b->mDepthStencil;
|
||||
// Check depth/stencil state
|
||||
if (a->mAttachmentState->HasDepthStencilAttachment()) {
|
||||
const DepthStencilState& stateA = a->mDepthStencil;
|
||||
const DepthStencilState& stateB = b->mDepthStencil;
|
||||
|
||||
ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
|
||||
ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
|
||||
ASSERT(!std::isnan(stateA.depthBiasClamp));
|
||||
ASSERT(!std::isnan(stateB.depthBiasClamp));
|
||||
ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
|
||||
ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
|
||||
ASSERT(!std::isnan(stateA.depthBiasClamp));
|
||||
ASSERT(!std::isnan(stateB.depthBiasClamp));
|
||||
|
||||
if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
|
||||
stateA.depthCompare != stateB.depthCompare ||
|
||||
stateA.depthBias != stateB.depthBias ||
|
||||
stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
|
||||
stateA.depthBiasClamp != stateB.depthBiasClamp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
|
||||
stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
|
||||
stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
|
||||
stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
|
||||
stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
|
||||
stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
|
||||
stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilReadMask != stateB.stencilReadMask ||
|
||||
stateA.stencilWriteMask != stateB.stencilWriteMask) {
|
||||
return false;
|
||||
if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
|
||||
stateA.depthCompare != stateB.depthCompare ||
|
||||
stateA.depthBias != stateB.depthBias ||
|
||||
stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
|
||||
stateA.depthBiasClamp != stateB.depthBiasClamp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
|
||||
stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
|
||||
stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
|
||||
stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
|
||||
stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
|
||||
stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
|
||||
stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
|
||||
return false;
|
||||
}
|
||||
if (stateA.stencilReadMask != stateB.stencilReadMask ||
|
||||
stateA.stencilWriteMask != stateB.stencilWriteMask) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace dawn_native {
|
|||
|
||||
static RenderPipelineBase* MakeError(DeviceBase* device);
|
||||
|
||||
bool DestroyApiObject() override;
|
||||
ObjectType GetType() const override;
|
||||
|
||||
const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
|
||||
|
@ -107,6 +108,10 @@ namespace dawn_native {
|
|||
bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
|
||||
};
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
RenderPipelineBase(DeviceBase* device);
|
||||
|
||||
private:
|
||||
RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
|
||||
|
|
|
@ -69,7 +69,9 @@ namespace dawn_native {
|
|||
|
||||
// SamplerBase
|
||||
|
||||
SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
|
||||
SamplerBase::SamplerBase(DeviceBase* device,
|
||||
const SamplerDescriptor* descriptor,
|
||||
ApiObjectBase::UntrackedByDeviceTag tag)
|
||||
: ApiObjectBase(device, kLabelNotImplemented),
|
||||
mAddressModeU(descriptor->addressModeU),
|
||||
mAddressModeV(descriptor->addressModeV),
|
||||
|
@ -83,14 +85,28 @@ namespace dawn_native {
|
|||
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)
|
||||
: ApiObjectBase(device, tag) {
|
||||
}
|
||||
|
||||
SamplerBase::~SamplerBase() {
|
||||
if (IsCachedReference()) {
|
||||
SamplerBase::~SamplerBase() = default;
|
||||
|
||||
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);
|
||||
}
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -30,11 +30,15 @@ namespace dawn_native {
|
|||
|
||||
class SamplerBase : public ApiObjectBase, public CachedObject {
|
||||
public:
|
||||
SamplerBase(DeviceBase* device,
|
||||
const SamplerDescriptor* descriptor,
|
||||
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||
SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
|
||||
~SamplerBase() override;
|
||||
|
||||
static SamplerBase* MakeError(DeviceBase* device);
|
||||
|
||||
bool DestroyApiObject() override;
|
||||
ObjectType GetType() const override;
|
||||
|
||||
bool IsComparison() const;
|
||||
|
@ -51,6 +55,10 @@ namespace dawn_native {
|
|||
return mMaxAnisotropy;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
SamplerBase(DeviceBase* device);
|
||||
|
||||
private:
|
||||
SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
|
||||
|
|
|
@ -1145,7 +1145,9 @@ namespace dawn_native {
|
|||
|
||||
// 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) {
|
||||
ASSERT(descriptor->nextInChain != 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)
|
||||
: ApiObjectBase(device, tag), mType(Type::Undefined) {
|
||||
}
|
||||
|
||||
ShaderModuleBase::~ShaderModuleBase() {
|
||||
if (IsCachedReference()) {
|
||||
ShaderModuleBase::~ShaderModuleBase() = default;
|
||||
|
||||
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);
|
||||
}
|
||||
return wasDestroyed;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -221,11 +221,15 @@ namespace dawn_native {
|
|||
|
||||
class ShaderModuleBase : public ApiObjectBase, public CachedObject {
|
||||
public:
|
||||
ShaderModuleBase(DeviceBase* device,
|
||||
const ShaderModuleDescriptor* descriptor,
|
||||
ApiObjectBase::UntrackedByDeviceTag tag);
|
||||
ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
|
||||
~ShaderModuleBase() override;
|
||||
|
||||
static Ref<ShaderModuleBase> MakeError(DeviceBase* device);
|
||||
|
||||
bool DestroyApiObject() override;
|
||||
ObjectType GetType() const override;
|
||||
|
||||
// Return true iff the program has an entrypoint called `entryPoint`.
|
||||
|
@ -252,6 +256,9 @@ namespace dawn_native {
|
|||
OwnedCompilationMessages* GetCompilationMessages() const;
|
||||
|
||||
protected:
|
||||
// Constructor used only for mocking and testing.
|
||||
ShaderModuleBase(DeviceBase* device);
|
||||
|
||||
MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
|
||||
|
||||
private:
|
||||
|
|
|
@ -115,6 +115,7 @@ namespace dawn_native {
|
|||
// SwapChainBase
|
||||
|
||||
SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||
TrackInDevice();
|
||||
}
|
||||
|
||||
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||
|
|
|
@ -138,9 +138,20 @@ source_set("dawn_native_mocks_sources") {
|
|||
"${dawn_root}/src/utils:dawn_utils",
|
||||
]
|
||||
|
||||
# Add internal dawn_native config for internal unittests.
|
||||
configs += [ "${dawn_root}/src/dawn_native:dawn_native_internal" ]
|
||||
|
||||
sources = [
|
||||
"unittests/native/mocks/BindGroupLayoutMock.h",
|
||||
"unittests/native/mocks/BindGroupMock.h",
|
||||
"unittests/native/mocks/ComputePipelineMock.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 "mocks/BindGroupLayoutMock.h"
|
||||
#include "mocks/BindGroupMock.h"
|
||||
#include "mocks/ComputePipelineMock.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 "utils/ComboRenderPipelineDescriptor.h"
|
||||
|
||||
namespace dawn_native { namespace {
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::ByMove;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Return;
|
||||
using ::testing::Test;
|
||||
|
||||
TEST(DestroyObjectTests, BindGroupLayoutExplicit) {
|
||||
// Skipping validation on descriptors as coverage for validation is already present.
|
||||
DeviceMock device;
|
||||
device.SetToggle(Toggle::SkipValidation, true);
|
||||
class DestroyObjectTests : public Test {
|
||||
public:
|
||||
DestroyObjectTests() : Test() {
|
||||
// Skipping validation on descriptors as coverage for validation is already present.
|
||||
mDevice.SetToggle(Toggle::SkipValidation, true);
|
||||
}
|
||||
|
||||
BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
|
||||
EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||
Ref<PipelineLayoutMock> GetPipelineLayout() {
|
||||
if (mPipelineLayout != nullptr) {
|
||||
return mPipelineLayout;
|
||||
}
|
||||
mPipelineLayout = AcquireRef(new PipelineLayoutMock(&mDevice));
|
||||
EXPECT_CALL(*mPipelineLayout.Get(), DestroyApiObjectImpl).Times(1);
|
||||
return mPipelineLayout;
|
||||
}
|
||||
|
||||
BindGroupLayoutDescriptor desc = {};
|
||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
||||
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
||||
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
|
||||
Ref<ShaderModuleMock> GetVertexShaderModule() {
|
||||
if (mVsModule != nullptr) {
|
||||
return mVsModule;
|
||||
}
|
||||
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());
|
||||
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
||||
Ref<ShaderModuleMock> GetComputeShaderModule() {
|
||||
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();
|
||||
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
||||
protected:
|
||||
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
|
||||
// will also complain if there is a memory leak.
|
||||
TEST(DestroyObjectTests, BindGroupLayoutImplicit) {
|
||||
// Skipping validation on descriptors as coverage for validation is already present.
|
||||
DeviceMock device;
|
||||
device.SetToggle(Toggle::SkipValidation, true);
|
||||
TEST_F(DestroyObjectTests, BindGroupImplicit) {
|
||||
BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
|
||||
EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
|
||||
{
|
||||
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);
|
||||
|
||||
{
|
||||
BindGroupLayoutDescriptor desc = {};
|
||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
||||
EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
|
||||
.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->IsCachedReference());
|
||||
}
|
||||
}
|
||||
|
||||
// Destroying the objects on the device should result in all created objects being destroyed in
|
||||
// order.
|
||||
TEST(DestroyObjectTests, DestroyObjects) {
|
||||
DeviceMock device;
|
||||
device.SetToggle(Toggle::SkipValidation, true);
|
||||
TEST_F(DestroyObjectTests, ComputePipelineExplicit) {
|
||||
ComputePipelineMock computePipelineMock(&mDevice);
|
||||
EXPECT_CALL(computePipelineMock, DestroyApiObjectImpl).Times(1);
|
||||
|
||||
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;
|
||||
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(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
|
||||
EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
|
||||
}
|
||||
|
||||
BindGroupLayoutDescriptor desc = {};
|
||||
Ref<BindGroupLayoutBase> bindGroupLayout;
|
||||
EXPECT_CALL(device, CreateBindGroupLayoutImpl)
|
||||
.WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
|
||||
DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
|
||||
EXPECT_TRUE(bindGroupLayout->IsAlive());
|
||||
EXPECT_TRUE(bindGroupLayout->IsCachedReference());
|
||||
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());
|
||||
}
|
||||
|
||||
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(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::
|
||||
|
|
|
@ -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