Make TextureState a bitfield

This makes validating a particular combination of states cost
just a few instructions (and, shift, cmp)

In preparation for tracking whether or not a texture created from
shared texture memory may be used in a submit, add a hasAccess bool

Legacy shared textures have access immediately after creation.

The old OwnedInternal/OwnedExternal enums are removed in favor of
alternative ways of determining when a texture needs to be destroyed.
It really only mattered in the Vulkan backend.

Bug: dawn:1745
Change-Id: Ie7fd17baaed2cf17c48eba8febef5fbb0986d546
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/146000
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.cpp b/src/dawn/native/CopyTextureForBrowserHelper.cpp
index f0bd78c..0ebd828 100644
--- a/src/dawn/native/CopyTextureForBrowserHelper.cpp
+++ b/src/dawn/native/CopyTextureForBrowserHelper.cpp
@@ -600,8 +600,7 @@
                                              const Extent3D& copySize,
                                              const CopyTextureForBrowserOptions& options) {
     DAWN_TRY(device->ValidateObject(destination.texture));
-    DAWN_INVALID_IF(destination.texture->GetTextureState() == TextureBase::TextureState::Destroyed,
-                    "Destination texture %s is destroyed.", destination.texture);
+    DAWN_TRY(destination.texture->ValidateCanUseInSubmitNow());
     DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, destination, copySize),
                      "validating the ImageCopyTexture for the destination");
     DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, destination, copySize),
@@ -652,8 +651,7 @@
                                          const CopyTextureForBrowserOptions* options) {
     // Validate source
     DAWN_TRY(device->ValidateObject(source->texture));
-    DAWN_INVALID_IF(source->texture->GetTextureState() == TextureBase::TextureState::Destroyed,
-                    "Source texture %s is destroyed.", source->texture);
+    DAWN_TRY(source->texture->ValidateCanUseInSubmitNow());
     DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, *source, *copySize),
                      "validating the ImageCopyTexture for the source");
     DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, *source, *copySize),
diff --git a/src/dawn/native/SwapChain.cpp b/src/dawn/native/SwapChain.cpp
index 7726d50..bca79f3 100644
--- a/src/dawn/native/SwapChain.cpp
+++ b/src/dawn/native/SwapChain.cpp
@@ -115,7 +115,7 @@
 
 SwapChainBase::~SwapChainBase() {
     if (mCurrentTexture != nullptr) {
-        ASSERT(mCurrentTexture->GetTextureState() == TextureBase::TextureState::Destroyed);
+        ASSERT(mCurrentTexture->IsDestroyed());
     }
 
     ASSERT(!mAttached);
@@ -223,7 +223,7 @@
         return;
     }
 
-    ASSERT(mCurrentTexture->GetTextureState() == TextureBase::TextureState::Destroyed);
+    ASSERT(mCurrentTexture->IsDestroyed());
     mCurrentTexture = nullptr;
 }
 
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index d742108..92f887f 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -593,9 +593,9 @@
 
 // TextureBase
 
-TextureBase::TextureBase(DeviceBase* device,
-                         const TextureDescriptor* descriptor,
-                         TextureState state)
+TextureBase::TextureState::TextureState() : hasAccess(true), destroyed(false) {}
+
+TextureBase::TextureBase(DeviceBase* device, const TextureDescriptor* descriptor)
     : ApiObjectBase(device, descriptor->label),
       mDimension(descriptor->dimension),
       mFormat(device->GetValidInternalFormat(descriptor->format)),
@@ -604,7 +604,6 @@
       mSampleCount(descriptor->sampleCount),
       mUsage(descriptor->usage),
       mInternalUsage(mUsage),
