Changeset 249183 in webkit
- Timestamp:
- Aug 27, 2019, 4:39:38 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/webgpu/buffer-errors-expected.txt (added)
-
LayoutTests/webgpu/buffer-errors.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp (modified) (3 diffs)
-
Source/WebCore/Modules/webgpu/WebGPUBuffer.h (modified) (3 diffs)
-
Source/WebCore/Modules/webgpu/WebGPUDevice.cpp (modified) (2 diffs)
-
Source/WebCore/platform/graphics/gpu/GPUBuffer.h (modified) (6 diffs)
-
Source/WebCore/platform/graphics/gpu/GPUObjectBase.h (modified) (1 diff)
-
Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r249176 r249183 1 2019-08-27 Justin Fan <justin_fan@apple.com> 2 3 [WebGPU] Implement GPUErrors for and relax GPUBuffer validation rules 4 https://bugs.webkit.org/show_bug.cgi?id=200852 5 6 Reviewed by Dean Jackson. 7 8 Add a test to ensure GPUBuffer errors are generated properly. 9 10 * webgpu/buffer-errors-expected.txt: Added. 11 * webgpu/buffer-errors.html: Added. 12 1 13 2019-08-27 Russell Epstein <repstein@apple.com> 2 14 -
trunk/Source/WebCore/ChangeLog
r249177 r249183 1 2019-08-27 Justin Fan <justin_fan@apple.com> 2 3 [WebGPU] Implement GPUErrors for and relax GPUBuffer validation rules 4 https://bugs.webkit.org/show_bug.cgi?id=200852 5 6 Reviewed by Dean Jackson. 7 8 Fix incorrect usage validation during GPUBuffer creation. 9 Implement GPUError reporting for GPUBuffer creation and methods. 10 11 Test: webgpu/buffer-errors.html 12 13 * Modules/webgpu/WebGPUBuffer.cpp: 14 (WebCore::WebGPUBuffer::create): 15 (WebCore::WebGPUBuffer::WebGPUBuffer): 16 (WebCore::WebGPUBuffer::unmap): 17 (WebCore::WebGPUBuffer::destroy): 18 (WebCore::WebGPUBuffer::rejectOrRegisterPromiseCallback): 19 * Modules/webgpu/WebGPUBuffer.h: Now inherits from GPUObjectBase. 20 * Modules/webgpu/WebGPUDevice.cpp: 21 (WebCore::WebGPUDevice::createBuffer const): 22 (WebCore::WebGPUDevice::createBufferMapped const): 23 * platform/graphics/gpu/GPUBuffer.h: No longer inherits from GPUObjectBase. 24 * platform/graphics/gpu/GPUObjectBase.h: 25 (WebCore::GPUObjectBase::errorScopes): 26 (WebCore::GPUObjectBase::generateError): Deleted. 27 * platform/graphics/gpu/cocoa/GPUBufferMetal.mm: 28 (WebCore::GPUBuffer::validateBufferUsage): 29 (WebCore::GPUBuffer::tryCreate): Alignment issue should be general WebGPU requirement. 30 (WebCore::GPUBuffer::GPUBuffer): 31 (WebCore::GPUBuffer::~GPUBuffer): Must do cleanup without generating errors. 32 (WebCore::GPUBuffer::registerMappingCallback): 33 (WebCore::GPUBuffer::copyStagingBufferToGPU): 34 (WebCore::GPUBuffer::unmap): 35 (WebCore::GPUBuffer::destroy): 36 1 37 2019-08-27 Zalan Bujtas <zalan@apple.com> 2 38 -
trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp
r246217 r249183 29 29 #if ENABLE(WEBGPU) 30 30 31 #include "Logging.h" 31 #include "GPUErrorScopes.h" 32 #include <wtf/text/StringConcatenate.h> 32 33 33 34 namespace WebCore { 34 35 35 Ref<WebGPUBuffer> WebGPUBuffer::create(RefPtr<GPUBuffer>&& buffer )36 Ref<WebGPUBuffer> WebGPUBuffer::create(RefPtr<GPUBuffer>&& buffer, GPUErrorScopes& errorScopes) 36 37 { 37 return adoptRef(*new WebGPUBuffer(WTFMove(buffer) ));38 return adoptRef(*new WebGPUBuffer(WTFMove(buffer), errorScopes)); 38 39 } 39 40 40 WebGPUBuffer::WebGPUBuffer(RefPtr<GPUBuffer>&& buffer) 41 : m_buffer(WTFMove(buffer)) 41 WebGPUBuffer::WebGPUBuffer(RefPtr<GPUBuffer>&& buffer, GPUErrorScopes& errorScopes) 42 : GPUObjectBase(makeRef(errorScopes)) 43 , m_buffer(WTFMove(buffer)) 42 44 { 43 45 } … … 55 57 void WebGPUBuffer::unmap() 56 58 { 59 errorScopes().setErrorPrefix("GPUBuffer.unmap(): "); 60 57 61 if (!m_buffer) 58 LOG(WebGPU, "GPUBuffer::unmap(): Invalid operation!");62 errorScopes().generatePrefixedError("Invalid operation: invalid GPUBuffer!"); 59 63 else 60 m_buffer->unmap( );64 m_buffer->unmap(&errorScopes()); 61 65 } 62 66 63 67 void WebGPUBuffer::destroy() 64 68 { 69 errorScopes().setErrorPrefix("GPUBuffer.destroy(): "); 70 65 71 if (!m_buffer) 66 LOG(WebGPU, "GPUBuffer::destroy():Invalid operation!");72 errorScopes().generatePrefixedError("Invalid operation!"); 67 73 else { 68 m_buffer->destroy( );74 m_buffer->destroy(&errorScopes()); 69 75 m_buffer = nullptr; 70 76 } … … 73 79 void WebGPUBuffer::rejectOrRegisterPromiseCallback(BufferMappingPromise&& promise, bool isRead) 74 80 { 81 errorScopes().setErrorPrefix(makeString("GPUBuffer.map", isRead ? "Read" : "Write", "Async(): ")); 82 75 83 if (!m_buffer) { 76 LOG(WebGPU, "GPUBuffer::map%sAsync(): Invalid operation!", isRead ? "Read" : "Write");84 errorScopes().generatePrefixedError("Invalid operation: invalid GPUBuffer!"); 77 85 promise.reject(); 78 86 return; 79 87 } 80 88 81 m_buffer->registerMappingCallback([promise = WTFMove(promise) ] (JSC::ArrayBuffer* arrayBuffer) mutable {89 m_buffer->registerMappingCallback([promise = WTFMove(promise), protectedErrorScopes = makeRef(errorScopes())] (JSC::ArrayBuffer* arrayBuffer) mutable { 82 90 if (arrayBuffer) 83 91 promise.resolve(*arrayBuffer); 84 else 92 else { 93 protectedErrorScopes->generateError("", GPUErrorFilter::OutOfMemory); 85 94 promise.reject(); 86 }, isRead); 95 } 96 }, isRead, errorScopes()); 87 97 } 88 98 -
trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h
r246217 r249183 30 30 #include "GPUBuffer.h" 31 31 #include "GPUBufferUsage.h" 32 #include "GPUObjectBase.h" 32 33 #include "JSDOMPromiseDeferred.h" 33 #include <wtf/RefCounted.h>34 34 #include <wtf/RefPtr.h> 35 35 … … 42 42 struct GPUBufferDescriptor; 43 43 44 class WebGPUBuffer : public RefCounted<WebGPUBuffer>{44 class WebGPUBuffer : public GPUObjectBase { 45 45 public: 46 static Ref<WebGPUBuffer> create(RefPtr<GPUBuffer>&& );46 static Ref<WebGPUBuffer> create(RefPtr<GPUBuffer>&&, GPUErrorScopes&); 47 47 48 48 GPUBuffer* buffer() { return m_buffer.get(); } … … 56 56 57 57 private: 58 explicit WebGPUBuffer(RefPtr<GPUBuffer>&& );58 explicit WebGPUBuffer(RefPtr<GPUBuffer>&&, GPUErrorScopes&); 59 59 60 60 void rejectOrRegisterPromiseCallback(BufferMappingPromise&&, bool); -
trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
r249131 r249183 92 92 93 93 auto buffer = m_device->tryCreateBuffer(descriptor, GPUBufferMappedOption::NotMapped, m_errorScopes); 94 return WebGPUBuffer::create(WTFMove(buffer) );94 return WebGPUBuffer::create(WTFMove(buffer), m_errorScopes); 95 95 } 96 96 … … 107 107 } 108 108 109 auto webBuffer = WebGPUBuffer::create(WTFMove(buffer) );109 auto webBuffer = WebGPUBuffer::create(WTFMove(buffer), m_errorScopes); 110 110 auto wrappedWebBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), webBuffer); 111 111 -
trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
r248606 r249183 30 30 #include "DeferrableTask.h" 31 31 #include "GPUBufferUsage.h" 32 #include "GPUObjectBase.h"33 32 #include <wtf/Function.h> 34 33 #include <wtf/OptionSet.h> … … 50 49 51 50 class GPUDevice; 51 class GPUErrorScopes; 52 52 53 53 struct GPUBufferDescriptor; … … 62 62 using PlatformBufferSmartPtr = RetainPtr<PlatformBuffer>; 63 63 64 class GPUBuffer : public GPUObjectBase{64 class GPUBuffer : public RefCounted<GPUBuffer> { 65 65 public: 66 66 enum class State { … … 95 95 96 96 using MappingCallback = WTF::Function<void(JSC::ArrayBuffer*)>; 97 void registerMappingCallback(MappingCallback&&, bool );98 void unmap( );99 void destroy( );97 void registerMappingCallback(MappingCallback&&, bool, GPUErrorScopes&); 98 void unmap(GPUErrorScopes*); 99 void destroy(GPUErrorScopes*); 100 100 101 101 private: … … 112 112 }; 113 113 114 GPUBuffer(PlatformBufferSmartPtr&&, GPUDevice&, size_t, OptionSet<GPUBufferUsage::Flags>, GPUBufferMappedOption , GPUErrorScopes&);114 GPUBuffer(PlatformBufferSmartPtr&&, GPUDevice&, size_t, OptionSet<GPUBufferUsage::Flags>, GPUBufferMappedOption); 115 115 static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>, GPUErrorScopes&); 116 116 … … 118 118 JSC::ArrayBuffer* stagingBufferForWrite(); 119 119 void runMappingCallback(); 120 void copyStagingBufferToGPU( );120 void copyStagingBufferToGPU(GPUErrorScopes*); 121 121 122 122 bool isMapWrite() const { return m_usage.contains(GPUBufferUsage::Flags::MapWrite); } -
trunk/Source/WebCore/platform/graphics/gpu/GPUObjectBase.h
r247500 r249183 34 34 35 35 class GPUObjectBase : public RefCounted<GPUObjectBase> { 36 public:37 void generateError(const String& message, GPUErrorFilter filter = GPUErrorFilter::Validation)38 {39 m_errorScopes->generateError(message, filter);40 }41 42 36 protected: 43 37 GPUObjectBase(Ref<GPUErrorScopes>&& reporter) 44 38 : m_errorScopes(WTFMove(reporter)) { } 39 40 GPUErrorScopes& errorScopes() { return m_errorScopes; } 45 41 46 42 private: -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
r248606 r249183 31 31 #import "GPUBufferDescriptor.h" 32 32 #import "GPUDevice.h" 33 #import " Logging.h"33 #import "GPUErrorScopes.h" 34 34 #import <JavaScriptCore/ArrayBuffer.h> 35 35 #import <Metal/Metal.h> … … 47 47 { 48 48 if (!device.platformDevice()) { 49 LOG(WebGPU, "GPUBuffer::tryCreate():Invalid GPUDevice!");49 errorScopes.generatePrefixedError("Invalid GPUDevice!"); 50 50 return false; 51 51 } … … 53 53 if (usage.containsAll({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead })) { 54 54 errorScopes.generatePrefixedError("Buffer cannot have both MAP_READ and MAP_WRITE usage!"); 55 return false;56 }57 58 if (usage.containsAny(readOnlyFlags) && (usage & GPUBufferUsage::Flags::Storage)) {59 LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer cannot have both STORAGE and a read-only usage!");60 55 return false; 61 56 } … … 77 72 return nullptr; 78 73 79 #if PLATFORM(MAC)80 74 // copyBufferToBuffer calls require 4-byte alignment. "Unmapping" a mapped-on-creation GPUBuffer 81 75 // that is otherwise unmappable requires such a copy to upload data. … … 83 77 && !usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead }) 84 78 && descriptor.size % 4) { 85 LOG(WebGPU, "GPUBuffer::tryCreate(): Data must be aligned to a multiple of 4 bytes!"); 86 return nullptr; 87 } 88 #endif 79 errorScopes.generatePrefixedError("Data must be aligned to a multiple of 4 bytes!"); 80 return nullptr; 81 } 89 82 90 83 // 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. … … 108 101 } 109 102 110 return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), device, size, usage, isMapped, errorScopes)); 111 } 112 113 GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, GPUDevice& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, GPUBufferMappedOption isMapped, GPUErrorScopes& errorScopes) 114 : GPUObjectBase(makeRef(errorScopes)) 115 , m_platformBuffer(WTFMove(buffer)) 103 return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), device, size, usage, isMapped)); 104 } 105 106 GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, GPUDevice& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, GPUBufferMappedOption isMapped) 107 : m_platformBuffer(WTFMove(buffer)) 116 108 , m_device(makeRef(device)) 117 109 , m_byteLength(size) … … 126 118 GPUBuffer::~GPUBuffer() 127 119 { 128 destroy( );120 destroy(nullptr); 129 121 } 130 122 … … 178 170 #endif // USE(METAL) 179 171 180 void GPUBuffer::registerMappingCallback(MappingCallback&& callback, bool isRead )172 void GPUBuffer::registerMappingCallback(MappingCallback&& callback, bool isRead, GPUErrorScopes& errorScopes) 181 173 { 182 174 // Reject if request is invalid. 183 175 if (isRead && !isMapReadable()) { 184 LOG(WebGPU, "GPUBuffer::mapReadAsync():Invalid operation!");176 errorScopes.generatePrefixedError("Invalid operation!"); 185 177 callback(nullptr); 186 178 return; 187 179 } 188 180 if (!isRead && !isMapWriteable()) { 189 LOG(WebGPU, "GPUBuffer::mapWriteAsync():Invalid operation!");181 errorScopes.generatePrefixedError("Invalid operation!"); 190 182 callback(nullptr); 191 183 return; … … 227 219 } 228 220 229 void GPUBuffer::copyStagingBufferToGPU( )221 void GPUBuffer::copyStagingBufferToGPU(GPUErrorScopes* errorScopes) 230 222 { 231 223 MTLCommandQueue *queue; … … 240 232 END_BLOCK_OBJC_EXCEPTIONS; 241 233 242 if (!stagingMtlBuffer ) {243 LOG(WebGPU, "GPUBuffer::unmap(): Unable to create staging buffer!");234 if (!stagingMtlBuffer && errorScopes) { 235 errorScopes->generateError("", GPUErrorFilter::OutOfMemory); 244 236 return; 245 237 } … … 259 251 } 260 252 261 void GPUBuffer::unmap( )262 { 263 if (!m_isMappedFromCreation && !isMappable() ) {264 LOG(WebGPU, "GPUBuffer::unmap(): Invalid operation: buffer is not mappable!");253 void GPUBuffer::unmap(GPUErrorScopes* errorScopes) 254 { 255 if (!m_isMappedFromCreation && !isMappable() && errorScopes) { 256 errorScopes->generatePrefixedError("Invalid operation: GPUBuffer is not mappable!"); 265 257 return; 266 258 } … … 272 264 memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength); 273 265 } else if (m_isMappedFromCreation) 274 copyStagingBufferToGPU( );266 copyStagingBufferToGPU(errorScopes); 275 267 276 268 m_isMappedFromCreation = false; … … 285 277 } 286 278 287 void GPUBuffer::destroy( )279 void GPUBuffer::destroy(GPUErrorScopes* errorScopes) 288 280 { 289 281 if (state() == State::Mapped) 290 unmap( );282 unmap(errorScopes); 291 283 292 284 m_platformBuffer = nullptr;
Note:
See TracChangeset
for help on using the changeset viewer.