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";