-      mState(state),
       mFormatEnumForReflection(descriptor->format) {
     uint32_t subresourceCount = mMipLevelCount * GetArrayLayers() * GetAspectCount(mFormat.aspects);
     mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
@@ -665,7 +664,7 @@
       mFormatEnumForReflection(descriptor->format) {}
 
 void TextureBase::DestroyImpl() {
-    mState = TextureState::Destroyed;
+    mState.destroyed = true;
 
     // Destroy all of the views associated with the texture as well.
     mTextureViews.Destroy();
@@ -746,9 +745,14 @@
     mInternalUsage |= usage;
 }
 
-TextureBase::TextureState TextureBase::GetTextureState() const {
+bool TextureBase::IsDestroyed() const {
     ASSERT(!IsError());
-    return mState;
+    return mState.destroyed;
+}
+
+void TextureBase::SetHasAccess(bool hasAccess) {
+    ASSERT(!IsError());
+    mState.hasAccess = hasAccess;
 }
 
 uint32_t TextureBase::GetSubresourceIndex(uint32_t mipLevel,
@@ -794,8 +798,8 @@
 
 MaybeError TextureBase::ValidateCanUseInSubmitNow() const {
     ASSERT(!IsError());
-    DAWN_INVALID_IF(mState == TextureState::Destroyed, "Destroyed texture %s used in a submit.",
-                    this);
+    DAWN_INVALID_IF(mState.destroyed, "Destroyed texture %s used in a submit.", this);
+
     return {};
 }
 
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h
index d920e9a..b12a997 100644
--- a/src/dawn/native/Texture.h
+++ b/src/dawn/native/Texture.h
@@ -57,7 +57,6 @@
 
 class TextureBase : public ApiObjectBase {
   public:
-    enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
     enum class ClearValue { Zero, NonZero };
 
     static TextureBase* MakeError(DeviceBase* device, const TextureDescriptor* descriptor);
@@ -83,7 +82,8 @@
     wgpu::TextureUsage GetUsage() const;
     wgpu::TextureUsage GetInternalUsage() const;
 
-    TextureState GetTextureState() const;
+    bool IsDestroyed() const;
+    void SetHasAccess(bool hasAccess);
     uint32_t GetSubresourceIndex(uint32_t mipLevel, uint32_t arraySlice, Aspect aspect) const;
     bool IsSubresourceContentInitialized(const SubresourceRange& range) const;
     void SetIsSubresourceContentInitialized(bool isInitialized, const SubresourceRange& range);
@@ -128,13 +128,22 @@
     wgpu::TextureUsage APIGetUsage() const;
 
   protected:
-    TextureBase(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
+    TextureBase(DeviceBase* device, const TextureDescriptor* descriptor);
     ~TextureBase() override;
 
     void DestroyImpl() override;
     void AddInternalUsage(wgpu::TextureUsage usage);
 
   private:
+    struct TextureState {
+        TextureState();
+
+        // Indicates whether the texture may access by the GPU in a queue submit.
+        bool hasAccess : 1;
+        // Indicates whether the texture has been destroyed.
+        bool destroyed : 1;
+    };
+
     TextureBase(DeviceBase* device, const TextureDescriptor* descriptor, ObjectBase::ErrorTag tag);
 
     wgpu::TextureDimension mDimension;
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index d43b82d..96a22a2 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -178,8 +178,7 @@
 
 // static
 ResultOrError<Ref<Texture>> Texture::Create(Device* device, const TextureDescriptor* descriptor) {
-    Ref<Texture> texture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal, Kind::Normal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, Kind::Normal));
     DAWN_TRY(texture->InitializeAsInternalTexture());
     return std::move(texture);
 }
@@ -188,8 +187,7 @@
 ResultOrError<Ref<Texture>> Texture::Create(Device* device,
                                             const TextureDescriptor* descriptor,
                                             ComPtr<ID3D11Resource> d3d11Texture) {
-    Ref<Texture> dawnTexture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal, Kind::Normal));
+    Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor, Kind::Normal));
     DAWN_TRY(dawnTexture->InitializeAsSwapChainTexture(std::move(d3d11Texture)));
     return std::move(dawnTexture);
 }
@@ -197,8 +195,7 @@
 ResultOrError<Ref<Texture>> Texture::CreateInternal(Device* device,
                                                     const TextureDescriptor* descriptor,
                                                     Kind kind) {
-    Ref<Texture> texture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal, kind));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, kind));
     DAWN_TRY(texture->InitializeAsInternalTexture());
     return std::move(texture);
 }
@@ -210,9 +207,7 @@
                                                          std::vector<Ref<d3d::Fence>> waitFences,
                                                          bool isSwapChainTexture,
                                                          bool isInitialized) {
-    Ref<Texture> dawnTexture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal, Kind::Normal));
-
+    Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor, Kind::Normal));
     DAWN_TRY(dawnTexture->InitializeAsExternalTexture(std::move(d3dTexture), std::move(waitFences),
                                                       isSwapChainTexture));
 
