Title: [261089] trunk
Revision
261089
Author
[email protected]
Date
2020-05-04 11:00:42 -0700 (Mon, 04 May 2020)

Log Message

WebGPU: copyTextureToTexture() has an implementation bug (src copy view info is used also as dst)
https://bugs.webkit.org/show_bug.cgi?id=211303

Patch by Guillem Vinals <[email protected]> on 2020-05-04
Reviewed by Daniel Bates.

Source/WebCore:

The source copy information is also used as the destination copy information.

Test: webgpu/blit-commands-texture-to-texture.html

* platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm:
(WebCore::GPUCommandBuffer::copyTextureToTexture):

LayoutTests:

* webgpu/blit-commands-texture-to-texture-expected.html: Added.
* webgpu/blit-commands-texture-to-texture.html: Added.
* webgpu/js/webgpu-functions.js:
(drawGreenMipChainOnRedBackgroundInSoftware):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (261088 => 261089)


--- trunk/LayoutTests/ChangeLog	2020-05-04 16:55:07 UTC (rev 261088)
+++ trunk/LayoutTests/ChangeLog	2020-05-04 18:00:42 UTC (rev 261089)
@@ -1,3 +1,15 @@
+2020-05-04  Guillem Vinals  <[email protected]>
+
+        WebGPU: copyTextureToTexture() has an implementation bug (src copy view info is used also as dst)
+        https://bugs.webkit.org/show_bug.cgi?id=211303
+
+        Reviewed by Daniel Bates.
+
+        * webgpu/blit-commands-texture-to-texture-expected.html: Added.
+        * webgpu/blit-commands-texture-to-texture.html: Added.
+        * webgpu/js/webgpu-functions.js:
+        (drawGreenMipChainOnRedBackgroundInSoftware):
+
 2020-05-04  Per Arne Vollan  <[email protected]>
 
         Unreviewed test gardening.

Added: trunk/LayoutTests/webgpu/blit-commands-texture-to-texture-expected.html (0 => 261089)


--- trunk/LayoutTests/webgpu/blit-commands-texture-to-texture-expected.html	                        (rev 0)
+++ trunk/LayoutTests/webgpu/blit-commands-texture-to-texture-expected.html	2020-05-04 18:00:42 UTC (rev 261089)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Reference File</title>
+<script src=""
+<p>Pass if square canvas below shows a green mip chain on a red background.</p>
+<canvas width="512" height="512"></canvas>
+<script>
+const canvas = document.querySelector("canvas");
+drawGreenMipChainOnRedBackgroundInSoftware(canvas);
+</script>

Added: trunk/LayoutTests/webgpu/blit-commands-texture-to-texture.html (0 => 261089)


