mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-07 13:45:51 +00:00
Adds destruction handling for Textures when device is destroyed.
Bug: dawn:628 Change-Id: Iaaa62507592e12a724673a0226783c0425b04f35 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67601 Commit-Queue: Loko Kung <lokokung@google.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
75c978f9b9
commit
6b6262dde0
@ -269,7 +269,7 @@ namespace dawn_native {
|
|||||||
// TODO(dawn/628) Add types into the array as they are implemented.
|
// TODO(dawn/628) Add types into the array as they are implemented.
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static constexpr std::array<ObjectType, 10> kObjectTypeDependencyOrder = {
|
static constexpr std::array<ObjectType, 13> kObjectTypeDependencyOrder = {
|
||||||
ObjectType::RenderPipeline,
|
ObjectType::RenderPipeline,
|
||||||
ObjectType::ComputePipeline,
|
ObjectType::ComputePipeline,
|
||||||
ObjectType::PipelineLayout,
|
ObjectType::PipelineLayout,
|
||||||
@ -277,6 +277,9 @@ namespace dawn_native {
|
|||||||
ObjectType::BindGroup,
|
ObjectType::BindGroup,
|
||||||
ObjectType::BindGroupLayout,
|
ObjectType::BindGroupLayout,
|
||||||
ObjectType::ShaderModule,
|
ObjectType::ShaderModule,
|
||||||
|
ObjectType::ExternalTexture,
|
||||||
|
ObjectType::TextureView,
|
||||||
|
ObjectType::Texture,
|
||||||
ObjectType::QuerySet,
|
ObjectType::QuerySet,
|
||||||
ObjectType::Sampler,
|
ObjectType::Sampler,
|
||||||
ObjectType::Buffer,
|
ObjectType::Buffer,
|
||||||
|
@ -91,6 +91,12 @@ namespace dawn_native {
|
|||||||
const ExternalTextureDescriptor* descriptor)
|
const ExternalTextureDescriptor* descriptor)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
|
: ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
|
||||||
textureViews[0] = descriptor->plane0;
|
textureViews[0] = descriptor->plane0;
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalTextureBase::ExternalTextureBase(DeviceBase* device)
|
||||||
|
: ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalTextureBase::ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
ExternalTextureBase::ExternalTextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
@ -113,8 +119,12 @@ namespace dawn_native {
|
|||||||
if (GetDevice()->ConsumedError(GetDevice()->ValidateObject(this))) {
|
if (GetDevice()->ConsumedError(GetDevice()->ValidateObject(this))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
DestroyApiObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExternalTextureBase::DestroyApiObject() {
|
||||||
mState = ExternalTextureState::Destroyed;
|
mState = ExternalTextureState::Destroyed;
|
||||||
ASSERT(!IsError());
|
return ApiObjectBase::DestroyApiObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -42,10 +42,15 @@ namespace dawn_native {
|
|||||||
|
|
||||||
static ExternalTextureBase* MakeError(DeviceBase* device);
|
static ExternalTextureBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
void APIDestroy();
|
void APIDestroy();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
ExternalTextureBase(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ExternalTextureState { Alive, Destroyed };
|
enum class ExternalTextureState { Alive, Destroyed };
|
||||||
ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
|
ExternalTextureBase(DeviceBase* device, const ExternalTextureDescriptor* descriptor);
|
||||||
|
@ -469,14 +469,30 @@ namespace dawn_native {
|
|||||||
if (internalUsageDesc != nullptr) {
|
if (internalUsageDesc != nullptr) {
|
||||||
mInternalUsage |= internalUsageDesc->internalUsage;
|
mInternalUsage |= internalUsageDesc->internalUsage;
|
||||||
}
|
}
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Format kUnusedFormat;
|
static Format kUnusedFormat;
|
||||||
|
|
||||||
|
TextureBase::TextureBase(DeviceBase* device, TextureState state)
|
||||||
|
: ApiObjectBase(device, kLabelNotImplemented), mFormat(kUnusedFormat), mState(state) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
: ApiObjectBase(device, tag), mFormat(kUnusedFormat) {
|
: ApiObjectBase(device, tag), mFormat(kUnusedFormat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextureBase::DestroyApiObject() {
|
||||||
|
// We need to run the destroy operations prior to setting the state to destroyed so that
|
||||||
|
// the state is both consistent, and implementations of the destroy that may check the
|
||||||
|
// state do not skip operations unintentionally. (Example in Vulkan backend, the destroy
|
||||||
|
// implementation will not be ran if we are already in the Destroyed state.)
|
||||||
|
bool wasDestroyed = ApiObjectBase::DestroyApiObject();
|
||||||
|
mState = TextureState::Destroyed;
|
||||||
|
return wasDestroyed;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
TextureBase* TextureBase::MakeError(DeviceBase* device) {
|
TextureBase* TextureBase::MakeError(DeviceBase* device) {
|
||||||
return new TextureBase(device, ObjectBase::kError);
|
return new TextureBase(device, ObjectBase::kError);
|
||||||
@ -670,15 +686,7 @@ namespace dawn_native {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
DestroyInternal();
|
DestroyApiObject();
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBase::DestroyImpl() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureBase::DestroyInternal() {
|
|
||||||
DestroyImpl();
|
|
||||||
mState = TextureState::Destroyed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError TextureBase::ValidateDestroy() const {
|
MaybeError TextureBase::ValidateDestroy() const {
|
||||||
@ -696,6 +704,14 @@ namespace dawn_native {
|
|||||||
mRange({ConvertViewAspect(mFormat, descriptor->aspect),
|
mRange({ConvertViewAspect(mFormat, descriptor->aspect),
|
||||||
{descriptor->baseArrayLayer, descriptor->arrayLayerCount},
|
{descriptor->baseArrayLayer, descriptor->arrayLayerCount},
|
||||||
{descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
|
{descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
|
||||||
|
TrackInDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureViewBase::TextureViewBase(TextureBase* texture)
|
||||||
|
: ApiObjectBase(texture->GetDevice(), kLabelNotImplemented),
|
||||||
|
mTexture(texture),
|
||||||
|
mFormat(kUnusedFormat) {
|
||||||
|
TrackInDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
@ -51,6 +51,7 @@ namespace dawn_native {
|
|||||||
|
|
||||||
static TextureBase* MakeError(DeviceBase* device);
|
static TextureBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
|
bool DestroyApiObject() override;
|
||||||
ObjectType GetType() const override;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
wgpu::TextureDimension GetDimension() const;
|
wgpu::TextureDimension GetDimension() const;
|
||||||
@ -96,11 +97,11 @@ namespace dawn_native {
|
|||||||
void APIDestroy();
|
void APIDestroy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DestroyInternal();
|
// Constructor used only for mocking and testing.
|
||||||
|
TextureBase(DeviceBase* device, TextureState state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
virtual void DestroyImpl();
|
|
||||||
|
|
||||||
MaybeError ValidateDestroy() const;
|
MaybeError ValidateDestroy() const;
|
||||||
wgpu::TextureDimension mDimension;
|
wgpu::TextureDimension mDimension;
|
||||||
@ -136,6 +137,10 @@ namespace dawn_native {
|
|||||||
uint32_t GetLayerCount() const;
|
uint32_t GetLayerCount() const;
|
||||||
const SubresourceRange& GetSubresourceRange() const;
|
const SubresourceRange& GetSubresourceRange() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor used only for mocking and testing.
|
||||||
|
TextureViewBase(TextureBase* texture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
@ -647,10 +647,9 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
DestroyInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyApiObjectImpl() {
|
||||||
Device* device = ToBackend(GetDevice());
|
Device* device = ToBackend(GetDevice());
|
||||||
|
|
||||||
// In PIX's D3D12-only mode, there is no way to determine frame boundaries
|
// In PIX's D3D12-only mode, there is no way to determine frame boundaries
|
||||||
|
@ -105,7 +105,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
void SetLabelImpl() override;
|
void SetLabelImpl() override;
|
||||||
void DestroyImpl() override;
|
void DestroyApiObjectImpl() override;
|
||||||
|
|
||||||
MaybeError ClearTexture(CommandRecordingContext* commandContext,
|
MaybeError ClearTexture(CommandRecordingContext* commandContext,
|
||||||
const SubresourceRange& range,
|
const SubresourceRange& range,
|
||||||
|
@ -66,7 +66,7 @@ namespace dawn_native { namespace metal {
|
|||||||
void InitializeAsWrapping(const TextureDescriptor* descriptor,
|
void InitializeAsWrapping(const TextureDescriptor* descriptor,
|
||||||
NSPRef<id<MTLTexture>> wrapped);
|
NSPRef<id<MTLTexture>> wrapped);
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyApiObjectImpl() override;
|
||||||
|
|
||||||
MaybeError ClearTexture(CommandRecordingContext* commandContext,
|
MaybeError ClearTexture(CommandRecordingContext* commandContext,
|
||||||
const SubresourceRange& range,
|
const SubresourceRange& range,
|
||||||
|
@ -493,10 +493,9 @@ namespace dawn_native { namespace metal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
DestroyInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyApiObjectImpl() {
|
||||||
mMtlTexture = nullptr;
|
mMtlTexture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,10 +188,9 @@ namespace dawn_native { namespace opengl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
DestroyInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyApiObjectImpl() {
|
||||||
if (GetTextureState() == TextureState::OwnedInternal) {
|
if (GetTextureState() == TextureState::OwnedInternal) {
|
||||||
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
|
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
|
||||||
mHandle = 0;
|
mHandle = 0;
|
||||||
@ -559,6 +558,9 @@ namespace dawn_native { namespace opengl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureView::~TextureView() {
|
TextureView::~TextureView() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureView::DestroyApiObjectImpl() {
|
||||||
if (mOwnsHandle) {
|
if (mOwnsHandle) {
|
||||||
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
|
ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ namespace dawn_native { namespace opengl {
|
|||||||
private:
|
private:
|
||||||
~Texture() override;
|
~Texture() override;
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyApiObjectImpl() override;
|
||||||
MaybeError ClearTexture(const SubresourceRange& range, TextureBase::ClearValue clearValue);
|
MaybeError ClearTexture(const SubresourceRange& range, TextureBase::ClearValue clearValue);
|
||||||
|
|
||||||
GLuint mHandle;
|
GLuint mHandle;
|
||||||
@ -57,6 +57,7 @@ namespace dawn_native { namespace opengl {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
~TextureView() override;
|
~TextureView() override;
|
||||||
|
void DestroyApiObjectImpl() override;
|
||||||
|
|
||||||
GLuint mHandle;
|
GLuint mHandle;
|
||||||
GLenum mTarget;
|
GLenum mTarget;
|
||||||
|
@ -792,12 +792,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
mSignalSemaphore = VK_NULL_HANDLE;
|
mSignalSemaphore = VK_NULL_HANDLE;
|
||||||
|
|
||||||
// Destroy the texture so it can't be used again
|
// Destroy the texture so it can't be used again
|
||||||
DestroyInternal();
|
DestroyApiObject();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
DestroyInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::SetLabelHelper(const char* prefix) {
|
void Texture::SetLabelHelper(const char* prefix) {
|
||||||
@ -809,7 +808,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
SetLabelHelper("Dawn_InternalTexture");
|
SetLabelHelper("Dawn_InternalTexture");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyApiObjectImpl() {
|
||||||
if (GetTextureState() == TextureState::OwnedInternal) {
|
if (GetTextureState() == TextureState::OwnedInternal) {
|
||||||
Device* device = ToBackend(GetDevice());
|
Device* device = ToBackend(GetDevice());
|
||||||
|
|
||||||
@ -1300,6 +1299,9 @@ namespace dawn_native { namespace vulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureView::~TextureView() {
|
TextureView::~TextureView() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureView::DestroyApiObjectImpl() {
|
||||||
Device* device = ToBackend(GetTexture()->GetDevice());
|
Device* device = ToBackend(GetTexture()->GetDevice());
|
||||||
|
|
||||||
if (mHandle != VK_NULL_HANDLE) {
|
if (mHandle != VK_NULL_HANDLE) {
|
||||||
|
@ -107,7 +107,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
external_memory::Service* externalMemoryService);
|
external_memory::Service* externalMemoryService);
|
||||||
void InitializeForSwapChain(VkImage nativeImage);
|
void InitializeForSwapChain(VkImage nativeImage);
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyApiObjectImpl() override;
|
||||||
MaybeError ClearTexture(CommandRecordingContext* recordingContext,
|
MaybeError ClearTexture(CommandRecordingContext* recordingContext,
|
||||||
const SubresourceRange& range,
|
const SubresourceRange& range,
|
||||||
TextureBase::ClearValue);
|
TextureBase::ClearValue);
|
||||||
@ -176,6 +176,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
~TextureView() override;
|
~TextureView() override;
|
||||||
|
void DestroyApiObjectImpl() override;
|
||||||
using TextureViewBase::TextureViewBase;
|
using TextureViewBase::TextureViewBase;
|
||||||
MaybeError Initialize(const TextureViewDescriptor* descriptor);
|
MaybeError Initialize(const TextureViewDescriptor* descriptor);
|
||||||
|
|
||||||
|
@ -146,6 +146,7 @@ source_set("dawn_native_mocks_sources") {
|
|||||||
"unittests/native/mocks/BindGroupMock.h",
|
"unittests/native/mocks/BindGroupMock.h",
|
||||||
"unittests/native/mocks/ComputePipelineMock.h",
|
"unittests/native/mocks/ComputePipelineMock.h",
|
||||||
"unittests/native/mocks/DeviceMock.h",
|
"unittests/native/mocks/DeviceMock.h",
|
||||||
|
"unittests/native/mocks/ExternalTextureMock.h",
|
||||||
"unittests/native/mocks/PipelineLayoutMock.h",
|
"unittests/native/mocks/PipelineLayoutMock.h",
|
||||||
"unittests/native/mocks/QuerySetMock.h",
|
"unittests/native/mocks/QuerySetMock.h",
|
||||||
"unittests/native/mocks/RenderPipelineMock.h",
|
"unittests/native/mocks/RenderPipelineMock.h",
|
||||||
@ -153,6 +154,7 @@ source_set("dawn_native_mocks_sources") {
|
|||||||
"unittests/native/mocks/ShaderModuleMock.cpp",
|
"unittests/native/mocks/ShaderModuleMock.cpp",
|
||||||
"unittests/native/mocks/ShaderModuleMock.h",
|
"unittests/native/mocks/ShaderModuleMock.h",
|
||||||
"unittests/native/mocks/SwapChainMock.h",
|
"unittests/native/mocks/SwapChainMock.h",
|
||||||
|
"unittests/native/mocks/TextureMock.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,14 @@
|
|||||||
#include "mocks/BufferMock.h"
|
#include "mocks/BufferMock.h"
|
||||||
#include "mocks/ComputePipelineMock.h"
|
#include "mocks/ComputePipelineMock.h"
|
||||||
#include "mocks/DeviceMock.h"
|
#include "mocks/DeviceMock.h"
|
||||||
|
#include "mocks/ExternalTextureMock.h"
|
||||||
#include "mocks/PipelineLayoutMock.h"
|
#include "mocks/PipelineLayoutMock.h"
|
||||||
#include "mocks/QuerySetMock.h"
|
#include "mocks/QuerySetMock.h"
|
||||||
#include "mocks/RenderPipelineMock.h"
|
#include "mocks/RenderPipelineMock.h"
|
||||||
#include "mocks/SamplerMock.h"
|
#include "mocks/SamplerMock.h"
|
||||||
#include "mocks/ShaderModuleMock.h"
|
#include "mocks/ShaderModuleMock.h"
|
||||||
#include "mocks/SwapChainMock.h"
|
#include "mocks/SwapChainMock.h"
|
||||||
|
#include "mocks/TextureMock.h"
|
||||||
#include "tests/DawnNativeTest.h"
|
#include "tests/DawnNativeTest.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
|
||||||
@ -44,6 +46,16 @@ namespace dawn_native { namespace {
|
|||||||
mDevice.SetToggle(Toggle::SkipValidation, true);
|
mDevice.SetToggle(Toggle::SkipValidation, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<TextureMock> GetTexture() {
|
||||||
|
if (mTexture != nullptr) {
|
||||||
|
return mTexture;
|
||||||
|
}
|
||||||
|
mTexture =
|
||||||
|
AcquireRef(new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal));
|
||||||
|
EXPECT_CALL(*mTexture.Get(), DestroyApiObjectImpl).Times(1);
|
||||||
|
return mTexture;
|
||||||
|
}
|
||||||
|
|
||||||
Ref<PipelineLayoutMock> GetPipelineLayout() {
|
Ref<PipelineLayoutMock> GetPipelineLayout() {
|
||||||
if (mPipelineLayout != nullptr) {
|
if (mPipelineLayout != nullptr) {
|
||||||
return mPipelineLayout;
|
return mPipelineLayout;
|
||||||
@ -85,6 +97,7 @@ namespace dawn_native { namespace {
|
|||||||
|
|
||||||
// The following lazy-initialized objects are used to facilitate creation of dependent
|
// The following lazy-initialized objects are used to facilitate creation of dependent
|
||||||
// objects under test.
|
// objects under test.
|
||||||
|
Ref<TextureMock> mTexture;
|
||||||
Ref<PipelineLayoutMock> mPipelineLayout;
|
Ref<PipelineLayoutMock> mPipelineLayout;
|
||||||
Ref<ShaderModuleMock> mVsModule;
|
Ref<ShaderModuleMock> mVsModule;
|
||||||
Ref<ShaderModuleMock> mCsModule;
|
Ref<ShaderModuleMock> mCsModule;
|
||||||
@ -237,6 +250,24 @@ namespace dawn_native { namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyObjectTests, ExternalTextureExplicit) {
|
||||||
|
ExternalTextureMock externalTextureMock(&mDevice);
|
||||||
|
EXPECT_CALL(externalTextureMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(externalTextureMock.IsAlive());
|
||||||
|
externalTextureMock.DestroyApiObject();
|
||||||
|
EXPECT_FALSE(externalTextureMock.IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can use an actual ExternalTexture object to test the implicit case.
|
||||||
|
TEST_F(DestroyObjectTests, ExternalTextureImplicit) {
|
||||||
|
ExternalTextureDescriptor desc = {};
|
||||||
|
Ref<ExternalTextureBase> externalTexture;
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(externalTexture, mDevice.CreateExternalTexture(&desc));
|
||||||
|
|
||||||
|
EXPECT_TRUE(externalTexture->IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DestroyObjectTests, PipelineLayoutExplicit) {
|
TEST_F(DestroyObjectTests, PipelineLayoutExplicit) {
|
||||||
PipelineLayoutMock pipelineLayoutMock(&mDevice);
|
PipelineLayoutMock pipelineLayoutMock(&mDevice);
|
||||||
EXPECT_CALL(pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
|
||||||
@ -409,6 +440,84 @@ namespace dawn_native { namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyObjectTests, TextureExplicit) {
|
||||||
|
{
|
||||||
|
TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
|
||||||
|
EXPECT_CALL(textureMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(textureMock.IsAlive());
|
||||||
|
textureMock.DestroyApiObject();
|
||||||
|
EXPECT_FALSE(textureMock.IsAlive());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
|
||||||
|
EXPECT_CALL(textureMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(textureMock.IsAlive());
|
||||||
|
textureMock.DestroyApiObject();
|
||||||
|
EXPECT_FALSE(textureMock.IsAlive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
|
||||||
|
// will also complain if there is a memory leak.
|
||||||
|
TEST_F(DestroyObjectTests, TextureImplicit) {
|
||||||
|
{
|
||||||
|
TextureMock* textureMock =
|
||||||
|
new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
|
||||||
|
EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
{
|
||||||
|
TextureDescriptor desc = {};
|
||||||
|
Ref<TextureBase> texture;
|
||||||
|
EXPECT_CALL(mDevice, CreateTextureImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(textureMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
|
||||||
|
|
||||||
|
EXPECT_TRUE(texture->IsAlive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
TextureMock* textureMock =
|
||||||
|
new TextureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
|
||||||
|
EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
{
|
||||||
|
TextureDescriptor desc = {};
|
||||||
|
Ref<TextureBase> texture;
|
||||||
|
EXPECT_CALL(mDevice, CreateTextureImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(textureMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
|
||||||
|
|
||||||
|
EXPECT_TRUE(texture->IsAlive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyObjectTests, TextureViewExplicit) {
|
||||||
|
TextureViewMock textureViewMock(GetTexture().Get());
|
||||||
|
EXPECT_CALL(textureViewMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(textureViewMock.IsAlive());
|
||||||
|
textureViewMock.DestroyApiObject();
|
||||||
|
EXPECT_FALSE(textureViewMock.IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the reference count on API objects reach 0, they should delete themselves. Note that GTest
|
||||||
|
// will also complain if there is a memory leak.
|
||||||
|
TEST_F(DestroyObjectTests, TextureViewImplicit) {
|
||||||
|
TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
|
||||||
|
EXPECT_CALL(*textureViewMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
{
|
||||||
|
TextureViewDescriptor desc = {};
|
||||||
|
Ref<TextureViewBase> textureView;
|
||||||
|
EXPECT_CALL(mDevice, CreateTextureViewImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(textureViewMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(textureView,
|
||||||
|
mDevice.CreateTextureView(GetTexture().Get(), &desc));
|
||||||
|
|
||||||
|
EXPECT_TRUE(textureView->IsAlive());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Destroying the objects on the mDevice should result in all created objects being destroyed in
|
// Destroying the objects on the mDevice should result in all created objects being destroyed in
|
||||||
// order.
|
// order.
|
||||||
TEST_F(DestroyObjectTests, DestroyObjects) {
|
TEST_F(DestroyObjectTests, DestroyObjects) {
|
||||||
@ -422,6 +531,9 @@ namespace dawn_native { namespace {
|
|||||||
SamplerMock* samplerMock = new SamplerMock(&mDevice);
|
SamplerMock* samplerMock = new SamplerMock(&mDevice);
|
||||||
ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
|
ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
|
||||||
SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
|
SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
|
||||||
|
TextureMock* textureMock =
|
||||||
|
new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
|
||||||
|
TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
|
||||||
{
|
{
|
||||||
InSequence seq;
|
InSequence seq;
|
||||||
EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
|
||||||
@ -431,6 +543,8 @@ namespace dawn_native { namespace {
|
|||||||
EXPECT_CALL(*bindGroupMock, 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(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*textureViewMock, DestroyApiObjectImpl).Times(1);
|
||||||
|
EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
|
||||||
EXPECT_CALL(*querySetMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*querySetMock, DestroyApiObjectImpl).Times(1);
|
||||||
EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
|
||||||
EXPECT_CALL(*bufferMock, DestroyApiObjectImpl).Times(1);
|
EXPECT_CALL(*bufferMock, DestroyApiObjectImpl).Times(1);
|
||||||
@ -484,6 +598,13 @@ namespace dawn_native { namespace {
|
|||||||
EXPECT_TRUE(computePipeline->IsCachedReference());
|
EXPECT_TRUE(computePipeline->IsCachedReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<ExternalTextureBase> externalTexture;
|
||||||
|
{
|
||||||
|
ExternalTextureDescriptor desc = {};
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(externalTexture, mDevice.CreateExternalTexture(&desc));
|
||||||
|
EXPECT_TRUE(externalTexture->IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
Ref<PipelineLayoutBase> pipelineLayout;
|
Ref<PipelineLayoutBase> pipelineLayout;
|
||||||
{
|
{
|
||||||
PipelineLayoutDescriptor desc = {};
|
PipelineLayoutDescriptor desc = {};
|
||||||
@ -560,17 +681,39 @@ namespace dawn_native { namespace {
|
|||||||
EXPECT_TRUE(swapChain->IsAlive());
|
EXPECT_TRUE(swapChain->IsAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<TextureBase> texture;
|
||||||
|
{
|
||||||
|
TextureDescriptor desc = {};
|
||||||
|
EXPECT_CALL(mDevice, CreateTextureImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(textureMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(texture, mDevice.CreateTexture(&desc));
|
||||||
|
EXPECT_TRUE(texture->IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<TextureViewBase> textureView;
|
||||||
|
{
|
||||||
|
TextureViewDescriptor desc = {};
|
||||||
|
EXPECT_CALL(mDevice, CreateTextureViewImpl)
|
||||||
|
.WillOnce(Return(ByMove(AcquireRef(textureViewMock))));
|
||||||
|
DAWN_ASSERT_AND_ASSIGN(textureView,
|
||||||
|
mDevice.CreateTextureView(GetTexture().Get(), &desc));
|
||||||
|
EXPECT_TRUE(textureView->IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
mDevice.DestroyObjects();
|
mDevice.DestroyObjects();
|
||||||
EXPECT_FALSE(bindGroup->IsAlive());
|
EXPECT_FALSE(bindGroup->IsAlive());
|
||||||
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
EXPECT_FALSE(bindGroupLayout->IsAlive());
|
||||||
EXPECT_FALSE(buffer->IsAlive());
|
EXPECT_FALSE(buffer->IsAlive());
|
||||||
EXPECT_FALSE(computePipeline->IsAlive());
|
EXPECT_FALSE(computePipeline->IsAlive());
|
||||||
|
EXPECT_FALSE(externalTexture->IsAlive());
|
||||||
EXPECT_FALSE(pipelineLayout->IsAlive());
|
EXPECT_FALSE(pipelineLayout->IsAlive());
|
||||||
EXPECT_FALSE(querySet->IsAlive());
|
EXPECT_FALSE(querySet->IsAlive());
|
||||||
EXPECT_FALSE(renderPipeline->IsAlive());
|
EXPECT_FALSE(renderPipeline->IsAlive());
|
||||||
EXPECT_FALSE(sampler->IsAlive());
|
EXPECT_FALSE(sampler->IsAlive());
|
||||||
EXPECT_FALSE(shaderModule->IsAlive());
|
EXPECT_FALSE(shaderModule->IsAlive());
|
||||||
EXPECT_FALSE(swapChain->IsAlive());
|
EXPECT_FALSE(swapChain->IsAlive());
|
||||||
|
EXPECT_FALSE(texture->IsAlive());
|
||||||
|
EXPECT_FALSE(textureView->IsAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::
|
}} // namespace dawn_native::
|
||||||
|
36
src/tests/unittests/native/mocks/ExternalTextureMock.h
Normal file
36
src/tests/unittests/native/mocks/ExternalTextureMock.h
Normal file
@ -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_EXTERNALTEXTURE_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_EXTERNALTEXTURE_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/ExternalTexture.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class ExternalTextureMock : public ExternalTextureBase {
|
||||||
|
public:
|
||||||
|
ExternalTextureMock(DeviceBase* device) : ExternalTextureBase(device) {
|
||||||
|
}
|
||||||
|
~ExternalTextureMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_EXTERNALTEXTURE_MOCK_H_
|
46
src/tests/unittests/native/mocks/TextureMock.h
Normal file
46
src/tests/unittests/native/mocks/TextureMock.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// 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_TEXTURE_MOCK_H_
|
||||||
|
#define TESTS_UNITTESTS_NATIVE_MOCKS_TEXTURE_MOCK_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/Texture.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class TextureMock : public TextureBase {
|
||||||
|
public:
|
||||||
|
TextureMock(DeviceBase* device, TextureBase::TextureState state)
|
||||||
|
: TextureBase(device, state) {
|
||||||
|
}
|
||||||
|
~TextureMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextureViewMock : public TextureViewBase {
|
||||||
|
public:
|
||||||
|
TextureViewMock(TextureBase* texture) : TextureViewBase(texture) {
|
||||||
|
}
|
||||||
|
~TextureViewMock() override = default;
|
||||||
|
|
||||||
|
MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // TESTS_UNITTESTS_NATIVE_MOCKS_TEXTURE_MOCK_H_
|
Loading…
x
Reference in New Issue
Block a user