@@ -351,8 +346,8 @@
     return {};
 }
 
-Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state, Kind kind)
-    : Base(device, descriptor, state), mKind(kind) {}
+Texture::Texture(Device* device, const TextureDescriptor* descriptor, Kind kind)
+    : Base(device, descriptor), mKind(kind) {}
 
 Texture::~Texture() = default;
 
diff --git a/src/dawn/native/d3d11/TextureD3D11.h b/src/dawn/native/d3d11/TextureD3D11.h
index b72cdab..159edac 100644
--- a/src/dawn/native/d3d11/TextureD3D11.h
+++ b/src/dawn/native/d3d11/TextureD3D11.h
@@ -105,7 +105,7 @@
                                                       const TextureDescriptor* descriptor,
                                                       Kind kind);
 
-    Texture(Device* device, const TextureDescriptor* descriptor, TextureState state, Kind kind);
+    Texture(Device* device, const TextureDescriptor* descriptor, Kind kind);
     ~Texture() override;
 
     template <typename T>
diff --git a/src/dawn/native/d3d12/TextureD3D12.cpp b/src/dawn/native/d3d12/TextureD3D12.cpp
index f3efb60..dd99140 100644
--- a/src/dawn/native/d3d12/TextureD3D12.cpp
+++ b/src/dawn/native/d3d12/TextureD3D12.cpp
@@ -163,8 +163,7 @@
 
 // static
 ResultOrError<Ref<Texture>> Texture::Create(Device* device, const TextureDescriptor* descriptor) {
-    Ref<Texture> dawnTexture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
+    Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor));
 
     DAWN_INVALID_IF(dawnTexture->GetFormat().IsMultiPlanar(),
                     "Cannot create a multi-planar formatted texture directly");
@@ -180,9 +179,7 @@
                                                          std::vector<Ref<d3d::Fence>> waitFences,
                                                          bool isSwapChainTexture,
                                                          bool isInitialized) {
-    Ref<Texture> dawnTexture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal));
-
+    Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor));
     DAWN_TRY(dawnTexture->InitializeAsExternalTexture(std::move(d3dTexture), std::move(waitFences),
                                                       isSwapChainTexture));
 
@@ -202,8 +199,7 @@
 ResultOrError<Ref<Texture>> Texture::Create(Device* device,
                                             const TextureDescriptor* descriptor,
                                             ComPtr<ID3D12Resource> d3d12Texture) {
-    Ref<Texture> dawnTexture =
-        AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal));
+    Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor));
     DAWN_TRY(dawnTexture->InitializeAsSwapChainTexture(std::move(d3d12Texture)));
     return std::move(dawnTexture);
 }
@@ -321,8 +317,8 @@
     return {};
 }
 
-Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state)
-    : Base(device, descriptor, state),
+Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+    : Base(device, descriptor),
       mSubresourceStateAndDecay(
           GetFormat().aspects,
           GetArrayLayers(),
diff --git a/src/dawn/native/d3d12/TextureD3D12.h b/src/dawn/native/d3d12/TextureD3D12.h
index 47bcd8e..1bb9a1d 100644
--- a/src/dawn/native/d3d12/TextureD3D12.h
+++ b/src/dawn/native/d3d12/TextureD3D12.h
@@ -94,7 +94,7 @@
   private:
     using Base = d3d::Texture;
 
-    Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
+    Texture(Device* device, const TextureDescriptor* descriptor);
     ~Texture() override;
 
     MaybeError InitializeAsInternalTexture();
diff --git a/src/dawn/native/metal/TextureMTL.h b/src/dawn/native/metal/TextureMTL.h
index cb1769c..cca2985 100644
--- a/src/dawn/native/metal/TextureMTL.h
+++ b/src/dawn/native/metal/TextureMTL.h
@@ -49,7 +49,7 @@
                                        const TextureDescriptor* descriptor,
                                        NSPRef<id<MTLTexture>> wrapped);
 
