Make the SwapChain interface match webgpu.h

This changes the methods of Dawn's SwapChain to match webgpu.h, namely
Present() now doesn't take arguments, and GetNextTexture() is replaced
with GetCurrentTextureView().

BUG=dawn:269

Change-Id: Ia0debefb170caf799c3310b1dad5535c4c5f59ca
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13441
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/dawn.json b/dawn.json
index 4886a70..8101144 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1188,16 +1188,8 @@
                     {"name": "height", "type": "uint32_t"}
                 ]
             },
-            {
-                "name": "get next texture",
-                "returns": "texture"
-            },
-            {
-                "name": "present",
-                "args": [
-                    {"name": "texture", "type": "texture"}
-                ]
-            }
+            {"name": "get current texture view", "returns": "texture view"},
+            {"name": "present"}
         ]
     },
     "swap chain descriptor": {
diff --git a/examples/Animometer.cpp b/examples/Animometer.cpp
index 70b0773..1cc5eaa 100644
--- a/examples/Animometer.cpp
+++ b/examples/Animometer.cpp
@@ -143,7 +143,7 @@
 }
 
 void frame() {
-    wgpu::Texture backbuffer = swapchain.GetNextTexture();
+    wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
 
     static int f = 0;
     f++;
@@ -152,7 +152,7 @@
     }
     ubo.SetSubData(0, kNumTriangles * sizeof(ShaderData), shaderData.data());
 
-    utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateView()});
+    utils::ComboRenderPassDescriptor renderPass({backbufferView});
     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
     {
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
@@ -169,7 +169,7 @@
 
     wgpu::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
-    swapchain.Present(backbuffer);
+    swapchain.Present();
     DoFlush();
     fprintf(stderr, "frame %i\n", f);
 }
diff --git a/examples/CHelloTriangle.cpp b/examples/CHelloTriangle.cpp
index 2082b9e..d457e38 100644
--- a/examples/CHelloTriangle.cpp
+++ b/examples/CHelloTriangle.cpp
@@ -125,8 +125,7 @@
 }
 
 void frame() {
-    WGPUTexture backbuffer = wgpuSwapChainGetNextTexture(swapchain);
-    WGPUTextureView backbufferView = wgpuTextureCreateView(backbuffer, nullptr);
+    WGPUTextureView backbufferView = wgpuSwapChainGetCurrentTextureView(swapchain);
     WGPURenderPassDescriptor renderpassInfo;
     renderpassInfo.nextInChain = nullptr;
     renderpassInfo.label = nullptr;
@@ -157,7 +156,7 @@
 
     wgpuQueueSubmit(queue, 1, &commands);
     wgpuCommandBufferRelease(commands);
-    wgpuSwapChainPresent(swapchain, backbuffer);
+    wgpuSwapChainPresent(swapchain);
     wgpuTextureViewRelease(backbufferView);
 
     DoFlush();
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index 185fe0c..1495387 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -261,7 +261,7 @@
     }
 }
 
-wgpu::CommandBuffer createCommandBuffer(const wgpu::Texture backbuffer, size_t i) {
+wgpu::CommandBuffer createCommandBuffer(const wgpu::TextureView backbufferView, size_t i) {
     auto& bufferDst = particleBuffers[(i + 1) % 2];
     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
 
@@ -274,7 +274,7 @@
     }
 
     {
-        utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateView()}, depthStencilView);
+        utils::ComboRenderPassDescriptor renderPass({backbufferView}, depthStencilView);
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
         pass.SetPipeline(renderPipeline);
         pass.SetVertexBuffer(0, bufferDst);
@@ -300,11 +300,11 @@
 }
 
 void frame() {
-    wgpu::Texture backbuffer = swapchain.GetNextTexture();
+    wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
 
-    wgpu::CommandBuffer commandBuffer = createCommandBuffer(backbuffer, pingpong);
+    wgpu::CommandBuffer commandBuffer = createCommandBuffer(backbufferView, pingpong);
     queue.Submit(1, &commandBuffer);
-    swapchain.Present(backbuffer);
+    swapchain.Present();
     DoFlush();
 
     pingpong = (pingpong + 1) % 2;
diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp
index 0568278..05e7a5c 100644
--- a/examples/CppHelloTriangle.cpp
+++ b/examples/CppHelloTriangle.cpp
@@ -153,8 +153,8 @@
     s.b += 0.02f;
     if (s.b >= 1.0f) {s.b = 0.0f;}
 
-    wgpu::Texture backbuffer = swapchain.GetNextTexture();
-    utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateView()}, depthStencilView);
+    wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
+    utils::ComboRenderPassDescriptor renderPass({backbufferView}, depthStencilView);
 
     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
     {
@@ -169,7 +169,7 @@
 
     wgpu::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
-    swapchain.Present(backbuffer);
+    swapchain.Present();
     DoFlush();
 }
 
diff --git a/examples/CubeReflection.cpp b/examples/CubeReflection.cpp
index 2531af77..2102783 100644
--- a/examples/CubeReflection.cpp
+++ b/examples/CubeReflection.cpp
@@ -264,8 +264,8 @@
 
     cameraBuffer.SetSubData(0, sizeof(CameraData), &cameraData);
 
