Changeset 244235 in webkit
- Timestamp:
- Apr 12, 2019, 4:40:53 PM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
-
ChangeLog (modified) (1 diff)
-
platform/graphics/gpu/GPUBuffer.h (modified) (3 diffs)
-
platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm (modified) (3 diffs)
-
platform/graphics/gpu/cocoa/GPUBufferMetal.mm (modified) (6 diffs)
-
platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm (modified) (6 diffs)
-
platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm (modified) (1 diff)
-
platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r244234 r244235 1 2019-04-12 Justin Fan <justin_fan@apple.com> 2 3 [Web GPU] Prevent narrowing conversions during Metal function calls on 32-bit platforms 4 https://bugs.webkit.org/show_bug.cgi?id=196793 5 6 Reviewed by Darin Adler. 7 8 On 32-bit platforms, NSUInteger is 32-bit, which limits certain Web GPU parameters. 9 Ensure that valid parameters are properly converted to NSUInteger for Metal calls, regardless of platform. 10 11 * platform/graphics/gpu/GPUBuffer.h: 12 (WebCore::GPUBuffer::byteLength const): 13 * platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm: 14 (WebCore::tryGetResourceAsBufferBinding): 15 (WebCore::setBufferOnEncoder): 16 * platform/graphics/gpu/cocoa/GPUBufferMetal.mm: 17 (WebCore::GPUBuffer::validateBufferUsage): 18 (WebCore::GPUBuffer::tryCreate): 19 (WebCore::GPUBuffer::GPUBuffer): 20 (WebCore::GPUBuffer::setSubData): 21 * platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm: 22 (WebCore::GPUCommandBuffer::copyBufferToBuffer): 23 (WebCore::GPUCommandBuffer::copyBufferToTexture): 24 (WebCore::GPUCommandBuffer::copyTextureToBuffer): 25 * platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm: 26 (WebCore::GPURenderPassEncoder::drawIndexed): 27 * platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm: 28 (WebCore::trySetInputStateForPipelineDescriptor): 29 1 30 2019-04-12 Ross Kirsling <ross.kirsling@sony.com> 2 31 -
trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h
r244147 r244235 72 72 73 73 PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); } 74 uint64_t byteLength() const { return m_byteLength; }74 size_t byteLength() const { return m_byteLength; } 75 75 bool isTransferSource() const { return m_usage.contains(GPUBufferUsage::Flags::TransferSource); } 76 76 bool isTransferDestination() const { return m_usage.contains(GPUBufferUsage::Flags::TransferDestination); } … … 111 111 static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>); 112 112 113 GPUBuffer(PlatformBufferSmartPtr&&, uint64_t, OptionSet<GPUBufferUsage::Flags>, Ref<GPUDevice>&&);113 GPUBuffer(PlatformBufferSmartPtr&&, size_t, OptionSet<GPUBufferUsage::Flags>, Ref<GPUDevice>&&); 114 114 115 115 JSC::ArrayBuffer* stagingBufferForRead(); … … 133 133 DeferrableTask<Timer> m_mappingCallbackTask; 134 134 135 uint64_t m_byteLength;135 size_t m_byteLength; 136 136 OptionSet<GPUBufferUsage::Flags> m_usage; 137 137 unsigned m_numScheduledCommandBuffers { 0 }; -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm
r243636 r244235 36 36 #import <Metal/Metal.h> 37 37 #import <wtf/BlockObjCExceptions.h> 38 #import <wtf/CheckedArithmetic.h> 38 39 #import <wtf/Optional.h> 39 40 … … 64 65 return WTF::nullopt; 65 66 } 67 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 68 if (!WTF::isInBounds<NSUInteger>(bufferBinding.offset)) { 69 LOG(WebGPU, "%s: Buffer offset is too large!", functionName); 70 return WTF::nullopt; 71 } 66 72 return GPUBufferBinding { bufferBinding.buffer.copyRef(), bufferBinding.offset, bufferBinding.size }; 67 73 } … … 72 78 73 79 BEGIN_BLOCK_OBJC_EXCEPTIONS; 74 [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:bufferBinding.offset atIndex:index]; 80 // Bounds check when converting GPUBufferBinding ensures that NSUInteger cast of uint64_t offset is safe. 81 [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:static_cast<NSUInteger>(bufferBinding.offset) atIndex:index]; 75 82 END_BLOCK_OBJC_EXCEPTIONS; 76 83 } -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm
r243658 r244235 46 46 { 47 47 if (!device.platformDevice()) { 48 LOG(WebGPU, "GPUBuffer:: create(): Invalid GPUDevice!");48 LOG(WebGPU, "GPUBuffer::tryCreate(): Invalid GPUDevice!"); 49 49 return false; 50 50 } 51 51 52 52 if (usage.containsAll({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead })) { 53 LOG(WebGPU, "GPUBuffer:: create(): Buffer cannot have both MAP_READ and MAP_WRITE usage!");53 LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer cannot have both MAP_READ and MAP_WRITE usage!"); 54 54 return false; 55 55 } 56 56 57 57 if (usage.containsAny(readOnlyFlags) && (usage & GPUBufferUsage::Flags::Storage)) { 58 LOG(WebGPU, "GPUBuffer:: create(): Buffer cannot have both STORAGE and a read-only usage!");58 LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer cannot have both STORAGE and a read-only usage!"); 59 59 return false; 60 60 } … … 65 65 RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor) 66 66 { 67 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 68 NSUInteger size = 0; 69 if (!WTF::convertSafely<NSUInteger, uint64_t>(descriptor.size, size)) { 70 LOG(WebGPU, "GPUBuffer::tryCreate(): Buffer size is too large!"); 71 return nullptr; 72 } 73 67 74 auto usage = OptionSet<GPUBufferUsage::Flags>::fromRaw(descriptor.usage); 68 75 if (!validateBufferUsage(device.get(), usage)) … … 80 87 BEGIN_BLOCK_OBJC_EXCEPTIONS; 81 88 82 mtlBuffer = adoptNS([device->platformDevice() newBufferWithLength: descriptor.sizeoptions:resourceOptions]);89 mtlBuffer = adoptNS([device->platformDevice() newBufferWithLength:static_cast<NSUInteger>(descriptor.size) options:resourceOptions]); 83 90 84 91 END_BLOCK_OBJC_EXCEPTIONS; 85 92 86 93 if (!mtlBuffer) { 87 LOG(WebGPU, "GPUBuffer:: create(): Unable to create MTLBuffer!");94 LOG(WebGPU, "GPUBuffer::tryCreate(): Unable to create MTLBuffer!"); 88 95 return nullptr; 89 96 } 90 97 91 return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), descriptor.size, usage, WTFMove(device)));92 } 93 94 GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, uint64_t size, OptionSet<GPUBufferUsage::Flags> usage, Ref<GPUDevice>&& device)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) 95 102 : m_platformBuffer(WTFMove(buffer)) 96 103 , m_device(WTFMove(device)) … … 137 144 } 138 145 #endif 139 140 auto subDataLength = checkedSum< uint64_t>(data.byteLength(), offset);146 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 147 auto subDataLength = checkedSum<NSUInteger>(data.byteLength(), offset); 141 148 if (subDataLength.hasOverflowed() || subDataLength.unsafeGet() > m_byteLength) { 142 149 LOG(WebGPU, "GPUBuffer::setSubData(): Invalid offset or data size!"); … … 146 153 if (m_subDataBuffers.isEmpty()) { 147 154 BEGIN_BLOCK_OBJC_EXCEPTIONS; 148 m_subDataBuffers.append(adoptNS([m_platformBuffer.get().device newBufferWithLength: m_byteLengthoptions:MTLResourceCPUCacheModeDefaultCache]));155 m_subDataBuffers.append(adoptNS([m_platformBuffer.get().device newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache])); 149 156 END_BLOCK_OBJC_EXCEPTIONS; 150 157 } … … 164 171 auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]); 165 172 166 [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset: offsetsize:stagingMtlBuffer.get().length];173 [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:static_cast<NSUInteger>(offset) size:stagingMtlBuffer.get().length]; 167 174 [blitEncoder endEncoding]; 168 175 -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUCommandBufferMetal.mm
r244147 r244235 108 108 #endif 109 109 110 auto srcLength = checkedSum<uint64_t>(size, srcOffset); 111 auto dstLength = checkedSum<uint64_t>(size, dstOffset); 110 // This call ensures that size, offset, and size + offset can safely fit in NSUInteger regardless of platform. 111 auto srcLength = checkedSum<NSUInteger>(size, srcOffset); 112 auto dstLength = checkedSum<NSUInteger>(size, dstOffset); 112 113 if (srcLength.hasOverflowed() || dstLength.hasOverflowed() 113 114 || srcLength.unsafeGet() > src->byteLength() || dstLength.unsafeGet() > dst->byteLength()) { … … 118 119 BEGIN_BLOCK_OBJC_EXCEPTIONS; 119 120 121 // These casts are safe due to earlier checkedSum() checks. 120 122 [blitEncoder() 121 123 copyFromBuffer:src->platformBuffer() 122 sourceOffset:s rcOffset124 sourceOffset:static_cast<NSUInteger>(srcOffset) 123 125 toBuffer:dst->platformBuffer() 124 destinationOffset: dstOffset125 size:s ize];126 destinationOffset:static_cast<NSUInteger>(dstOffset) 127 size:static_cast<NSUInteger>(size)]; 126 128 127 129 END_BLOCK_OBJC_EXCEPTIONS; … … 138 140 } 139 141 142 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 143 NSUInteger sourceOffset = 0; 144 if (!WTF::convertSafely<NSUInteger, uint64_t>(srcBuffer.offset, sourceOffset)) { 145 LOG(WebGPU, "GPUCommandBuffer::copyBufferToTexture(): Source offset is too large!"); 146 return; 147 } 148 140 149 // FIXME: Add Metal validation. 141 150 … … 154 163 [blitEncoder() 155 164 copyFromBuffer:srcBuffer.buffer->platformBuffer() 156 sourceOffset:s rcBuffer.offset165 sourceOffset:sourceOffset 157 166 sourceBytesPerRow:srcBuffer.rowPitch 158 167 sourceBytesPerImage:srcBuffer.imageHeight … … 175 184 return; 176 185 } 186 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 187 NSUInteger destinationOffset = 0; 188 if (!WTF::convertSafely<NSUInteger, uint64_t>(dstBuffer.offset, destinationOffset)) { 189 LOG(WebGPU, "GPUCommandBuffer::copyTextureToBuffer(): Destination offset is too large!"); 190 return; 191 } 177 192 178 193 // FIXME: Add Metal validation? … … 187 202 sourceSize:MTLSizeMake(size.width, size.height, size.depth) 188 203 toBuffer:dstBuffer.buffer->platformBuffer() 189 destinationOffset:d stBuffer.offset204 destinationOffset:destinationOffset 190 205 destinationBytesPerRow:dstBuffer.rowPitch 191 206 destinationBytesPerImage:dstBuffer.imageHeight]; -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm
r244147 r244235 357 357 358 358 auto indexByteSize = (m_pipeline->indexFormat() == GPUIndexFormat::Uint16) ? sizeof(uint16_t) : sizeof(uint32_t); 359 360 // This calculation cannot overflow as firstIndex is bounded to 32 bits, and indexByteSize to sizeof(uint32_t). 359 361 uint64_t firstIndexOffset = firstIndex * indexByteSize; 360 auto totalOffset = checkedSum<uint64_t>(firstIndexOffset, m_indexBufferOffset); 362 363 // This call ensures that neither argument nor their sum will overflow NSUInteger. 364 auto totalOffset = checkedSum<NSUInteger>(firstIndexOffset, m_indexBufferOffset); 361 365 if (totalOffset.hasOverflowed() || totalOffset >= m_indexBuffer->byteLength()) { 362 366 LOG(WebGPU, "%s: Invalid firstIndex!", functionName); -
trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm
r244147 r244235 37 37 #import <Metal/Metal.h> 38 38 #import <wtf/BlockObjCExceptions.h> 39 #import <wtf/CheckedArithmetic.h> 39 40 #import <wtf/OptionSet.h> 40 41 #import <wtf/Optional.h> … … 340 341 return false; 341 342 } 343 // MTLBuffer size (NSUInteger) is 32 bits on some platforms. 344 // FIXME: Ensure offset < buffer's stride + format's data size. 345 NSUInteger attributeOffset = 0; 346 if (!WTF::convertSafely<NSUInteger, uint64_t>(attributes[i].offset, attributeOffset)) { 347 LOG(WebGPU, "%s: Buffer offset for vertex attribute %u is too large!", functionName, location); 348 return false; 349 } 342 350 343 351 auto mtlAttributeDesc = retainPtr([attributeArray objectAtIndexedSubscript:location]); 344 352 [mtlAttributeDesc setFormat:mtlVertexFormatForGPUVertexFormat(attributes[i].format)]; 345 [mtlAttributeDesc setOffset:attribute s[i].offset]; // FIXME: After adding more vertex formats, ensure offset < buffer's stride + format's data size.353 [mtlAttributeDesc setOffset:attributeOffset]; 346 354 [mtlAttributeDesc setBufferIndex:WHLSL::Metal::calculateVertexBufferIndex(attributes[i].inputSlot)]; 347 355 } … … 357 365 return false; 358 366 } 367 NSUInteger inputStride = 0; 368 if (!WTF::convertSafely<NSUInteger, uint64_t>(inputs[j].stride, inputStride)) { 369 LOG(WebGPU, "%s: Stride for vertex buffer slot %d is too large!", functionName, slot); 370 return false; 371 } 359 372 360 373 auto convertedSlot = WHLSL::Metal::calculateVertexBufferIndex(slot); 361 374 auto mtlLayoutDesc = retainPtr([layoutArray objectAtIndexedSubscript:convertedSlot]); 362 375 [mtlLayoutDesc setStepFunction:mtlStepFunctionForGPUInputStepMode(inputs[j].stepMode)]; 363 [mtlLayoutDesc setStride:input s[j].stride];376 [mtlLayoutDesc setStride:inputStride]; 364 377 } 365 378
Note:
See TracChangeset
for help on using the changeset viewer.