-    Texture(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
+    Texture(DeviceBase* device, const TextureDescriptor* descriptor);
 
     id<MTLTexture> GetMTLTexture() const;
     IOSurfaceRef GetIOSurface();
diff --git a/src/dawn/native/metal/TextureMTL.mm b/src/dawn/native/metal/TextureMTL.mm
index 28e3d95..f2ff3b0 100644
--- a/src/dawn/native/metal/TextureMTL.mm
+++ b/src/dawn/native/metal/TextureMTL.mm
@@ -721,7 +721,7 @@
 
 // static
 ResultOrError<Ref<Texture>> Texture::Create(Device* device, const TextureDescriptor* descriptor) {
-    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor));
     DAWN_TRY(texture->InitializeAsInternalTexture(descriptor));
     return texture;
 }
@@ -734,8 +734,7 @@
     std::vector<MTLSharedEventAndSignalValue> waitEvents) {
     const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
-    Ref<Texture> texture =
-        AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, textureDescriptor));
     DAWN_TRY(texture->InitializeFromIOSurface(descriptor, textureDescriptor, ioSurface,
                                               std::move(waitEvents)));
     return texture;
@@ -745,7 +744,7 @@
 Ref<Texture> Texture::CreateWrapping(Device* device,
                                      const TextureDescriptor* descriptor,
                                      NSPRef<id<MTLTexture>> wrapped) {
-    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor));
     texture->InitializeAsWrapping(descriptor, std::move(wrapped));
     return texture;
 }
@@ -840,8 +839,7 @@
     Destroy();
 }
 
-Texture::Texture(DeviceBase* dev, const TextureDescriptor* desc, TextureState st)
-    : TextureBase(dev, desc, st) {}
+Texture::Texture(DeviceBase* dev, const TextureDescriptor* desc) : TextureBase(dev, desc) {}
 
 Texture::~Texture() {}
 
@@ -1121,7 +1119,7 @@
     Texture* texture = ToBackend(GetTexture());
 
     // Texture could be destroyed by the time we make a view.
-    if (GetTexture()->GetTextureState() == Texture::TextureState::Destroyed) {
+    if (GetTexture()->IsDestroyed()) {
         return {};
     }
 
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index a69c0b7..40b7f15 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -195,7 +195,7 @@
     return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
-    return AcquireRef(new Texture(this, descriptor, TextureBase::TextureState::OwnedInternal));
+    return AcquireRef(new Texture(this, descriptor));
 }
 ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
     TextureBase* texture,
@@ -469,8 +469,7 @@
 
 ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     TextureDescriptor textureDesc = GetSwapChainBaseTextureDescriptor(this);
-    mTexture = AcquireRef(
-        new Texture(GetDevice(), &textureDesc, TextureBase::TextureState::OwnedInternal));
+    mTexture = AcquireRef(new Texture(GetDevice(), &textureDesc));
     return mTexture;
 }
 
@@ -506,7 +505,7 @@
 
 void Device::ForceEventualFlushOfCommands() {}
 
-Texture::Texture(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state)
-    : TextureBase(device, descriptor, state) {}
+Texture::Texture(DeviceBase* device, const TextureDescriptor* descriptor)
+    : TextureBase(device, descriptor) {}
 
 }  // namespace dawn::native::null
diff --git a/src/dawn/native/null/DeviceNull.h b/src/dawn/native/null/DeviceNull.h
index 97b0bb2..9d96941 100644
--- a/src/dawn/native/null/DeviceNull.h
+++ b/src/dawn/native/null/DeviceNull.h
@@ -317,7 +317,7 @@
 
 class Texture : public TextureBase {
   public:
-    Texture(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
+    Texture(DeviceBase* device, const TextureDescriptor* descriptor);
 };
 
 }  // namespace dawn::native::null
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index a75c7d8..714cd3e 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -327,7 +327,7 @@
 
     // TODO(dawn:803): Validate the OpenGL texture format from the EGLImage against the format
     // in the passed-in TextureDescriptor.
-    return new Texture(this, textureDescriptor, tex, TextureBase::TextureState::OwnedInternal);
+    return new Texture(this, textureDescriptor, tex);
 }
 
 TextureBase* Device::CreateTextureWrappingGLTexture(const ExternalImageDescriptor* descriptor,
@@ -361,7 +361,7 @@
         return nullptr;
     }
 