-    wgpu::Texture backbuffer = swapchain.GetNextTexture();
-    utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateView()}, depthStencilView);
+    wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
+    utils::ComboRenderPassDescriptor renderPass({backbufferView}, depthStencilView);
 
     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
     {
@@ -292,7 +292,7 @@
 
     wgpu::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
-    swapchain.Present(backbuffer);
+    swapchain.Present();
     DoFlush();
 }
 
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index e9907b9..37549d3 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -99,12 +99,21 @@
                                   static_cast<WGPUTextureUsage>(allowedUsage), width, height);
     }
 
-    TextureBase* SwapChainBase::GetNextTexture() {
-        if (GetDevice()->ConsumedError(ValidateGetNextTexture())) {
-            return TextureBase::MakeError(GetDevice());
+    TextureViewBase* SwapChainBase::GetCurrentTextureView() {
+        if (GetDevice()->ConsumedError(ValidateGetCurrentTextureView())) {
+            return TextureViewBase::MakeError(GetDevice());
         }
         ASSERT(!IsError());
 
+        // Return the same current texture view until Present is called.
+        if (mCurrentTextureView.Get() != nullptr) {
+            // Calling GetCurrentTextureView always returns a new reference so add it even when
+            // reuse the existing texture view.
+            mCurrentTextureView->Reference();
+            return mCurrentTextureView.Get();
+        }
+
+        // Create the backing texture and the view.
         TextureDescriptor descriptor;
         descriptor.dimension = wgpu::TextureDimension::e2D;
         descriptor.size.width = mWidth;
@@ -116,21 +125,28 @@
         descriptor.mipLevelCount = 1;
         descriptor.usage = mAllowedUsage;
 
-        auto* texture = GetNextTextureImpl(&descriptor);
-        mLastNextTexture = texture;
-        return texture;
+        // Get the texture but remove the external refcount because it is never passed outside
+        // of dawn_native
+        mCurrentTexture = AcquireRef(GetNextTextureImpl(&descriptor));
+
+        mCurrentTextureView = mCurrentTexture->CreateView(nullptr);
+        return mCurrentTextureView.Get();
     }
 
-    void SwapChainBase::Present(TextureBase* texture) {
-        if (GetDevice()->ConsumedError(ValidatePresent(texture))) {
+    void SwapChainBase::Present() {
+        if (GetDevice()->ConsumedError(ValidatePresent())) {
             return;
         }
         ASSERT(!IsError());
 
-        if (GetDevice()->ConsumedError(OnBeforePresent(texture)))
+        if (GetDevice()->ConsumedError(OnBeforePresent(mCurrentTexture.Get()))) {
             return;
+        }
 
         mImplementation.Present(mImplementation.userData);
+
+        mCurrentTexture = nullptr;
+        mCurrentTextureView = nullptr;
     }
 
     const DawnSwapChainImplementation& SwapChainBase::GetImplementation() {
@@ -154,7 +170,7 @@
         return {};
     }
 
-    MaybeError SwapChainBase::ValidateGetNextTexture() const {
+    MaybeError SwapChainBase::ValidateGetCurrentTextureView() const {
         DAWN_TRY(GetDevice()->ValidateObject(this));
 
         if (mWidth == 0) {
@@ -165,14 +181,12 @@
         return {};
     }
 
-    MaybeError SwapChainBase::ValidatePresent(TextureBase* texture) const {
+    MaybeError SwapChainBase::ValidatePresent() const {
         DAWN_TRY(GetDevice()->ValidateObject(this));
-        DAWN_TRY(GetDevice()->ValidateObject(texture));
 
-        // This also checks that the texture is valid since mLastNextTexture is always valid.
-        if (texture != mLastNextTexture) {
+        if (mCurrentTextureView.Get() == nullptr) {
             return DAWN_VALIDATION_ERROR(
-                "Tried to present something other than the last NextTexture");
+                "Cannot call present without a GetCurrentTextureView call for this frame");
         }
 
         return {};
diff --git a/src/dawn_native/SwapChain.h b/src/dawn_native/SwapChain.h
index 0ae6a16..7742293 100644
--- a/src/dawn_native/SwapChain.h
+++ b/src/dawn_native/SwapChain.h
@@ -39,8 +39,8 @@
                        wgpu::TextureUsage allowedUsage,
                        uint32_t width,
                        uint32_t height);
-        TextureBase* GetNextTexture();
-        void Present(TextureBase* texture);
+        TextureViewBase* GetCurrentTextureView();
+        void Present();
 
       protected:
         SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag);
@@ -54,15 +54,16 @@
                                      wgpu::TextureUsage allowedUsage,
                                      uint32_t width,
                                      uint32_t height) const;
-        MaybeError ValidateGetNextTexture() const;
-        MaybeError ValidatePresent(TextureBase* texture) const;
+        MaybeError ValidateGetCurrentTextureView() const;
+        MaybeError ValidatePresent() const;
 
         DawnSwapChainImplementation mImplementation = {};
         wgpu::TextureFormat mFormat = {};
         wgpu::TextureUsage mAllowedUsage;
         uint32_t mWidth = 0;
         uint32_t mHeight = 0;
-        TextureBase* mLastNextTexture = nullptr;
+        Ref<TextureBase> mCurrentTexture;
+        Ref<TextureViewBase> mCurrentTextureView;
     };
 
 }  // namespace dawn_native