[webkit-reviews] review granted: [Bug 187333] Improve WebGPU implementation, including using Metal Objective-C protocols more simply and correctly : [Attachment 344307] Patch
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Fri Jul 6 18:03:31 PDT 2018
Sam Weinig <sam at webkit.org> has granted Darin Adler <darin at apple.com>'s request
for review:
Bug 187333: Improve WebGPU implementation, including using Metal Objective-C
protocols more simply and correctly
https://bugs.webkit.org/show_bug.cgi?id=187333
Attachment 344307: Patch
https://bugs.webkit.org/attachment.cgi?id=344307&action=review
--- Comment #15 from Sam Weinig <sam at webkit.org> ---
Comment on attachment 344307
--> https://bugs.webkit.org/attachment.cgi?id=344307
Patch
View in context: https://bugs.webkit.org/attachment.cgi?id=344307&action=review
> Source/WebCore/ChangeLog:74
> + (WebCore::WebGPUBuffer::create): Return nullptr if we fail to create
a GPU buffer.
> + Also use more references rather than pointers for things that are
never null.
This is a change in behavior (we always used to return an object). What is
motivating this change? Do we have a test for this new behavior?
> Source/WebCore/ChangeLog:268
> + * platform/graphics/cocoa/GPUBufferMetal.mm:
Instead of being in the platform/graphics/cocoa directory, should we move this
(and all the other metal files, to a platform/graphics/metal directory?
> Source/WTF/wtf/Compiler.h:303
> +#if !defined(OBJC_PROTOCOL) && defined(__OBJC__)
> +#define OBJC_PROTOCOL(protocolName) @protocol protocolName; using
protocolName = NSObject <protocolName>
> +#endif
I'm not clear on what the 'using...' part is doing. Might be worth a comment.
> Source/WebCore/html/canvas/WebGPUCommandBuffer.cpp:75
> RefPtr<WebGPURenderCommandEncoder>
WebGPUCommandBuffer::createRenderCommandEncoderWithDescriptor(WebGPURenderPassD
escriptor& descriptor)
> {
> - RefPtr<WebGPURenderCommandEncoder> commandEncoder =
WebGPURenderCommandEncoder::create(this->context(), this, &descriptor);
> - return commandEncoder;
> + return WebGPURenderCommandEncoder::create(*context(), m_buffer,
descriptor.descriptor());
> }
It looks like WebGPURenderCommandEncoder::create returns a
Ref<WebGPURenderCommandEncoder>, so this function could as well.
> Source/WebCore/html/canvas/WebGPUCommandBuffer.cpp:80
> RefPtr<WebGPUComputeCommandEncoder>
WebGPUCommandBuffer::createComputeCommandEncoder()
> {
> - RefPtr<WebGPUComputeCommandEncoder> commandEncoder =
WebGPUComputeCommandEncoder::create(this->context(), this);
> - return commandEncoder;
> + return WebGPUComputeCommandEncoder::create(*context(), m_buffer);
> }
Ditto.
> Source/WebCore/html/canvas/WebGPUCommandQueue.cpp:52
> RefPtr<WebGPUCommandBuffer> WebGPUCommandQueue::createCommandBuffer()
> {
> - RefPtr<WebGPUCommandBuffer> buffer =
WebGPUCommandBuffer::create(this->context(), this);
> - return buffer;
> + return WebGPUCommandBuffer::create(*context(), m_queue);
> }
WebGPUCommandBuffer::create returns a Ref<WebGPUCommandBuffer>, so this
function can as well.
> Source/WebCore/html/canvas/WebGPUDrawable.cpp:45
> + , m_texture { WebGPUTexture::createFromDrawableTexture(context,
GPUTexture { m_drawable }) }
WebGPUTexture::createFromDrawableTexture returns a Ref<WebGPUTexture>, so
m_texture can be a Ref<WebGPUTexture>.
> Source/WebCore/html/canvas/WebGPULibrary.cpp:58
> + auto function = WebGPUFunction::create(*context(), m_library, name);
> if (!function->function())
> return nullptr;
> - return function;
> + return WTFMove(function);
It seems like this could be done slightly more efficiently if the GPUFunction
was created first, checked to see if the function was non-null, and then only
if it was non-null, moved into a newly created WebGPUFunction. This would avoid
the allocation of the WebGPUFunction in the case that the function doesn't
exist.
> Source/WebCore/html/canvas/WebGPURenderPassDescriptor.cpp:47
> -RefPtr<WebGPURenderPassDepthAttachmentDescriptor>
WebGPURenderPassDescriptor::depthAttachment()
> +WebGPURenderPassDepthAttachmentDescriptor*
WebGPURenderPassDescriptor::depthAttachment()
> {
> - if (!m_renderPassDescriptor)
> - return nullptr;
> -
> - if (!m_depthAttachmentDescriptor) {
> - RefPtr<GPURenderPassDepthAttachmentDescriptor>
platformDepthAttachment = m_renderPassDescriptor->depthAttachment();
> - m_depthAttachmentDescriptor =
WebGPURenderPassDepthAttachmentDescriptor::create(this->context(),
platformDepthAttachment.get());
> - }
> - return m_depthAttachmentDescriptor;
> + if (!m_depthAttachment)
> + m_depthAttachment =
WebGPURenderPassDepthAttachmentDescriptor::create(*context(),
m_descriptor.depthAttachment());
> + return m_depthAttachment.get();
> }
WebGPURenderPassDepthAttachmentDescriptor::create returns a
Ref<WebGPURenderPassDepthAttachmentDescriptor>, so I think this function can
also return a Ref<> (or a reference).
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:82
> - auto renderingContext = std::unique_ptr<WebGPURenderingContext>(new
WebGPURenderingContext(canvas, device.releaseNonNull()));
> + auto renderingContext = std::unique_ptr<WebGPURenderingContext>(new
WebGPURenderingContext(canvas, WTFMove(device)));
Can std::make_unique be used here?
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:162
> RefPtr<WebGPURenderPipelineState>
WebGPURenderingContext::createRenderPipelineState(WebGPURenderPipelineDescripto
r& descriptor)
> {
> - RefPtr<WebGPURenderPipelineState> state =
WebGPURenderPipelineState::create(this, &descriptor);
> - return state;
> + return WebGPURenderPipelineState::create(*this,
descriptor.descriptor());
> }
This can return a Ref<WebGPURenderPipelineState>.
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:167
> RefPtr<WebGPUDepthStencilState>
WebGPURenderingContext::createDepthStencilState(WebGPUDepthStencilDescriptor&
descriptor)
> {
> - RefPtr<WebGPUDepthStencilState> state =
WebGPUDepthStencilState::create(this, &descriptor);
> - return state;
> + return WebGPUDepthStencilState::create(*this, descriptor.descriptor());
> }
This can return a Ref<WebGPURenderPipelineState>
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:172
> RefPtr<WebGPUComputePipelineState>
WebGPURenderingContext::createComputePipelineState(WebGPUFunction& function)
> {
> - RefPtr<WebGPUComputePipelineState> state =
WebGPUComputePipelineState::create(this, &function);
> - return state;
> + return WebGPUComputePipelineState::create(*this, function.function());
> }
This can return a Ref<WebGPURenderPipelineState>.
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:177
> RefPtr<WebGPUCommandQueue> WebGPURenderingContext::createCommandQueue()
> {
> - RefPtr<WebGPUCommandQueue> queue = WebGPUCommandQueue::create(this);
> - return queue;
> + return WebGPUCommandQueue::create(*this);
> }
This can return a Ref<WebGPUCommandQueue>.
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:182
> RefPtr<WebGPUDrawable> WebGPURenderingContext::nextDrawable()
> {
> - RefPtr<WebGPUDrawable> drawable = WebGPUDrawable::create(this);
> - return drawable;
> + return WebGPUDrawable::create(*this);
> }
This can return a Ref<WebGPUDrawable>
> Source/WebCore/html/canvas/WebGPURenderingContext.cpp:192
> RefPtr<WebGPUTexture>
WebGPURenderingContext::createTexture(WebGPUTextureDescriptor& descriptor)
> {
> - RefPtr<WebGPUTexture> texture = WebGPUTexture::create(this,
&descriptor);
> - return texture;
> + return WebGPUTexture::create(*this, descriptor.descriptor());
> }
This can return a Ref<WebGPUTexture>.
> Source/WebCore/platform/graphics/cocoa/GPURenderPipelineDescriptorMetal.mm:59
> + if (!newFunction.metal())
> + return;
> + [m_metal setVertexFunction:newFunction.metal()];
This is changing behavior when newFunction.metal() is nil, it used to call
setVertexFunction with nil. Why is that the right change?
> Source/WebCore/platform/graphics/cocoa/GPURenderPipelineDescriptorMetal.mm:66
> + if (!newFunction.metal())
> + return;
> + [m_metal setFragmentFunction:newFunction.metal()];
Ditto.
> Source/WebCore/platform/graphics/cocoa/GPURenderPipelineStateMetal.mm:40
> +GPURenderPipelineState::GPURenderPipelineState(const GPUDevice& device,
const GPURenderPipelineDescriptor& descriptor)
> + : m_metal { adoptNS([device.metal()
newRenderPipelineStateWithDescriptor:descriptor.metal() error:nil]) }
Should we be checking this error value?
> Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.cpp:55
> +DOMPromiseProxy<IDLVoid>& GPUCommandBuffer::completed()
> {
> + if (!m_addedCompletedHandler) {
> + addCompletedHandler();
> + m_addedCompletedHandler = true;
> + }
> return m_completedPromise;
> }
This feels like a layering violation. Classes in the platform layer should not
be using DOMPromiseProxy. I believe what we have done traditionally is just
use stored callback functions.
More information about the webkit-reviews
mailing list