-    return new Texture(this, textureDescriptor, texture, TextureBase::TextureState::OwnedInternal);
+    return new Texture(this, textureDescriptor, texture);
 }
 
 MaybeError Device::TickImpl() {
diff --git a/src/dawn/native/opengl/TextureGL.cpp b/src/dawn/native/opengl/TextureGL.cpp
index fe8f1fd..2e5c391 100644
--- a/src/dawn/native/opengl/TextureGL.cpp
+++ b/src/dawn/native/opengl/TextureGL.cpp
@@ -182,7 +182,7 @@
 }
 
 Texture::Texture(Device* device, const TextureDescriptor* descriptor)
-    : Texture(device, descriptor, 0, TextureState::OwnedInternal) {
+    : Texture(device, descriptor, 0) {
     const OpenGLFunctions& gl = device->GetGL();
 
     gl.GenTextures(1, &mHandle);
@@ -207,11 +207,8 @@
     return mGenID;
 }
 
-Texture::Texture(Device* device,
-                 const TextureDescriptor* descriptor,
-                 GLuint handle,
-                 TextureState state)
-    : TextureBase(device, descriptor, state), mHandle(handle) {
+Texture::Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle)
+    : TextureBase(device, descriptor), mHandle(handle) {
     mTarget = TargetForTexture(descriptor);
 }
 
@@ -219,7 +216,7 @@
 
 void Texture::DestroyImpl() {
     TextureBase::DestroyImpl();
-    if (GetTextureState() == TextureState::OwnedInternal) {
+    if (mHandle != 0) {
         const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();
         gl.DeleteTextures(1, &mHandle);
         mHandle = 0;
@@ -560,7 +557,7 @@
                                             texture->GetSampleCount());
 
     // Texture could be destroyed by the time we make a view.
-    if (GetTexture()->GetTextureState() == Texture::TextureState::Destroyed) {
+    if (GetTexture()->IsDestroyed()) {
         return;
     }
 
diff --git a/src/dawn/native/opengl/TextureGL.h b/src/dawn/native/opengl/TextureGL.h
index d9bacc8..bdc4fea 100644
--- a/src/dawn/native/opengl/TextureGL.h
+++ b/src/dawn/native/opengl/TextureGL.h
@@ -27,7 +27,7 @@
 class Texture final : public TextureBase {
   public:
     static ResultOrError<Ref<Texture>> Create(Device* device, const TextureDescriptor* descriptor);
-    Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle, TextureState state);
+    Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle);
 
     GLuint GetHandle() const;
     GLenum GetGLTarget() const;
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp
index f1bb1ce..d27f58f 100644
--- a/src/dawn/native/vulkan/TextureVk.cpp
+++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -636,7 +636,7 @@
 ResultOrError<Ref<Texture>> Texture::Create(Device* device,
                                             const TextureDescriptor* descriptor,
                                             VkImageUsageFlags extraUsages) {
-    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, TextureState::OwnedInternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor));
     DAWN_TRY(texture->InitializeAsInternalTexture(extraUsages));
     return std::move(texture);
 }
@@ -647,8 +647,7 @@
     const ExternalImageDescriptorVk* descriptor,
     const TextureDescriptor* textureDescriptor,
     external_memory::Service* externalMemoryService) {
-    Ref<Texture> texture =
-        AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedInternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, textureDescriptor));
     DAWN_TRY(texture->InitializeFromExternal(descriptor, externalMemoryService));
     return texture.Detach();
 }
@@ -657,13 +656,13 @@
 Ref<Texture> Texture::CreateForSwapChain(Device* device,
                                          const TextureDescriptor* descriptor,
                                          VkImage nativeImage) {
-    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, TextureState::OwnedExternal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor));
     texture->InitializeForSwapChain(nativeImage);
     return texture;
 }
 
-Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state)
-    : TextureBase(device, descriptor, state),
+Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+    : TextureBase(device, descriptor),
       mCombinedAspect(ComputeCombinedAspect(device, GetFormat())),
       // A usage of none will make sure the texture is transitioned before its first use as
       // required by the Vulkan spec.
