Changeset 246217 in webkit
- Timestamp:
- Jun 7, 2019 3:24:55 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r246214 r246217 1 2019-06-07 Justin Fan <justin_fan@apple.com> 2 3 [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped 4 https://bugs.webkit.org/show_bug.cgi?id=198591 5 6 Reviewed by Myles C. Maxfield. 7 8 GPUBuffer.setSubData has been removed from the WebGPU implementation. 9 GPUDevice.createBufferMapped has been added to the WebGPU implementation. 10 Replace all setSubData calls with appropriate replacements. 11 12 * webgpu/blend-triangle-strip.html: 13 * webgpu/blit-commands.html: 14 * webgpu/buffer-command-buffer-races.html: 15 * webgpu/buffer-resource-triangles.html: 16 * webgpu/compute-squares.html: 17 * webgpu/depth-enabled-triangle-strip.html: 18 * webgpu/draw-indexed-triangles.html: 19 * webgpu/js/webgpu-functions.js: 20 (createBufferWithData): 21 (async.mapWriteDataToBuffer): 22 * webgpu/map-read-buffers-expected.txt: 23 * webgpu/map-read-buffers.html: 24 * webgpu/texture-triangle-strip.html: 25 * webgpu/vertex-buffer-triangle-strip.html: 26 1 27 2019-06-07 Per Arne Vollan <pvollan@apple.com> 2 28 -
trunk/LayoutTests/webgpu/blend-triangle-strip.html
r245905 r246217 76 76 1, -1, 0, 1 77 77 ]); 78 const vertexBuffer = device.createBuffer({ size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 79 vertexBuffer.setSubData(0, vertexData.buffer); 78 const vertexBuffer = createBufferWithData(device, { size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX }, vertexData.buffer); 80 79 81 80 const context = canvas.getContext("gpu"); -
trunk/LayoutTests/webgpu/blit-commands.html
r244442 r246217 31 31 const bufferDescriptor = { 32 32 size: imageData.data.byteLength, 33 usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST33 usage: GPUBufferUsage.TRANSFER_SRC 34 34 }; 35 const bufferA = device.createBuffer(bufferDescriptor); 36 bufferA.setSubData(0, imageData.data.buffer); 35 bufferA = createBufferWithData(device, bufferDescriptor, imageData.data.buffer); 37 36 37 bufferDescriptor.usage |= GPUBufferUsage.TRANSFER_DST; 38 38 const bufferB = device.createBuffer(bufferDescriptor); 39 39 const bufferViewB = { -
trunk/LayoutTests/webgpu/buffer-command-buffer-races.html
r245905 r246217 64 64 65 65 function createAndSetVertexBuffer(device, vertices) { 66 const floatArray = new Float32Array(vertices); 67 const buffer = device.createBuffer({ size: floatArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 68 buffer.setSubData(0, floatArray.buffer); 69 return buffer; 66 const vertexArray = new Float32Array(vertices) 67 return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); 70 68 } 71 69 … … 98 96 const blueArray = new Float32Array(blue); 99 97 100 const colorBuffer = device.createBuffer({ size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_WRITE }); 101 colorBuffer.setSubData(0, greenArray.buffer); 98 const colorBuffer = createBufferWithData(device, { size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE }, greenArray.buffer); 102 99 103 100 const attachment = { … … 127 124 colorBuffer.unmap(); 128 125 129 /* setSubData immediately after a submit should not affect the preceding draw call. */126 /* Writing data immediately after a submit should not affect the preceding draw call. */ 130 127 drawAndSubmitCommands(device, pipeline, attachment, middleBuffer, colorBuffer); 131 colorBuffer.setSubData(0, blueArray.buffer);128 await mapWriteDataToBuffer(colorBuffer, blueArray.buffer); 132 129 133 130 /* destroy right after a submit should not affect the draw call. */ 134 colorBuffer.setSubData(0, greenArray.buffer);131 await mapWriteDataToBuffer(colorBuffer, greenArray.buffer); 135 132 drawAndSubmitCommands(device, pipeline, attachment, upperRightBuffer, colorBuffer); 136 133 upperRightBuffer.destroy(); -
trunk/LayoutTests/webgpu/buffer-resource-triangles.html
r245905 r246217 82 82 83 83 const vertexSize = 4 * 4; 84 const verticesBufferSize = vertexSize * 3;85 84 function createAndUploadVerticesBuffer(device) { 86 const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 87 const arrayBuffer = new Float32Array([ 85 const vertexArray = new Float32Array([ 88 86 0, 1, 0, 1, 89 87 -1, -1, 0, 1, 90 88 1, -1, 0, 1 91 ]).buffer; 92 93 buffer.setSubData(0, arrayBuffer); 94 return buffer; 89 ]); 90 return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); 95 91 } 96 92 -
trunk/LayoutTests/webgpu/compute-squares.html
r244442 r246217 40 40 const pipeline = device.createComputePipeline({ computeStage: computeStageDescriptor }); 41 41 42 const dataBuffer = device.createBuffer({ size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ }); 43 dataBuffer.setSubData(0, data.buffer); 42 const dataBuffer = createBufferWithData(device, { size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ }, data.buffer); 44 43 45 44 const bgLayoutBinding = { binding: dataBinding, visibility: GPUShaderStageBit.COMPUTE, type: "storage-buffer" }; -
trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html
r245905 r246217 49 49 50 50 function createVertexBuffer(device) { 51 const bufferSize = 4 * 4 * 4; 52 const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 53 const arrayBuffer = new Float32Array([ 51 const vertexArray = new Float32Array([ 54 52 // float4 xyzw 55 53 -1, 1, 0, 1, … … 57 55 1, 1, 0, 1, 58 56 1, -1, 0, 1 59 ]).buffer; 60 61 buffer.setSubData(0, arrayBuffer); 62 return buffer; 57 ]); 58 return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); 63 59 } 64 60 -
trunk/LayoutTests/webgpu/draw-indexed-triangles.html
r245905 r246217 54 54 1, -1, 0, 1, 1 55 55 ]); 56 const buffer = device.createBuffer({ size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 57 buffer.setSubData(0, vertexArray.buffer); 58 59 return buffer; 56 return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); 60 57 } 61 58 … … 66 63 const offsetArray = [1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; }); 67 64 const indexArray = new Uint32Array([1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; })); 68 const buffer = device.createBuffer({ size: indexArray.byteLength + indexBufferOffset, usage: GPUBufferUsage.INDEX | GPUBufferUsage.TRANSFER_DST }); 69 buffer.setSubData(indexBufferOffset, indexArray.buffer); 65 const buffer = createBufferWithData( 66 device, 67 { 68 size: indexArray.byteLength + indexBufferOffset, 69 usage: GPUBufferUsage.INDEX 70 }, 71 indexArray.buffer, 72 indexBufferOffset 73 ); 70 74 71 75 return buffer; -
trunk/LayoutTests/webgpu/js/webgpu-functions.js
r245905 r246217 89 89 renderPassEncoder.endPass(); 90 90 } 91 92 function createBufferWithData(device, descriptor, data, offset = 0) { 93 const mappedBuffer = device.createBufferMapped(descriptor); 94 const dataArray = new Uint8Array(mappedBuffer[1]); 95 dataArray.set(new Uint8Array(data), offset); 96 mappedBuffer[0].unmap(); 97 return mappedBuffer[0]; 98 } 99 100 async function mapWriteDataToBuffer(buffer, data, offset = 0) { 101 const arrayBuffer = await buffer.mapWriteAsync(); 102 const writeArray = new Uint8Array(arrayBuffer); 103 writeArray.set(new Uint8Array(data), offset); 104 buffer.unmap(); 105 } -
trunk/LayoutTests/webgpu/map-read-buffers-expected.txt
r242148 r246217 1 1 2 PASS setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer. 2 PASS mapReadAsync, unmap, and destroy on a GPUBuffer. 3 PASS GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped. 3 4 PASS Reject a map read on a buffer not created with MAP_READ usage. 4 5 PASS Reject a map read on a mapped GPUBuffer. -
trunk/LayoutTests/webgpu/map-read-buffers.html
r244856 r246217 1 1 <!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] --> 2 2 <meta charset=utf-8> 3 <title>Tests for setSubDataand mapReadAsync on a GPUBuffer.</title>3 <title>Tests for createBufferMapped and mapReadAsync on a GPUBuffer.</title> 4 4 <body> 5 5 <script src="../resources/testharness.js"></script> … … 12 12 // Basic mapReadAsync functionality 13 13 promise_test(async () => { 14 const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage. TRANSFER_DST | GPUBufferUsage.MAP_READ });14 const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ }); 15 15 assert_true(buffer instanceof GPUBuffer, "createBuffer returned a GPUBuffer"); 16 17 let array = new Float32Array([1, 2, 3, 4]);18 buffer.setSubData(0, array.buffer);19 16 20 17 let arrayBuffer = await buffer.mapReadAsync(); … … 22 19 23 20 const readArray = new Float32Array(arrayBuffer); 24 assert_equals(readArray[3], 4, "successfully map-read value set by setSubData"); 25 26 buffer.unmap(); 27 28 buffer.setSubData(4 * 3, array.slice(0, 1).buffer); 29 let arrayBuffer1 = await buffer.mapReadAsync(); 30 const readArray1 = new Float32Array(arrayBuffer1); 31 assert_equals(readArray[3], 1, "successfully setSubData with an offset"); 21 assert_equals(readArray[0], 0, "successfully access a value from a map read"); 32 22 33 23 buffer.unmap(); … … 41 31 }, () => {}); 42 32 43 }, "setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer."); 33 }, "mapReadAsync, unmap, and destroy on a GPUBuffer."); 34 35 // GPUDevice.createBufferMapped 36 promise_test(async () => { 37 const bufferResult = device.createBufferMapped({ size: 16, usage: GPUBufferUsage.MAP_READ }); 38 const buffer = bufferResult[0]; 39 const arrayBuffer = bufferResult[1]; 40 41 assert_true(buffer instanceof GPUBuffer, "createBufferMapped returned a GPUBuffer"); 42 assert_true(arrayBuffer instanceof ArrayBuffer, "createBufferMapped returned an ArrayBuffer"); 43 44 let array = new Float32Array(arrayBuffer); 45 array.set([1, 2, 3, 4]); 46 47 // Buffer should already be "mapped". 48 await buffer.mapReadAsync().then(() => { 49 assert_unreached("GPUBuffer created via GPUBufferMapped cannot be mapped until after first unmap!"); 50 }, () => {}); 51 52 buffer.unmap(); 53 54 // Buffer should not be re-mappable for writes. 55 await buffer.mapWriteAsync().then(() => { 56 assert_unreached("Buffer was not created with MAP_WRITE!"); 57 }, () => {}); 58 59 // Read results of original writes. 60 let resultArrayBuffer = await buffer.mapReadAsync(); 61 const resultArray = new Float32Array(resultArrayBuffer); 62 resultArray.forEach((v, i) => { 63 assert_equals(v, array[i], "Successfully map-read value written to GPUBuffer mapped on creation"); 64 }) 65 66 buffer.destroy(); 67 }, "GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped."); 44 68 45 69 /* Basic validation */ -
trunk/LayoutTests/webgpu/texture-triangle-strip.html
r245905 r246217 90 90 1, -1, 0, 1 91 91 ]); 92 const positionBuffer = device.createBuffer({ size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 93 positionBuffer.setSubData(0, positionArray.buffer); 92 const positionBuffer = createBufferWithData(device, { size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX }, positionArray.buffer); 94 93 95 94 const texCoordsArray = new Float32Array([ … … 100 99 1, 1 101 100 ]); 102 const textureCoordBuffer = device.createBuffer({ size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 103 textureCoordBuffer.setSubData(0, texCoordsArray.buffer); 101 const textureCoordBuffer = createBufferWithData(device, { size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX }, texCoordsArray.buffer); 104 102 105 103 const vertexInputDescriptor = createVertexInputDescriptor(); … … 123 121 const textureBufferDescriptor = { 124 122 size: imageData.data.length, 125 usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST 126 }; 127 const textureBuffer = device.createBuffer(textureBufferDescriptor); 128 textureBuffer.setSubData(0, imageData.data.buffer); 123 usage: GPUBufferUsage.TRANSFER_SRC 124 }; 125 const textureBuffer = createBufferWithData(device, textureBufferDescriptor, imageData.data.buffer); 129 126 130 127 // Create GPUTexture -
trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html
r245905 r246217 43 43 44 44 function createVertexBuffer(device) { 45 const bufferSize = 4 * 5 * 4; 46 const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); 47 const vertexArrayBuffer0 = new Float32Array([ 45 const vertexArray = new Float32Array([ 48 46 // float4 xyzw, float g 49 47 -1, 1, 0, 1, 1, 50 -1, -1, 0, 1, 1 51 ]).buffer; 52 const vertexArrayBuffer1 = new Float32Array([ 48 -1, -1, 0, 1, 1, 53 49 1, 1, 0, 1, 1, 54 50 1, -1, 0, 1, 1 55 ]) .buffer;51 ]); 56 52 57 buffer.setSubData(0, vertexArrayBuffer0); 58 buffer.setSubData(4 * 5 * 2, vertexArrayBuffer1); 59 60 return buffer; 53 return createBufferWithData( 54 device, 55 { 56 size: vertexArray.byteLength, 57 usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE 58 }, 59 vertexArray.buffer 60 ); 61 61 } 62 62 -
trunk/Source/WebCore/ChangeLog
r246216 r246217 1 2019-06-07 Justin Fan <justin_fan@apple.com> 2 3 [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped 4 https://bugs.webkit.org/show_bug.cgi?id=198591 5 6 Reviewed by Myles C. Maxfield. 7 8 Remove GPUBuffer.setSubData from the WebGPU API. 9 Add GPUDevice.createBufferMapped to the WebGPU API. 10 11 Existing tests have been updated. 12 13 * Modules/webgpu/WebGPUBuffer.cpp: 14 (WebCore::WebGPUBuffer::setSubData): Deleted. 15 * Modules/webgpu/WebGPUBuffer.h: 16 * Modules/webgpu/WebGPUBuffer.idl: 17 * Modules/webgpu/WebGPUDevice.cpp: 18 (WebCore::WebGPUDevice::createBufferMapped const): 19 * Modules/webgpu/WebGPUDevice.h: 20 * Modules/webgpu/WebGPUDevice.idl: 21 * platform/graphics/gpu/GPUBuffer.h: 22 * platform/graphics/gpu/GPUCommandBuffer.h: 23 * platform/graphics/gpu/GPUDevice.cpp: 24 (WebCore::GPUDevice::tryCreateBuffer): 25 * platform/graphics/gpu/GPUDevice.h: 26 * platform/graphics/gpu/cocoa/GPUBufferMetal.mm: 27 (WebCore::GPUBuffer::tryCreate): 28 (WebCore::GPUBuffer::GPUBuffer): 29 (WebCore::GPUBuffer::state const): 30 (WebCore::GPUBuffer::mapOnCreation): 31 (WebCore::GPUBuffer::commandBufferCompleted): 32 (WebCore::GPUBuffer::copyStagingBufferToGPU): 33 Required to unmap GPUBuffers created with GPU-private storage. 34 (WebCore::GPUBuffer::unmap): 35 (WebCore::GPUBuffer::setSubData): Deleted. 36 (WebCore::GPUBuffer::reuseSubDataBuffer): Deleted. 37 1 38 2019-06-07 Michael Catanzaro <mcatanzaro@igalia.com> 2 39 -
trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp
r243658 r246217 41 41 : m_buffer(WTFMove(buffer)) 42 42 { 43 }44 45 void WebGPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data)46 {47 if (!m_buffer)48 LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!");49 else50 m_buffer->setSubData(offset, data);51 43 } 52 44 -
trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h
r243658 r246217 49 49 const GPUBuffer* buffer() const { return m_buffer.get(); } 50 50 51 void setSubData(uint64_t, const JSC::ArrayBuffer&);52 51 using BufferMappingPromise = DOMPromiseDeferred<IDLInterface<JSC::ArrayBuffer>>; 53 52 void mapReadAsync(BufferMappingPromise&&); -
trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl
r244856 r246217 33 33 InterfaceName=GPUBuffer 34 34 ] interface WebGPUBuffer { 35 void setSubData(u64 offset, ArrayBuffer data);36 37 35 Promise<ArrayBuffer> mapReadAsync(); 38 36 Promise<ArrayBuffer> mapWriteAsync(); -
trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
r244507 r246217 42 42 #include "GPUShaderModuleDescriptor.h" 43 43 #include "GPUTextureDescriptor.h" 44 #include "JSDOMConvertBufferSource.h" 45 #include "JSWebGPUBuffer.h" 44 46 #include "Logging.h" 45 47 #include "WebGPUBindGroup.h" … … 47 49 #include "WebGPUBindGroupDescriptor.h" 48 50 #include "WebGPUBindGroupLayout.h" 49 #include "WebGPUBuffer.h"50 51 #include "WebGPUBufferBinding.h" 51 52 #include "WebGPUCommandEncoder.h" … … 83 84 auto buffer = m_device->tryCreateBuffer(descriptor); 84 85 return WebGPUBuffer::create(WTFMove(buffer)); 86 } 87 88 Vector<JSC::JSValue> WebGPUDevice::createBufferMapped(JSC::ExecState& state, const GPUBufferDescriptor& descriptor) const 89 { 90 JSC::JSValue wrappedArrayBuffer = JSC::jsNull(); 91 92 auto buffer = m_device->tryCreateBuffer(descriptor, true); 93 if (buffer) { 94 auto arrayBuffer = buffer->mapOnCreation(); 95 wrappedArrayBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), arrayBuffer); 96 } 97 98 auto webBuffer = WebGPUBuffer::create(WTFMove(buffer)); 99 auto wrappedWebBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), webBuffer); 100 101 return { wrappedWebBuffer, wrappedArrayBuffer }; 85 102 } 86 103 -
trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h
r244507 r246217 35 35 #include <wtf/RefCounted.h> 36 36 #include <wtf/RefPtr.h> 37 #include <wtf/Vector.h> 38 39 namespace JSC { 40 class ArrayBuffer; 41 class JSValue; 42 } 37 43 38 44 namespace WebCore { … … 70 76 71 77 Ref<WebGPUBuffer> createBuffer(const GPUBufferDescriptor&) const; 78 Vector<JSC::JSValue> createBufferMapped(JSC::ExecState&, const GPUBufferDescriptor&) const; 72 79 Ref<WebGPUTexture> createTexture(const GPUTextureDescriptor&) const; 73 80 Ref<WebGPUSampler> createSampler(const GPUSamplerDescriptor&) const; -
trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.idl
r244856 r246217 25 25 // https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl 26 26 27 typedef sequence<any> GPUMappedBuffer; // [GPUBuffer, ArrayBuffer] 28 27 29 [ 28 30 Conditional=WEBGPU, … … 34 36 35 37 WebGPUBuffer createBuffer(GPUBufferDescriptor descriptor); 38 [CallWith=ExecState] GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor); 36 39 WebGPUTexture createTexture(GPUTextureDescriptor descriptor); 37 40 WebGPUSampler createSampler(GPUSamplerDescriptor descriptor); -
trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
r244235 r246217 69 69 ~GPUBuffer(); 70 70 71 static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor& );71 static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&, bool isMappedOnCreation); 72 72 73 73 PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); } … … 83 83 State state() const; 84 84 85 JSC::ArrayBuffer* mapOnCreation(); 86 85 87 #if USE(METAL) 86 88 void commandBufferCommitted(MTLCommandBuffer *); 87 89 void commandBufferCompleted(); 88 89 void reuseSubDataBuffer(RetainPtr<MTLBuffer>&&);90 90 #endif 91 91 92 void setSubData(uint64_t, const JSC::ArrayBuffer&);93 92 using MappingCallback = WTF::Function<void(JSC::ArrayBuffer*)>; 94 93 void registerMappingCallback(MappingCallback&&, bool); … … 109 108 }; 110 109 110 GPUBuffer(PlatformBufferSmartPtr&&, Ref<GPUDevice>&&, size_t, OptionSet<GPUBufferUsage::Flags>, bool); 111 111 static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>); 112 113 GPUBuffer(PlatformBufferSmartPtr&&, size_t, OptionSet<GPUBufferUsage::Flags>, Ref<GPUDevice>&&);114 112 115 113 JSC::ArrayBuffer* stagingBufferForRead(); 116 114 JSC::ArrayBuffer* stagingBufferForWrite(); 117 115 void runMappingCallback(); 116 void copyStagingBufferToGPU(); 118 117 119 118 bool isMapWrite() const { return m_usage.contains(GPUBufferUsage::Flags::MapWrite); } … … 125 124 Ref<GPUDevice> m_device; 126 125 127 #if USE(METAL)128 Vector<RetainPtr<MTLBuffer>> m_subDataBuffers;129 #endif130 131 126 RefPtr<JSC::ArrayBuffer> m_stagingBuffer; 132 127 RefPtr<PendingMappingCallback> m_mappingCallback; … … 136 131 OptionSet<GPUBufferUsage::Flags> m_usage; 137 132 unsigned m_numScheduledCommandBuffers { 0 }; 133 bool m_isMappedFromCreation { false }; 138 134 }; 139 135 -
trunk/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h
r243658 r246217 109 109 Vector<Ref<GPUBuffer>> m_usedBuffers; 110 110 Vector<Ref<GPUTexture>> m_usedTextures; 111 bool m_isEncodingPass = false;111 bool m_isEncodingPass { false }; 112 112 #if USE(METAL) 113 113 MTLBlitCommandEncoder *blitEncoder() const; -
trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp
r244507 r246217 51 51 namespace WebCore { 52 52 53 RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor )53 RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor, bool isMappedOnCreation) 54 54 { 55 return GPUBuffer::tryCreate(makeRef(*this), descriptor );55 return GPUBuffer::tryCreate(makeRef(*this), descriptor, isMappedOnCreation); 56 56 } 57 57 -
trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h
r244507 r246217 66 66 static RefPtr<GPUDevice> tryCreate(const Optional<GPURequestAdapterOptions>&); 67 67 68 RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor& );68 RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&, bool isMappedOnCreation = false); 69 69 RefPtr<GPUTexture> tryCreateTexture(const GPUTextureDescriptor&) const; 70 70 RefPtr<GPUSampler> tryCreateSampler(const GPUSamplerDescriptor&) const; -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
r244297 r246217 63 63 } 64 64 65 RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor )65 RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor, bool isMappedOnCreation) 66 66 { 67 67 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. … … 76 76 return nullptr; 77 77 78 #if PLATFORM(MAC) 79 // copyBufferToBuffer calls require 4-byte alignment. "Unmapping" a mapped-on-creation GPUBuffer 80 // that is otherwise unmappable requires such a copy to upload data. 81 if (isMappedOnCreation 82 && !usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead }) 83 && descriptor.size % 4) { 84 LOG(WebGPU, "GPUBuffer::tryCreate(): Data must be aligned to a multiple of 4 bytes!"); 85 return nullptr; 86 } 87 #endif 88 78 89 // FIXME: Metal best practices: Read-only one-time-use data less than 4 KB should not allocate a MTLBuffer and be used in [MTLCommandEncoder set*Bytes] calls instead. 79 90 … … 96 107 } 97 108 98 return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), size, usage, WTFMove(device)));99 } 100 101 GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, size_t size, OptionSet<GPUBufferUsage::Flags> usage, Ref<GPUDevice>&& device)109 return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(device), size, usage, isMappedOnCreation)); 110 } 111 112 GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, Ref<GPUDevice>&& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, bool isMapped) 102 113 : m_platformBuffer(WTFMove(buffer)) 103 114 , m_device(WTFMove(device)) 104 115 , m_byteLength(size) 105 116 , m_usage(usage) 117 , m_isMappedFromCreation(isMapped) 106 118 { 107 119 } … … 121 133 if (!m_platformBuffer) 122 134 return State::Destroyed; 123 if (m_ mappingCallback)135 if (m_isMappedFromCreation || m_mappingCallback) 124 136 return State::Mapped; 125 137 … … 127 139 } 128 140 129 void GPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data) 130 { 131 MTLCommandQueue *queue; 132 if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue())) 133 return; 134 135 if (!isTransferDestination() || state() != State::Unmapped) { 136 LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!"); 137 return; 138 } 139 140 #if PLATFORM(MAC) 141 if (offset % 4 || data.byteLength() % 4) { 142 LOG(WebGPU, "GPUBuffer::setSubData(): Data must be aligned to a multiple of 4 bytes!"); 143 return; 144 } 145 #endif 146 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 147 auto subDataLength = checkedSum<NSUInteger>(data.byteLength(), offset); 148 if (subDataLength.hasOverflowed() || subDataLength.unsafeGet() > m_byteLength) { 149 LOG(WebGPU, "GPUBuffer::setSubData(): Invalid offset or data size!"); 150 return; 151 } 152 153 if (m_subDataBuffers.isEmpty()) { 154 BEGIN_BLOCK_OBJC_EXCEPTIONS; 155 m_subDataBuffers.append(adoptNS([m_platformBuffer.get().device newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache])); 156 END_BLOCK_OBJC_EXCEPTIONS; 157 } 158 159 __block auto stagingMtlBuffer = m_subDataBuffers.takeLast(); 160 161 if (!stagingMtlBuffer || stagingMtlBuffer.get().length < data.byteLength()) { 162 LOG(WebGPU, "GPUBuffer::setSubData(): Unable to get staging buffer for provided data!"); 163 return; 164 } 165 166 memcpy(stagingMtlBuffer.get().contents, data.data(), data.byteLength()); 167 168 BEGIN_BLOCK_OBJC_EXCEPTIONS; 169 170 auto commandBuffer = retainPtr([queue commandBuffer]); 171 auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]); 172 173 [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:static_cast<NSUInteger>(offset) size:stagingMtlBuffer.get().length]; 174 [blitEncoder endEncoding]; 175 176 if (isMappable()) 177 commandBufferCommitted(commandBuffer.get()); 178 179 auto protectedThis = makeRefPtr(this); 180 [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>) { 181 protectedThis->reuseSubDataBuffer(WTFMove(stagingMtlBuffer)); 182 }]; 183 [commandBuffer commit]; 184 185 END_BLOCK_OBJC_EXCEPTIONS; 141 JSC::ArrayBuffer* GPUBuffer::mapOnCreation() 142 { 143 ASSERT(m_isMappedFromCreation); 144 return stagingBufferForWrite(); 186 145 } 187 146 … … 210 169 211 170 --m_numScheduledCommandBuffers; 212 }213 214 void GPUBuffer::reuseSubDataBuffer(RetainPtr<MTLBuffer>&& buffer)215 {216 m_subDataBuffers.append(WTFMove(buffer));217 171 } 218 172 #endif // USE(METAL) … … 267 221 } 268 222 223 void GPUBuffer::copyStagingBufferToGPU() 224 { 225 MTLCommandQueue *queue; 226 if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue())) 227 return; 228 229 RetainPtr<MTLBuffer> stagingMtlBuffer; 230 231 BEGIN_BLOCK_OBJC_EXCEPTIONS; 232 // GPUBuffer creation validation ensures m_byteSize fits in NSUInteger. 233 stagingMtlBuffer = adoptNS([m_device->platformDevice() newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache]); 234 END_BLOCK_OBJC_EXCEPTIONS; 235 236 if (!stagingMtlBuffer) { 237 LOG(WebGPU, "GPUBuffer::unmap(): Unable to create staging buffer!"); 238 return; 239 } 240 241 memcpy(stagingMtlBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); 242 243 BEGIN_BLOCK_OBJC_EXCEPTIONS; 244 245 auto commandBuffer = retainPtr([queue commandBuffer]); 246 auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]); 247 248 [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:0 size:static_cast<NSUInteger>(m_byteLength)]; 249 [blitEncoder endEncoding]; 250 [commandBuffer commit]; 251 252 END_BLOCK_OBJC_EXCEPTIONS; 253 } 254 269 255 void GPUBuffer::unmap() 270 256 { 271 if (!isMappable()) { 272 LOG(WebGPU, "GPUBuffer::unmap(): Buffer is not mappable!"); 273 return; 274 } 275 276 if (m_stagingBuffer && isMapWrite()) { 277 ASSERT(m_platformBuffer); 278 memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); 257 if (!m_isMappedFromCreation && !isMappable()) { 258 LOG(WebGPU, "GPUBuffer::unmap(): Invalid operation: buffer is not mappable!"); 259 return; 260 } 261 262 if (m_stagingBuffer) { 263 if (isMappable()) { 264 // MAP_WRITE and MAP_READ buffers have shared, CPU-accessible storage. 265 ASSERT(m_platformBuffer && m_platformBuffer.get().contents); 266 memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); 267 } else if (m_isMappedFromCreation) 268 copyStagingBufferToGPU(); 269 270 m_isMappedFromCreation = false; 279 271 m_stagingBuffer = nullptr; 280 272 }
Note: See TracChangeset
for help on using the changeset viewer.