De-duplicate ExternalTexture Dummy Textures

Avoid recreating 1x1x1 dummy textures for single-plane external texture
by just caching one and reusing it.

Bug: dawn:1082
Change-Id: Ia1fc3520a1b503d4491a256353277400ba90f344
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/80462
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Brandon1 Jones <brandon1.jones@intel.com>
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 233a6de..d03a73f 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -400,6 +400,7 @@
         mPersistentCache = nullptr;
         mEmptyBindGroupLayout = nullptr;
         mInternalPipelineStore = nullptr;
+        mExternalTextureDummyView = nullptr;
 
         AssumeCommandsComplete();
 
@@ -787,6 +788,35 @@
         ASSERT(removedCount == 1);
     }
 
+    ResultOrError<Ref<TextureViewBase>>
+    DeviceBase::GetOrCreateDummyTextureViewForExternalTexture() {
+        if (!mExternalTextureDummyView.Get()) {
+            Ref<TextureBase> externalTextureDummy;
+            TextureDescriptor textureDesc;
+            textureDesc.dimension = wgpu::TextureDimension::e2D;
+            textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+            textureDesc.label = "Dawn_External_Texture_Dummy_Texture";
+            textureDesc.size = {1, 1, 1};
+            textureDesc.usage = wgpu::TextureUsage::TextureBinding;
+
+            DAWN_TRY_ASSIGN(externalTextureDummy, CreateTexture(&textureDesc));
+
+            TextureViewDescriptor textureViewDesc;
+            textureViewDesc.arrayLayerCount = 1;
+            textureViewDesc.aspect = wgpu::TextureAspect::All;
+            textureViewDesc.baseArrayLayer = 0;
+            textureViewDesc.dimension = wgpu::TextureViewDimension::e2D;
+            textureViewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+            textureViewDesc.label = "Dawn_External_Texture_Dummy_Texture_View";
+            textureViewDesc.mipLevelCount = 1;
+
+            DAWN_TRY_ASSIGN(mExternalTextureDummyView,
+                            CreateTextureView(externalTextureDummy.Get(), &textureViewDesc));
+        }
+
+        return mExternalTextureDummyView;
+    }
+
     ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::GetOrCreatePipelineLayout(
         const PipelineLayoutDescriptor* descriptor) {
         PipelineLayoutBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index 36de304..6bb9e2f 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -170,6 +170,8 @@
 
         void UncacheComputePipeline(ComputePipelineBase* obj);
 
+        ResultOrError<Ref<TextureViewBase>> GetOrCreateDummyTextureViewForExternalTexture();
+
         ResultOrError<Ref<PipelineLayoutBase>> GetOrCreatePipelineLayout(
             const PipelineLayoutDescriptor* descriptor);
         void UncachePipelineLayout(PipelineLayoutBase* obj);
@@ -507,6 +509,8 @@
 
         Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
 
+        Ref<TextureViewBase> mExternalTextureDummyView;
+
         std::unique_ptr<DynamicUploader> mDynamicUploader;
         std::unique_ptr<AsyncTaskManager> mAsyncTaskManager;
         Ref<QueueBase> mQueue;
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index fe06ccc..1570825 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -129,26 +129,8 @@
         if (descriptor->plane1) {
             mTextureViews[1] = descriptor->plane1;
         } else {
-            TextureDescriptor textureDesc;
-            textureDesc.dimension = wgpu::TextureDimension::e2D;
-            textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
-            textureDesc.label = "Dawn_External_Texture_Dummy_Texture";
-            textureDesc.size = {1, 1, 1};
-            textureDesc.usage = wgpu::TextureUsage::TextureBinding;
-
-            DAWN_TRY_ASSIGN(mDummyTexture, device->CreateTexture(&textureDesc));
-
-            TextureViewDescriptor textureViewDesc;
-            textureViewDesc.arrayLayerCount = 1;
-            textureViewDesc.aspect = wgpu::TextureAspect::All;
-            textureViewDesc.baseArrayLayer = 0;
-            textureViewDesc.dimension = wgpu::TextureViewDimension::e2D;
-            textureViewDesc.format = wgpu::TextureFormat::RGBA8Unorm;
-            textureViewDesc.label = "Dawn_External_Texture_Dummy_Texture_View";
-            textureViewDesc.mipLevelCount = 1;
-
             DAWN_TRY_ASSIGN(mTextureViews[1],
-                            device->CreateTextureView(mDummyTexture.Get(), &textureViewDesc));
+                            device->GetOrCreateDummyTextureViewForExternalTexture());
         }
 
         // We must create a buffer to store parameters needed by a shader that operates on this