@@ -993,24 +992,29 @@
 }
 
 void Texture::DestroyImpl() {
-    if (GetTextureState() == TextureState::OwnedInternal) {
-        Device* device = ToBackend(GetDevice());
+    Device* device = ToBackend(GetDevice());
 
-        // For textures created from a VkImage, the allocation if kInvalid so the Device knows
-        // to skip the deallocation of the (absence of) VkDeviceMemory.
-        device->GetResourceMemoryAllocator()->Deallocate(&mMemoryAllocation);
-
-        if (mHandle != VK_NULL_HANDLE) {
-            device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
-        }
-
-        if (mExternalAllocation != VK_NULL_HANDLE) {
-            device->GetFencedDeleter()->DeleteWhenUnused(mExternalAllocation);
-        }
-
-        mHandle = VK_NULL_HANDLE;
-        mExternalAllocation = VK_NULL_HANDLE;
+    // The VkImage is only allocated if it is backed by a valid memory allocation.
+    // It is not allocated if the Texture was initialized from an external VkImage,
+    // like a swapchin.
+    bool allocatedVkImage = (mMemoryAllocation.GetInfo().mMethod != AllocationMethod::kInvalid ||
+                             mExternalAllocation != VK_NULL_HANDLE) &&
+                            mHandle != VK_NULL_HANDLE;
+    if (allocatedVkImage) {
+        device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
     }
+
+    // For textures created from a VkImage, the allocation is kInvalid so the Device knows
+    // to skip the deallocation of the (absence of) VkDeviceMemory.
+    device->GetResourceMemoryAllocator()->Deallocate(&mMemoryAllocation);
+
+    if (mExternalAllocation != VK_NULL_HANDLE) {
+        device->GetFencedDeleter()->DeleteWhenUnused(mExternalAllocation);
+    }
+
+    mHandle = VK_NULL_HANDLE;
+    mExternalAllocation = VK_NULL_HANDLE;
+
     // For Vulkan, we currently run the base destruction code after the internal changes because
     // of the dependency on the texture state which the base code overwrites too early.
     TextureBase::DestroyImpl();
@@ -1432,7 +1436,7 @@
     }
 
     // Texture could be destroyed by the time we make a view.
-    if (GetTexture()->GetTextureState() == Texture::TextureState::Destroyed) {
+    if (GetTexture()->IsDestroyed()) {
         return {};
     }
 
diff --git a/src/dawn/native/vulkan/TextureVk.h b/src/dawn/native/vulkan/TextureVk.h
index 0d9a923..6873d2f 100644
--- a/src/dawn/native/vulkan/TextureVk.h
+++ b/src/dawn/native/vulkan/TextureVk.h
@@ -108,7 +108,7 @@
 
   private:
     ~Texture() override;
-    Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
+    Texture(Device* device, const TextureDescriptor* descriptor);
 
     MaybeError InitializeAsInternalTexture(VkImageUsageFlags extraUsages);
     MaybeError InitializeFromExternal(const ExternalImageDescriptorVk* descriptor,
diff --git a/src/dawn/tests/unittests/native/mocks/TextureMock.cpp b/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
index 7150fae..4501321 100644
--- a/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/TextureMock.cpp
@@ -16,10 +16,8 @@
 
 namespace dawn::native {
 
-TextureMock::TextureMock(DeviceMock* device,
-                         const TextureDescriptor* descriptor,
-                         TextureBase::TextureState state)
-    : TextureBase(device, descriptor, state) {
+TextureMock::TextureMock(DeviceMock* device, const TextureDescriptor* descriptor)
+    : TextureBase(device, descriptor) {
     ON_CALL(*this, DestroyImpl).WillByDefault([this] { this->TextureBase::DestroyImpl(); });
 }
 
diff --git a/src/dawn/tests/unittests/native/mocks/TextureMock.h b/src/dawn/tests/unittests/native/mocks/TextureMock.h
index 93a819f..fb89998 100644
--- a/src/dawn/tests/unittests/native/mocks/TextureMock.h
+++ b/src/dawn/tests/unittests/native/mocks/TextureMock.h
@@ -24,9 +24,7 @@
 
 class TextureMock : public TextureBase {
   public:
-    TextureMock(DeviceMock* device,
-                const TextureDescriptor* descriptor,
-                TextureBase::TextureState state = TextureBase::TextureState::OwnedInternal);
+    TextureMock(DeviceMock* device, const TextureDescriptor* descriptor);
     ~TextureMock() override;
 
     MOCK_METHOD(void, DestroyImpl, (), (override));