WebKit Bugzilla
Attachment 371464 Details for
Bug 198591
: [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198591-20190605185215.patch (text/plain), 38.91 KB, created by
Justin Fan
on 2019-06-05 18:52:16 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Justin Fan
Created:
2019-06-05 18:52:16 PDT
Size:
38.91 KB
patch
obsolete
>Subversion Revision: 245905 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 25f91879632da76946012c996e6c50681289fd6a..2ab13c01792522c073de712a0381e2b0a2e6c227 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,40 @@ >+2019-06-05 Justin Fan <justin_fan@apple.com> >+ >+ [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped >+ https://bugs.webkit.org/show_bug.cgi?id=198591 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Remove GPUBuffer.setSubData from the WebGPU API. >+ Add GPUDevice.createBufferMapped to the WebGPU API. >+ >+ Existing tests have been updated. >+ >+ * Modules/webgpu/WebGPUBuffer.cpp: >+ (WebCore::WebGPUBuffer::setSubData): Deleted. >+ * Modules/webgpu/WebGPUBuffer.h: >+ * Modules/webgpu/WebGPUBuffer.idl: >+ * Modules/webgpu/WebGPUDevice.cpp: >+ (WebCore::WebGPUDevice::createBufferMapped const): >+ * Modules/webgpu/WebGPUDevice.h: >+ * Modules/webgpu/WebGPUDevice.idl: >+ * platform/graphics/gpu/GPUBuffer.h: >+ * platform/graphics/gpu/GPUCommandBuffer.h: >+ * platform/graphics/gpu/GPUDevice.cpp: >+ (WebCore::GPUDevice::tryCreateBuffer): >+ * platform/graphics/gpu/GPUDevice.h: >+ * platform/graphics/gpu/cocoa/GPUBufferMetal.mm: >+ (WebCore::GPUBuffer::tryCreate): >+ (WebCore::GPUBuffer::GPUBuffer): >+ (WebCore::GPUBuffer::state const): >+ (WebCore::GPUBuffer::mapOnCreation): >+ (WebCore::GPUBuffer::commandBufferCompleted): >+ (WebCore::GPUBuffer::copyStagingBufferToGPU): >+ Required to unmap GPUBuffers created with GPU-private storage. >+ (WebCore::GPUBuffer::unmap): >+ (WebCore::GPUBuffer::setSubData): Deleted. >+ (WebCore::GPUBuffer::reuseSubDataBuffer): Deleted. >+ > 2019-05-30 Justin Fan <justin_fan@apple.com> > > [Web GPU] Vertex Buffers/Input State API updates >diff --git a/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp b/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp >index 1f082ecafbf824dc012942ba6dd7998ac8ef88a1..c222e3557591a680d8b38603d87732740d57362d 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp >+++ b/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp >@@ -42,14 +42,6 @@ WebGPUBuffer::WebGPUBuffer(RefPtr<GPUBuffer>&& buffer) > { > } > >-void WebGPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data) >-{ >- if (!m_buffer) >- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!"); >- else >- m_buffer->setSubData(offset, data); >-} >- > void WebGPUBuffer::mapReadAsync(BufferMappingPromise&& promise) > { > rejectOrRegisterPromiseCallback(WTFMove(promise), true); >diff --git a/Source/WebCore/Modules/webgpu/WebGPUBuffer.h b/Source/WebCore/Modules/webgpu/WebGPUBuffer.h >index d41e9170df5fa3111326608a995567201675de29..587970d91713ac80a997487f48ef2f0fcc25210f 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUBuffer.h >+++ b/Source/WebCore/Modules/webgpu/WebGPUBuffer.h >@@ -48,7 +48,6 @@ public: > GPUBuffer* buffer() { return m_buffer.get(); } > const GPUBuffer* buffer() const { return m_buffer.get(); } > >- void setSubData(uint64_t, const JSC::ArrayBuffer&); > using BufferMappingPromise = DOMPromiseDeferred<IDLInterface<JSC::ArrayBuffer>>; > void mapReadAsync(BufferMappingPromise&&); > void mapWriteAsync(BufferMappingPromise&&); >diff --git a/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl b/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl >index a870547b38e025e0ccbae36c4b346e8a4755a020..7ef8cba96fc1805e0cdf039db60938d6dfc1a06d 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl >+++ b/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl >@@ -32,8 +32,6 @@ typedef unsigned long long u64; > ImplementationLacksVTable, > InterfaceName=GPUBuffer > ] interface WebGPUBuffer { >- void setSubData(u64 offset, ArrayBuffer data); >- > Promise<ArrayBuffer> mapReadAsync(); > Promise<ArrayBuffer> mapWriteAsync(); > void unmap(); >diff --git a/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp b/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp >index a4785297fc97ace9bb1b6d368dd111d40d4d64fa..f059ad89e09d4f4a74f8b8e813f44f5a0a9b9e1e 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp >+++ b/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp >@@ -41,12 +41,13 @@ > #include "GPUSamplerDescriptor.h" > #include "GPUShaderModuleDescriptor.h" > #include "GPUTextureDescriptor.h" >+#include "JSDOMConvertBufferSource.h" >+#include "JSWebGPUBuffer.h" > #include "Logging.h" > #include "WebGPUBindGroup.h" > #include "WebGPUBindGroupBinding.h" > #include "WebGPUBindGroupDescriptor.h" > #include "WebGPUBindGroupLayout.h" >-#include "WebGPUBuffer.h" > #include "WebGPUBufferBinding.h" > #include "WebGPUCommandEncoder.h" > #include "WebGPUComputePipeline.h" >@@ -84,6 +85,22 @@ Ref<WebGPUBuffer> WebGPUDevice::createBuffer(const GPUBufferDescriptor& descript > return WebGPUBuffer::create(WTFMove(buffer)); > } > >+Vector<JSC::JSValue> WebGPUDevice::createBufferMapped(JSC::ExecState& state, const GPUBufferDescriptor& descriptor) const >+{ >+ JSC::JSValue wrappedArrayBuffer = JSC::jsNull(); >+ >+ auto buffer = m_device->tryCreateBuffer(descriptor, true); >+ if (buffer) { >+ auto arrayBuffer = buffer->mapOnCreation(); >+ wrappedArrayBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), arrayBuffer); >+ } >+ >+ auto webBuffer = WebGPUBuffer::create(WTFMove(buffer)); >+ auto wrappedWebBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), webBuffer); >+ >+ return { wrappedWebBuffer, wrappedArrayBuffer }; >+} >+ > Ref<WebGPUTexture> WebGPUDevice::createTexture(const GPUTextureDescriptor& descriptor) const > { > auto texture = m_device->tryCreateTexture(descriptor); >diff --git a/Source/WebCore/Modules/webgpu/WebGPUDevice.h b/Source/WebCore/Modules/webgpu/WebGPUDevice.h >index 653f0761302d093985faea0060d9cfda1db47355..21d371a03a751544a91d7c8a1ad0cd621595aa1b 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUDevice.h >+++ b/Source/WebCore/Modules/webgpu/WebGPUDevice.h >@@ -34,6 +34,12 @@ > #include <wtf/Ref.h> > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> >+#include <wtf/Vector.h> >+ >+namespace JSC { >+class ArrayBuffer; >+class JSValue; >+} > > namespace WebCore { > >@@ -69,6 +75,7 @@ public: > const GPUDevice& device() const { return m_device.get(); } > > Ref<WebGPUBuffer> createBuffer(const GPUBufferDescriptor&) const; >+ Vector<JSC::JSValue> createBufferMapped(JSC::ExecState&, const GPUBufferDescriptor&) const; > Ref<WebGPUTexture> createTexture(const GPUTextureDescriptor&) const; > Ref<WebGPUSampler> createSampler(const GPUSamplerDescriptor&) const; > >diff --git a/Source/WebCore/Modules/webgpu/WebGPUDevice.idl b/Source/WebCore/Modules/webgpu/WebGPUDevice.idl >index 057260ef441e6cf67412f933599567dcbb14c656..d8314e76d4302c15b183ef536460f947c57287ec 100644 >--- a/Source/WebCore/Modules/webgpu/WebGPUDevice.idl >+++ b/Source/WebCore/Modules/webgpu/WebGPUDevice.idl >@@ -24,6 +24,8 @@ > */ > // https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl > >+typedef sequence<any> GPUMappedBuffer; // [GPUBuffer, ArrayBuffer] >+ > [ > Conditional=WEBGPU, > EnabledAtRuntime=WebGPU, >@@ -33,6 +35,7 @@ > readonly attribute WebGPUAdapter adapter; > > WebGPUBuffer createBuffer(GPUBufferDescriptor descriptor); >+ [CallWith=ExecState] GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor); > WebGPUTexture createTexture(GPUTextureDescriptor descriptor); > WebGPUSampler createSampler(GPUSamplerDescriptor descriptor); > >diff --git a/Source/WebCore/platform/graphics/gpu/GPUBuffer.h b/Source/WebCore/platform/graphics/gpu/GPUBuffer.h >index e46a9a4d442ecc69b45bd285a6f7f7a620b56e63..42508bc761705bf1a0e6611791f5ea67097b5505 100644 >--- a/Source/WebCore/platform/graphics/gpu/GPUBuffer.h >+++ b/Source/WebCore/platform/graphics/gpu/GPUBuffer.h >@@ -68,7 +68,7 @@ public: > > ~GPUBuffer(); > >- static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&); >+ static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&, bool isMappedOnCreation); > > PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); } > size_t byteLength() const { return m_byteLength; } >@@ -82,14 +82,13 @@ public: > bool isMappable() const { return m_usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead }); } > State state() const; > >+ JSC::ArrayBuffer* mapOnCreation(); >+ > #if USE(METAL) > void commandBufferCommitted(MTLCommandBuffer *); > void commandBufferCompleted(); >- >- void reuseSubDataBuffer(RetainPtr<MTLBuffer>&&); > #endif > >- void setSubData(uint64_t, const JSC::ArrayBuffer&); > using MappingCallback = WTF::Function<void(JSC::ArrayBuffer*)>; > void registerMappingCallback(MappingCallback&&, bool); > void unmap(); >@@ -108,13 +107,13 @@ private: > PendingMappingCallback(MappingCallback&&); > }; > >+ GPUBuffer(PlatformBufferSmartPtr&&, Ref<GPUDevice>&&, size_t, OptionSet<GPUBufferUsage::Flags>, bool); > static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>); > >- GPUBuffer(PlatformBufferSmartPtr&&, size_t, OptionSet<GPUBufferUsage::Flags>, Ref<GPUDevice>&&); >- > JSC::ArrayBuffer* stagingBufferForRead(); > JSC::ArrayBuffer* stagingBufferForWrite(); > void runMappingCallback(); >+ void copyStagingBufferToGPU(); > > bool isMapWrite() const { return m_usage.contains(GPUBufferUsage::Flags::MapWrite); } > bool isMapRead() const { return m_usage.contains(GPUBufferUsage::Flags::MapRead); } >@@ -124,10 +123,6 @@ private: > PlatformBufferSmartPtr m_platformBuffer; > Ref<GPUDevice> m_device; > >-#if USE(METAL) >- Vector<RetainPtr<MTLBuffer>> m_subDataBuffers; >-#endif >- > RefPtr<JSC::ArrayBuffer> m_stagingBuffer; > RefPtr<PendingMappingCallback> m_mappingCallback; > DeferrableTask<Timer> m_mappingCallbackTask; >@@ -135,6 +130,7 @@ private: > size_t m_byteLength; > OptionSet<GPUBufferUsage::Flags> m_usage; > unsigned m_numScheduledCommandBuffers { 0 }; >+ bool m_isMappedFromCreation { false }; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h b/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h >index afb52778872bc09515cdde4e2467801d25f5890b..94c463371c83e6328558e32d83da033f9697eba1 100644 >--- a/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h >+++ b/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h >@@ -108,7 +108,7 @@ private: > PlatformCommandBufferSmartPtr m_platformCommandBuffer; > Vector<Ref<GPUBuffer>> m_usedBuffers; > Vector<Ref<GPUTexture>> m_usedTextures; >- bool m_isEncodingPass = false; >+ bool m_isEncodingPass { false }; > #if USE(METAL) > MTLBlitCommandEncoder *blitEncoder() const; > mutable RetainPtr<MTLBlitCommandEncoder> m_blitEncoder; >diff --git a/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp b/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp >index 083a77c35a27883833a88f64380bc6f684620e86..a649a6071919b6d5c241a72f268825a0e651e7ad 100644 >--- a/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp >+++ b/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp >@@ -50,9 +50,9 @@ > > namespace WebCore { > >-RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor) >+RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor, bool isMappedOnCreation) > { >- return GPUBuffer::tryCreate(makeRef(*this), descriptor); >+ return GPUBuffer::tryCreate(makeRef(*this), descriptor, isMappedOnCreation); > } > > RefPtr<GPUTexture> GPUDevice::tryCreateTexture(const GPUTextureDescriptor& descriptor) const >diff --git a/Source/WebCore/platform/graphics/gpu/GPUDevice.h b/Source/WebCore/platform/graphics/gpu/GPUDevice.h >index c913defe31832e362d45c14c6b7ac62b5a3dd5f6..a7139541d0bfd14db28fa959ffb019430f803bbe 100644 >--- a/Source/WebCore/platform/graphics/gpu/GPUDevice.h >+++ b/Source/WebCore/platform/graphics/gpu/GPUDevice.h >@@ -65,7 +65,7 @@ class GPUDevice : public RefCounted<GPUDevice>, public CanMakeWeakPtr<GPUDevice> > public: > static RefPtr<GPUDevice> tryCreate(const Optional<GPURequestAdapterOptions>&); > >- RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&); >+ RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&, bool isMappedOnCreation = false); > RefPtr<GPUTexture> tryCreateTexture(const GPUTextureDescriptor&) const; > RefPtr<GPUSampler> tryCreateSampler(const GPUSamplerDescriptor&) const; > >diff --git a/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm b/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm >index 8a3ed328f922bf316d3307fa58efcbb6b492afaf..59a07ff9ceb7d8ea52d3cb6cd1ac3c7df5fc2a05 100644 >--- a/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm >+++ b/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm >@@ -62,7 +62,7 @@ bool GPUBuffer::validateBufferUsage(const GPUDevice& device, OptionSet<GPUBuffer > return true; > } > >-RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor) >+RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor, bool isMappedOnCreation) > { > // MTLBuffer size (NSUInteger) is 32 bits on some platforms. > NSUInteger size = 0; >@@ -75,6 +75,17 @@ RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferD > if (!validateBufferUsage(device.get(), usage)) > return nullptr; > >+#if PLATFORM(MAC) >+ // copyBufferToBuffer calls require 4-byte alignment. "Unmapping" a mapped-on-creation GPUBuffer >+ // that is otherwise unmappable requires such a copy to upload data. >+ if (isMappedOnCreation >+ && !usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead }) >+ && descriptor.size % 4) { >+ LOG(WebGPU, "GPUBuffer::tryCreate(): Data must be aligned to a multiple of 4 bytes!"); >+ return nullptr; >+ } >+#endif >+ > // 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. > > MTLResourceOptions resourceOptions = MTLResourceCPUCacheModeDefaultCache; >@@ -95,14 +106,15 @@ RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferD > return nullptr; > } > >- return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), size, usage, WTFMove(device))); >+ return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(device), size, usage, isMappedOnCreation)); > } > >-GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, size_t size, OptionSet<GPUBufferUsage::Flags> usage, Ref<GPUDevice>&& device) >+GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, Ref<GPUDevice>&& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, bool isMapped) > : m_platformBuffer(WTFMove(buffer)) > , m_device(WTFMove(device)) > , m_byteLength(size) > , m_usage(usage) >+ , m_isMappedFromCreation(isMapped) > { > } > >@@ -120,69 +132,16 @@ GPUBuffer::State GPUBuffer::state() const > { > if (!m_platformBuffer) > return State::Destroyed; >- if (m_mappingCallback) >+ if (m_isMappedFromCreation || m_mappingCallback) > return State::Mapped; > > return State::Unmapped; > } > >-void GPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data) >+JSC::ArrayBuffer* GPUBuffer::mapOnCreation() > { >- MTLCommandQueue *queue; >- if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue())) >- return; >- >- if (!isTransferDestination() || state() != State::Unmapped) { >- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!"); >- return; >- } >- >-#if PLATFORM(MAC) >- if (offset % 4 || data.byteLength() % 4) { >- LOG(WebGPU, "GPUBuffer::setSubData(): Data must be aligned to a multiple of 4 bytes!"); >- return; >- } >-#endif >- // MTLBuffer size (NSUInteger) is 32 bits on some platforms. >- auto subDataLength = checkedSum<NSUInteger>(data.byteLength(), offset); >- if (subDataLength.hasOverflowed() || subDataLength.unsafeGet() > m_byteLength) { >- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid offset or data size!"); >- return; >- } >- >- if (m_subDataBuffers.isEmpty()) { >- BEGIN_BLOCK_OBJC_EXCEPTIONS; >- m_subDataBuffers.append(adoptNS([m_platformBuffer.get().device newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache])); >- END_BLOCK_OBJC_EXCEPTIONS; >- } >- >- __block auto stagingMtlBuffer = m_subDataBuffers.takeLast(); >- >- if (!stagingMtlBuffer || stagingMtlBuffer.get().length < data.byteLength()) { >- LOG(WebGPU, "GPUBuffer::setSubData(): Unable to get staging buffer for provided data!"); >- return; >- } >- >- memcpy(stagingMtlBuffer.get().contents, data.data(), data.byteLength()); >- >- BEGIN_BLOCK_OBJC_EXCEPTIONS; >- >- auto commandBuffer = retainPtr([queue commandBuffer]); >- auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]); >- >- [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:static_cast<NSUInteger>(offset) size:stagingMtlBuffer.get().length]; >- [blitEncoder endEncoding]; >- >- if (isMappable()) >- commandBufferCommitted(commandBuffer.get()); >- >- auto protectedThis = makeRefPtr(this); >- [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>) { >- protectedThis->reuseSubDataBuffer(WTFMove(stagingMtlBuffer)); >- }]; >- [commandBuffer commit]; >- >- END_BLOCK_OBJC_EXCEPTIONS; >+ ASSERT(m_isMappedFromCreation); >+ return stagingBufferForWrite(); > } > > #if USE(METAL) >@@ -210,11 +169,6 @@ void GPUBuffer::commandBufferCompleted() > > --m_numScheduledCommandBuffers; > } >- >-void GPUBuffer::reuseSubDataBuffer(RetainPtr<MTLBuffer>&& buffer) >-{ >- m_subDataBuffers.append(WTFMove(buffer)); >-} > #endif // USE(METAL) > > void GPUBuffer::registerMappingCallback(MappingCallback&& callback, bool isRead) >@@ -266,16 +220,54 @@ JSC::ArrayBuffer* GPUBuffer::stagingBufferForWrite() > return m_stagingBuffer.get(); > } > >+void GPUBuffer::copyStagingBufferToGPU() >+{ >+ MTLCommandQueue *queue; >+ if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue())) >+ return; >+ >+ RetainPtr<MTLBuffer> stagingMtlBuffer; >+ >+ BEGIN_BLOCK_OBJC_EXCEPTIONS; >+ // GPUBuffer creation validation ensures m_byteSize fits in NSUInteger. >+ stagingMtlBuffer = adoptNS([m_device->platformDevice() newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache]); >+ END_BLOCK_OBJC_EXCEPTIONS; >+ >+ if (!stagingMtlBuffer) { >+ LOG(WebGPU, "GPUBuffer::unmap(): Unable to create staging buffer!"); >+ return; >+ } >+ >+ memcpy(stagingMtlBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); >+ >+ BEGIN_BLOCK_OBJC_EXCEPTIONS; >+ >+ auto commandBuffer = retainPtr([queue commandBuffer]); >+ auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]); >+ >+ [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:0 size:static_cast<NSUInteger>(m_byteLength)]; >+ [blitEncoder endEncoding]; >+ [commandBuffer commit]; >+ >+ END_BLOCK_OBJC_EXCEPTIONS; >+} >+ > void GPUBuffer::unmap() > { >- if (!isMappable()) { >- LOG(WebGPU, "GPUBuffer::unmap(): Buffer is not mappable!"); >+ if (!m_isMappedFromCreation && !isMappable()) { >+ LOG(WebGPU, "GPUBuffer::unmap(): Invalid operation: buffer is not mappable!"); > return; > } > >- if (m_stagingBuffer && isMapWrite()) { >- ASSERT(m_platformBuffer); >- memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); >+ if (m_stagingBuffer) { >+ if (isMappable()) { >+ // MAP_WRITE and MAP_READ buffers have shared, CPU-accessible storage. >+ ASSERT(m_platformBuffer && m_platformBuffer.get().contents); >+ memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); >+ } else if (m_isMappedFromCreation) >+ copyStagingBufferToGPU(); >+ >+ m_isMappedFromCreation = false; > m_stagingBuffer = nullptr; > } > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 78485df80530a7bd5d1b9de9fbfadb210dadf9e0..4ecdb7acf1d739534622892cf2a5ae55f467bbf8 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,29 @@ >+2019-06-05 Justin Fan <justin_fan@apple.com> >+ >+ [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped >+ https://bugs.webkit.org/show_bug.cgi?id=198591 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ GPUBuffer.setSubData has been removed from the WebGPU implementation. >+ GPUDevice.createBufferMapped has been added to the WebGPU implementation. >+ Replace all setSubData calls with appropriate replacements. >+ >+ * webgpu/blend-triangle-strip.html: >+ * webgpu/blit-commands.html: >+ * webgpu/buffer-command-buffer-races.html: >+ * webgpu/buffer-resource-triangles.html: >+ * webgpu/compute-squares.html: >+ * webgpu/depth-enabled-triangle-strip.html: >+ * webgpu/draw-indexed-triangles.html: >+ * webgpu/js/webgpu-functions.js: >+ (createBufferWithData): >+ (async.mapWriteDataToBuffer): >+ * webgpu/map-read-buffers-expected.txt: >+ * webgpu/map-read-buffers.html: >+ * webgpu/texture-triangle-strip.html: >+ * webgpu/vertex-buffer-triangle-strip.html: >+ > 2019-05-30 Justin Fan <justin_fan@apple.com> > > [Web GPU] Vertex Buffers/Input State API updates >diff --git a/LayoutTests/webgpu/blend-triangle-strip.html b/LayoutTests/webgpu/blend-triangle-strip.html >index dd7fda67489bb3e37a44cb882b8ac0a2650c22a3..cabef69e79d2b328d73a6323bf2ccf0df89c1166 100644 >--- a/LayoutTests/webgpu/blend-triangle-strip.html >+++ b/LayoutTests/webgpu/blend-triangle-strip.html >@@ -75,8 +75,7 @@ async function test() { > 1, 1, 0, 1, > 1, -1, 0, 1 > ]); >- const vertexBuffer = device.createBuffer({ size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- vertexBuffer.setSubData(0, vertexData.buffer); >+ const vertexBuffer = createBufferWithData(device, { size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX }, vertexData.buffer); > > const context = canvas.getContext("gpu"); > const swapChain = context.configureSwapChain({ device: device, format: "bgra8unorm" }); >diff --git a/LayoutTests/webgpu/blit-commands.html b/LayoutTests/webgpu/blit-commands.html >index d7ea225b131f797f93bc838827bfc4321fdbc2b6..8deaa19311c5de3596c65e583516d837899346a0 100644 >--- a/LayoutTests/webgpu/blit-commands.html >+++ b/LayoutTests/webgpu/blit-commands.html >@@ -30,11 +30,11 @@ async function test(image) { > > const bufferDescriptor = { > size: imageData.data.byteLength, >- usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST >+ usage: GPUBufferUsage.TRANSFER_SRC > }; >- const bufferA = device.createBuffer(bufferDescriptor); >- bufferA.setSubData(0, imageData.data.buffer); >+ bufferA = createBufferWithData(device, bufferDescriptor, imageData.data.buffer); > >+ bufferDescriptor.usage |= GPUBufferUsage.TRANSFER_DST; > const bufferB = device.createBuffer(bufferDescriptor); > const bufferViewB = { > buffer: bufferB, >diff --git a/LayoutTests/webgpu/buffer-command-buffer-races.html b/LayoutTests/webgpu/buffer-command-buffer-races.html >index 2aecda42a6c7ef9fd240944e6a39b8ecc49ab200..864c5ef29cf2772bb83510481996c93ed7b50f86 100644 >--- a/LayoutTests/webgpu/buffer-command-buffer-races.html >+++ b/LayoutTests/webgpu/buffer-command-buffer-races.html >@@ -63,10 +63,8 @@ function createVertexInputDescriptor() { > } > > function createAndSetVertexBuffer(device, vertices) { >- const floatArray = new Float32Array(vertices); >- const buffer = device.createBuffer({ size: floatArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- buffer.setSubData(0, floatArray.buffer); >- return buffer; >+ const vertexArray = new Float32Array(vertices) >+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); > } > > function drawAndSubmitCommands(device, pipeline, attachment, vertexBuffer, colorBuffer) { >@@ -97,8 +95,7 @@ async function test() { > const greenArray = new Float32Array(green); > const blueArray = new Float32Array(blue); > >- const colorBuffer = device.createBuffer({ size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_WRITE }); >- colorBuffer.setSubData(0, greenArray.buffer); >+ const colorBuffer = createBufferWithData(device, { size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE }, greenArray.buffer); > > const attachment = { > attachment: swapChain.getCurrentTexture().createDefaultView(), >@@ -126,12 +123,12 @@ async function test() { > /* colorBuffer does not actually contain "green" again until this call. */ > colorBuffer.unmap(); > >- /* setSubData immediately after a submit should not affect the preceding draw call. */ >+ /* Writing data immediately after a submit should not affect the preceding draw call. */ > drawAndSubmitCommands(device, pipeline, attachment, middleBuffer, colorBuffer); >- colorBuffer.setSubData(0, blueArray.buffer); >+ await mapWriteDataToBuffer(colorBuffer, blueArray.buffer); > > /* destroy right after a submit should not affect the draw call. */ >- colorBuffer.setSubData(0, greenArray.buffer); >+ await mapWriteDataToBuffer(colorBuffer, greenArray.buffer); > drawAndSubmitCommands(device, pipeline, attachment, upperRightBuffer, colorBuffer); > upperRightBuffer.destroy(); > >diff --git a/LayoutTests/webgpu/buffer-resource-triangles.html b/LayoutTests/webgpu/buffer-resource-triangles.html >index bd06c457d497e6b38441f79161697b7b08c6824d..e2e6d34dedb27848e6651e47e0f7686889a2d393 100644 >--- a/LayoutTests/webgpu/buffer-resource-triangles.html >+++ b/LayoutTests/webgpu/buffer-resource-triangles.html >@@ -81,17 +81,13 @@ function createUniformBufferBindGroupLayout(bindNum, stage = GPUShaderStageBit.V > } > > const vertexSize = 4 * 4; >-const verticesBufferSize = vertexSize * 3; > function createAndUploadVerticesBuffer(device) { >- const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- const arrayBuffer = new Float32Array([ >+ const vertexArray = new Float32Array([ > 0, 1, 0, 1, > -1, -1, 0, 1, > 1, -1, 0, 1 >- ]).buffer; >- >- buffer.setSubData(0, arrayBuffer); >- return buffer; >+ ]); >+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); > } > > function createFloat4Buffer(device, a, b, promises) { >diff --git a/LayoutTests/webgpu/compute-squares.html b/LayoutTests/webgpu/compute-squares.html >index fcacf92d72d753558a329165fe94128fa6d80213..39bffc08d2ab0961c4eaa65e69224fb6bc5ca320 100644 >--- a/LayoutTests/webgpu/compute-squares.html >+++ b/LayoutTests/webgpu/compute-squares.html >@@ -39,8 +39,7 @@ promise_test(async () => { > const computeStageDescriptor = { module: shaderModule, entryPoint: "compute" }; > const pipeline = device.createComputePipeline({ computeStage: computeStageDescriptor }); > >- const dataBuffer = device.createBuffer({ size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ }); >- dataBuffer.setSubData(0, data.buffer); >+ const dataBuffer = createBufferWithData(device, { size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ }, data.buffer); > > const bgLayoutBinding = { binding: dataBinding, visibility: GPUShaderStageBit.COMPUTE, type: "storage-buffer" }; > const bgLayout = device.createBindGroupLayout({ bindings: [bgLayoutBinding] }); >diff --git a/LayoutTests/webgpu/depth-enabled-triangle-strip.html b/LayoutTests/webgpu/depth-enabled-triangle-strip.html >index 925c4c8ddefc3e5dc3d841a424fcb208791f397c..e903b1b1bdb86ae55ec8174bd9642e353ea6419e 100644 >--- a/LayoutTests/webgpu/depth-enabled-triangle-strip.html >+++ b/LayoutTests/webgpu/depth-enabled-triangle-strip.html >@@ -48,18 +48,14 @@ fragment float4 fragment_main(VertexOut v [[stage_in]]) > ` > > function createVertexBuffer(device) { >- const bufferSize = 4 * 4 * 4; >- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- const arrayBuffer = new Float32Array([ >+ const vertexArray = new Float32Array([ > // float4 xyzw > -1, 1, 0, 1, > -1, -1, 0, 1, > 1, 1, 0, 1, > 1, -1, 0, 1 >- ]).buffer; >- >- buffer.setSubData(0, arrayBuffer); >- return buffer; >+ ]); >+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); > } > > function createVertexInputDescriptor() { >diff --git a/LayoutTests/webgpu/draw-indexed-triangles.html b/LayoutTests/webgpu/draw-indexed-triangles.html >index 289e3bffff38cab342ec9bcb157aaf9ce36a89d4..3731f0b1572525bd9b1b3fc3ca8e1aefc11eb639 100644 >--- a/LayoutTests/webgpu/draw-indexed-triangles.html >+++ b/LayoutTests/webgpu/draw-indexed-triangles.html >@@ -53,10 +53,7 @@ function createVertexBuffer(device) { > 1, -1, 0, 1, 0, > 1, -1, 0, 1, 1 > ]); >- const buffer = device.createBuffer({ size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- buffer.setSubData(0, vertexArray.buffer); >- >- return buffer; >+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer); > } > > const indexBufferOffset = 2048; // Test a buffer offset for index array. >@@ -65,8 +62,15 @@ const indexOffset = -9001; // Test a base index to add to index array values. > function createIndexBuffer(device) { > const offsetArray = [1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; }); > const indexArray = new Uint32Array([1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; })); >- const buffer = device.createBuffer({ size: indexArray.byteLength + indexBufferOffset, usage: GPUBufferUsage.INDEX | GPUBufferUsage.TRANSFER_DST }); >- buffer.setSubData(indexBufferOffset, indexArray.buffer); >+ const buffer = createBufferWithData( >+ device, >+ { >+ size: indexArray.byteLength + indexBufferOffset, >+ usage: GPUBufferUsage.INDEX >+ }, >+ indexArray.buffer, >+ indexBufferOffset >+ ); > > return buffer; > } >diff --git a/LayoutTests/webgpu/js/webgpu-functions.js b/LayoutTests/webgpu/js/webgpu-functions.js >index 1cc6d6e2798fb44f705fa96f71a8a051a6f36acf..8a53bd7cf649b964b8024a82246b54c6bc9d6e42 100644 >--- a/LayoutTests/webgpu/js/webgpu-functions.js >+++ b/LayoutTests/webgpu/js/webgpu-functions.js >@@ -87,4 +87,19 @@ function encodeBasicCommands(renderPassEncoder, renderPipeline, vertexBuffer) { > renderPassEncoder.setPipeline(renderPipeline); > renderPassEncoder.draw(4, 1, 0, 0); > renderPassEncoder.endPass(); >+} >+ >+function createBufferWithData(device, descriptor, data, offset = 0) { >+ const mappedBuffer = device.createBufferMapped(descriptor); >+ const dataArray = new Uint8Array(mappedBuffer[1]); >+ dataArray.set(new Uint8Array(data), offset); >+ mappedBuffer[0].unmap(); >+ return mappedBuffer[0]; >+} >+ >+async function mapWriteDataToBuffer(buffer, data, offset = 0) { >+ const arrayBuffer = await buffer.mapWriteAsync(); >+ const writeArray = new Uint8Array(arrayBuffer); >+ writeArray.set(new Uint8Array(data), offset); >+ buffer.unmap(); > } >\ No newline at end of file >diff --git a/LayoutTests/webgpu/map-read-buffers-expected.txt b/LayoutTests/webgpu/map-read-buffers-expected.txt >index e3795794d32f4b15c5e7c3ce2dc60478faea188e..6015e0ce1e76eca1fb43baace0b9cca521afdeb6 100644 >--- a/LayoutTests/webgpu/map-read-buffers-expected.txt >+++ b/LayoutTests/webgpu/map-read-buffers-expected.txt >@@ -1,5 +1,6 @@ > >-PASS setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer. >+PASS mapReadAsync, unmap, and destroy on a GPUBuffer. >+PASS GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped. > PASS Reject a map read on a buffer not created with MAP_READ usage. > PASS Reject a map read on a mapped GPUBuffer. > PASS Reject a pending map read if GPUBuffer is unmapped. >diff --git a/LayoutTests/webgpu/map-read-buffers.html b/LayoutTests/webgpu/map-read-buffers.html >index 58ce09198892e758d944cbc5b80dbcab0d825650..442549dd4f48db1b94327f3fc31d1b3c331b5627 100644 >--- a/LayoutTests/webgpu/map-read-buffers.html >+++ b/LayoutTests/webgpu/map-read-buffers.html >@@ -1,6 +1,6 @@ > <!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] --> > <meta charset=utf-8> >-<title>Tests for setSubData and mapReadAsync on a GPUBuffer.</title> >+<title>Tests for createBufferMapped and mapReadAsync on a GPUBuffer.</title> > <body> > <script src="../resources/testharness.js"></script> > <script src="../resources/testharnessreport.js"></script> >@@ -11,24 +11,14 @@ async function runTests() { > > // Basic mapReadAsync functionality > promise_test(async () => { >- const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ }); >+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ }); > assert_true(buffer instanceof GPUBuffer, "createBuffer returned a GPUBuffer"); > >- let array = new Float32Array([1, 2, 3, 4]); >- buffer.setSubData(0, array.buffer); >- > let arrayBuffer = await buffer.mapReadAsync(); > assert_true(arrayBuffer instanceof ArrayBuffer, "first mapReadAsync resolved successfully"); > > const readArray = new Float32Array(arrayBuffer); >- assert_equals(readArray[3], 4, "successfully map-read value set by setSubData"); >- >- buffer.unmap(); >- >- buffer.setSubData(4 * 3, array.slice(0, 1).buffer); >- let arrayBuffer1 = await buffer.mapReadAsync(); >- const readArray1 = new Float32Array(arrayBuffer1); >- assert_equals(readArray[3], 1, "successfully setSubData with an offset"); >+ assert_equals(readArray[0], 0, "successfully access a value from a map read"); > > buffer.unmap(); > >@@ -40,7 +30,41 @@ async function runTests() { > assert_unreached("Buffer was destroyed!"); > }, () => {}); > >- }, "setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer."); >+ }, "mapReadAsync, unmap, and destroy on a GPUBuffer."); >+ >+ // GPUDevice.createBufferMapped >+ promise_test(async () => { >+ const bufferResult = device.createBufferMapped({ size: 16, usage: GPUBufferUsage.MAP_READ }); >+ const buffer = bufferResult[0]; >+ const arrayBuffer = bufferResult[1]; >+ >+ assert_true(buffer instanceof GPUBuffer, "createBufferMapped returned a GPUBuffer"); >+ assert_true(arrayBuffer instanceof ArrayBuffer, "createBufferMapped returned an ArrayBuffer"); >+ >+ let array = new Float32Array(arrayBuffer); >+ array.set([1, 2, 3, 4]); >+ >+ // Buffer should already be "mapped". >+ await buffer.mapReadAsync().then(() => { >+ assert_unreached("GPUBuffer created via GPUBufferMapped cannot be mapped until after first unmap!"); >+ }, () => {}); >+ >+ buffer.unmap(); >+ >+ // Buffer should not be re-mappable for writes. >+ await buffer.mapWriteAsync().then(() => { >+ assert_unreached("Buffer was not created with MAP_WRITE!"); >+ }, () => {}); >+ >+ // Read results of original writes. >+ let resultArrayBuffer = await buffer.mapReadAsync(); >+ const resultArray = new Float32Array(resultArrayBuffer); >+ resultArray.forEach((v, i) => { >+ assert_equals(v, array[i], "Successfully map-read value written to GPUBuffer mapped on creation"); >+ }) >+ >+ buffer.destroy(); >+ }, "GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped."); > > /* Basic validation */ > // FIXME: Test invalid combinations of GPUBufferUsage after implementing error handling. >diff --git a/LayoutTests/webgpu/texture-triangle-strip.html b/LayoutTests/webgpu/texture-triangle-strip.html >index 33a0e659959a1b99aff46cfa82651dfc6f119a58..88e2cad4e2760c85b4726afd9fd6ab1b15730a48 100644 >--- a/LayoutTests/webgpu/texture-triangle-strip.html >+++ b/LayoutTests/webgpu/texture-triangle-strip.html >@@ -89,8 +89,7 @@ async function test() { > 1, 1, 0, 1, > 1, -1, 0, 1 > ]); >- const positionBuffer = device.createBuffer({ size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- positionBuffer.setSubData(0, positionArray.buffer); >+ const positionBuffer = createBufferWithData(device, { size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX }, positionArray.buffer); > > const texCoordsArray = new Float32Array([ > // float2 texCoords >@@ -99,8 +98,7 @@ async function test() { > 1, 0, > 1, 1 > ]); >- const textureCoordBuffer = device.createBuffer({ size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- textureCoordBuffer.setSubData(0, texCoordsArray.buffer); >+ const textureCoordBuffer = createBufferWithData(device, { size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX }, texCoordsArray.buffer); > > const vertexInputDescriptor = createVertexInputDescriptor(); > >@@ -122,10 +120,9 @@ async function test() { > > const textureBufferDescriptor = { > size: imageData.data.length, >- usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST >+ usage: GPUBufferUsage.TRANSFER_SRC > }; >- const textureBuffer = device.createBuffer(textureBufferDescriptor); >- textureBuffer.setSubData(0, imageData.data.buffer); >+ const textureBuffer = createBufferWithData(device, textureBufferDescriptor, imageData.data.buffer); > > // Create GPUTexture > const textureSize = { >diff --git a/LayoutTests/webgpu/vertex-buffer-triangle-strip.html b/LayoutTests/webgpu/vertex-buffer-triangle-strip.html >index acd4cee2b277de75f780adfe5b2c54fa33b4bdf7..f1fcaa9f306335536ad024f87f54e791875b8780 100644 >--- a/LayoutTests/webgpu/vertex-buffer-triangle-strip.html >+++ b/LayoutTests/webgpu/vertex-buffer-triangle-strip.html >@@ -42,22 +42,22 @@ fragment float4 fragment_main(VertexOut v [[stage_in]]) > ` > > function createVertexBuffer(device) { >- const bufferSize = 4 * 5 * 4; >- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST }); >- const vertexArrayBuffer0 = new Float32Array([ >+ const vertexArray = new Float32Array([ > // float4 xyzw, float g > -1, 1, 0, 1, 1, >- -1, -1, 0, 1, 1 >- ]).buffer; >- const vertexArrayBuffer1 = new Float32Array([ >+ -1, -1, 0, 1, 1, > 1, 1, 0, 1, 1, > 1, -1, 0, 1, 1 >- ]).buffer; >+ ]); > >- buffer.setSubData(0, vertexArrayBuffer0); >- buffer.setSubData(4 * 5 * 2, vertexArrayBuffer1); >- >- return buffer; >+ return createBufferWithData( >+ device, >+ { >+ size: vertexArray.byteLength, >+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE >+ }, >+ vertexArray.buffer >+ ); > } > > function createVertexInputDescriptor() {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198591
: 371464