--- trunk/LayoutTests/webgpu/blit-commands-texture-to-texture.html	                        (rev 0)
+++ trunk/LayoutTests/webgpu/blit-commands-texture-to-texture.html	2020-05-04 18:00:42 UTC (rev 261089)
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Blitting Texture To Texture</title>
+<meta name="assert" content="Blit operations populate a texture correctly (all mip levels).">
+<link rel="match" href=""
+<p>Pass if square canvas below shows a green mip chain on a red background.</p>
+<canvas width="512" height="512"></canvas>
+<body>
+<script src=""
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function loadTextureFromCanvas2d(device, canvas2d) {
+    const textureSize = {
+        width:  canvas2d.width,
+        height: canvas2d.height,
+        depth:  1
+    };
+
+    // Mipmap count
+    let maxResolution = Math.max(canvas2d.width, canvas2d.height);
+    let mipLevelCount = Math.ceil(Math.log2(maxResolution));
+    if (mipLevelCount < 1) mipLevelCount = 1;
+
+    const textureDescriptor = {
+        size: textureSize,
+        arrayLayerCount: 2,
+        mipLevelCount: mipLevelCount,
+        sampleCount: 1,
+        dimension: "2d",
+        format: "rgba8unorm",
+        usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED 
+    };
+
+    // Create texture and also add the descriptor
+    const texture = device.createTexture(textureDescriptor);
+    texture.descriptor = textureDescriptor;
+
+    // Texture data 
+    const context2d = canvas2d.getContext('2d');
+    const imageData = context2d.getImageData(0, 0, canvas2d.width, canvas2d.height);
+
+    const textureDataBufferDescriptor = {
+        size: imageData.data.length,
+        usage: GPUBufferUsage.COPY_SRC
+    };
+    const [textureDataBuffer, textureArrayBuffer] = device.createBufferMapped(textureDataBufferDescriptor);
+    
+    const textureWriteArray = new Uint8Array(textureArrayBuffer);
+    textureWriteArray.set(imageData.data);
+    textureDataBuffer.unmap();
+
+    const dataCopyView = {
+        buffer: textureDataBuffer,
+        offset: 0,
+        rowPitch: canvas2d.width * 4,
+        imageHeight: 0
+    };
+    const textureCopyView = {
+        texture: texture,
+        mipLevel: 0,
+        arrayLayer: 0,
+        origin: { x: 0, y: 0, z: 0 }
+    };
+
+    const blitCommandEncoder = device.createCommandEncoder();
+    blitCommandEncoder.copyBufferToTexture(dataCopyView, textureCopyView, textureSize);
+    device.getQueue().submit([blitCommandEncoder.finish()]);
+
+    return texture;
+}
+
+async function test(device) {
+    const canvas2d  = await document.querySelector("canvas");
+    const context2d = canvas2d.getContext('2d');
+
+    // textureA (layer 0, mip 0): Green
+    context2d.fillStyle = 'rgb(0, 255, 0)';
+    context2d.fillRect(0, 0, canvas2d.width, canvas2d.height);
+    const textureA = loadTextureFromCanvas2d(device, canvas2d);
+
+    // textureB (layer 0, mip 0): Red
+    context2d.fillStyle = 'rgb(255, 0, 0)';
+    context2d.fillRect(0, 0, canvas2d.width, canvas2d.height);
+    const textureB = loadTextureFromCanvas2d(device, canvas2d); 
+
+    // Clean canvas to blue
+    context2d.fillStyle = 'rgb(0, 0, 255)';
+    context2d.fillRect(0, 0, canvas2d.width, canvas2d.height);
+
+    // Test copyTextureToTexture
+
+    let size = Object.assign({}, textureA.descriptor.size);
+    let blitCommandEncoder = device.createCommandEncoder();
+    for (var i = 1; i < textureA.descriptor.mipLevelCount; ++i) {
+        size.width  = Math.max(Math.floor(size.width / 2), 1);
+        size.height = Math.max(Math.floor(size.height / 2), 1);
+
+        let srcTextureCopyView = {
+            texture: textureA,
+            mipLevel: 0,
+            arrayLayer: 0,
+            origin: { x: 0, y: 0, z: 0 }
+        };
+        let dstTextureCopyView = {
+            texture: textureA,
+            mipLevel: i,
+            arrayLayer: 1,
+            origin: { x: 0, y: 0, z: 0 }
+        };
+        // Populate textureA (layer 1, mip i)
+        blitCommandEncoder.copyTextureToTexture(srcTextureCopyView, dstTextureCopyView, size);
+
+        srcTextureCopyView = {
+            texture: textureA,
+            mipLevel: i,
+            arrayLayer: 1,
+            origin: { x: 0, y: 0, z: 0 }
+        };
+        dstTextureCopyView = {
+            texture: textureB,
+            mipLevel: 0,
+            arrayLayer: 0,
+            origin: { x: 0, y: size.height, z: 0 }
+        };
+        // Populate textureB (layer 0, mip 0) with textureA (layer 1, mip i)
+        blitCommandEncoder.copyTextureToTexture(srcTextureCopyView, dstTextureCopyView, size);
+    }
+
+    // Render textureB into canvas2d
+
+    const imageDataLengthInBytes = canvas2d.width * canvas2d.height * 4;
+    const bufferDescriptor = {
+        size: imageDataLengthInBytes,
+        usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
+    };
+    const bufferA = device.createBuffer(bufferDescriptor);
+
+    const bufferCopyView = {
+        buffer: bufferA,
+        rowPitch: canvas2d.width * 4,
+        imageHeight: 0
+    };
+    const textureCopyView = {
+        texture: textureB
+    };
+    blitCommandEncoder.copyTextureToBuffer(textureCopyView, bufferCopyView, textureA.descriptor.size);
+
+    device.getQueue().submit([blitCommandEncoder.finish()]);
+
+    await bufferA.mapReadAsync().then(ab => {
+        const array = new Uint8ClampedArray(ab);
+        const resultImageData = new ImageData(array, canvas2d.width, canvas2d.height);
+
+        context2d.putImageData(resultImageData, 0, 0);
+
+        bufferA.destroy();
+    });
+}
+
+getBasicDevice().then(function(device) {
+    test(device).then(function() {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }, function(e) {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+}, function() {
+    const canvas2d = document.querySelector("canvas");
+    drawGreenMipChainOnRedBackgroundInSoftware(canvas2d);
+    if (window.testRunner)
+        testRunner.notifyDone();
+});
+</script>
+</body>

Modified: trunk/LayoutTests/webgpu/js/webgpu-functions.js (261088 => 261089)


--- trunk/LayoutTests/webgpu/js/webgpu-functions.js	2020-05-04 16:55:07 UTC (rev 261088)
+++ trunk/LayoutTests/webgpu/js/webgpu-functions.js	2020-05-04 18:00:42 UTC (rev 261089)
@@ -4,6 +4,26 @@
     return device;
 }
 
+function drawGreenMipChainOnRedBackgroundInSoftware(canvas) {
+    const context = canvas.getContext("2d");
+    context.fillStyle = "rgb(255, 0, 0)";
+    context.fillRect(0, 0, canvas.width, canvas.height);
+
+    let maxResolution = Math.max(canvas.width, canvas.height);
+    let mipLevelCount = Math.ceil(Math.log2(maxResolution));
+    if (mipLevelCount < 1) mipLevelCount = 1;
+
+    let width  = canvas.width;
+    let height = canvas.height;
+    for (var i = 1; i < mipLevelCount; ++i) {
+        width  = Math.max(Math.floor(width  / 2), 1);
+        height = Math.max(Math.floor(height / 2), 1);
+        context.fillStyle = "rgb(0, 255, 0)";
+        context.fillRect(0, height, width, height);
+    }
+
+}
+
 function drawWhiteSquareOnBlueBackgroundInSoftware(canvas) {
     const context = canvas.getContext("2d");
     context.fillStyle = "blue";

Modified: trunk/Source/WebCore/ChangeLog (261088 => 261089)


--- trunk/Source/WebCore/ChangeLog	2020-05-04 16:55:07 UTC (rev 261088)
+++ trunk/Source/WebCore/ChangeLog	2020-05-04 18:00:42 UTC (rev 261089)
@@ -1,3 +1,17 @@
+2020-05-04  Guillem Vinals  <[email protected]>
+
+        WebGPU: copyTextureToTexture() has an implementation bug (src copy view info is used also as dst)
+        https://bugs.webkit.org/show_bug.cgi?id=211303
+
+        Reviewed by Daniel Bates.
+
+        The source copy information is also used as the destination copy information.
+
+        Test: webgpu/blit-commands-texture-to-texture.html
+
+        * platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm:
+        (WebCore::GPUCommandBuffer::copyTextureToTexture):
+
 2020-05-04  Antoine Quint  <[email protected]>
 
         Media controls tracks menu shows "Auto" selected instead of track selected via the JS API

Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm (261088 => 261089)


--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm	2020-05-04 16:55:07 UTC (rev 261088)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm	2020-05-04 18:00:42 UTC (rev 261089)
@@ -229,8 +229,8 @@
         sourceOrigin:MTLOriginMake(src.origin.x, src.origin.y, src.origin.z)
         sourceSize:MTLSizeMake(size.width, size.height, size.depth)
         toTexture:dst.texture->platformTexture()
-        destinationSlice:src.arrayLayer
-        destinationLevel:src.mipLevel
+        destinationSlice:dst.arrayLayer
+        destinationLevel:dst.mipLevel
         destinationOrigin:MTLOriginMake(dst.origin.x, dst.origin.y, dst.origin.z)];
 
     END_BLOCK_OBJC_EXCEPTIONS;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to