Changeset 224065 in webkit
- Timestamp:
- Oct 26, 2017 4:32:10 PM (6 years ago)
- Location:
- trunk/Tools
- Files:
-
- 47 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r224057 r224065 1 2017-10-26 Myles C. Maxfield <mmaxfield@apple.com> 2 3 Demonstrate a possible structure of the WebGPU API 4 https://bugs.webkit.org/show_bug.cgi?id=178874 5 6 Reviewed by Dean Jackson. 7 8 Over the past few weeks, we've been putting together an example showing that a WebGPU API 9 which has implicit barriers can work on all three low-level graphics APIs. We've implemented 10 it on top of Vulkan first, because this is the API which has the strictest requirements and 11 is most difficult to use. 12 13 With this API, this is a valid WebGPU snippet: 14 15 auto device = WebGPU::Device::create(hInstance, hWnd); 16 auto& commandQueue = device->getCommandQueue(); 17 auto& renderState = device->getRenderState(vertexShader, "main", fragmentShader, "main", { }, { }, { }, nullptr); 18 19 … later, in the draw() function … 20 21 auto renderPass = commandQueue->createRenderPass(nullptr); 22 renderPass->setRenderState(renderState); 23 renderPass->setViewport(0, 0, width, height); 24 renderPass->setScissorRect(0, 0, width, height); 25 renderPass->draw(3); 26 commandQueue->commitRenderPass(std::move(renderPass)); 27 commandQueue->present(); 28 29 This snippet doesn’t hook up any vertex attributes or resources, which means the vertex 30 shader has to say something like ({vec4(…), vec4(…), vec4(…)})[gl_VertexIndex]. It also 31 passes in “nullptr” when creating the render pass, which means “render to the screen, rather 32 than to a frame buffer.” You can also see that it doesn’t attach any resources to the draw 33 call. 34 35 In Direct3D 12 and Vulkan, resources are bound in sets, rather than individually. For 36 example, a set might contain two uniform buffers, a texture, and another uniform buffer. At 37 draw time, you swap in whole sets of resources with a single call. A shader invocation can 38 access a collection of sets. Because all shader resource accesses are indirected through 39 these sets, the shape of these sets needs to be supplied at the time you compile the render 40 state. Here is a snippet which bounds a single set which contains a uniform buffer and a 41 texture: 42 43 auto buffer = device->getBuffer(bufferInitialContents); 44 auto texture = device->getTexture(buffer width, height, WebGPU::PixelFormat::RGBA8, textureInitialContents); 45 // One resource set, which holds a single uniform buffer object and a single texture 46 auto& renderState = device->getRenderState(vertexShader, "main", fragmentShader, "main", { }, { }, { { WebGPU::ResourceType::UniformBufferObject, WebGPU::ResourceType::Texture } }, nullptr); 47 48 … later, in the draw() function … 49 50 auto renderPass = commandQueue->createRenderPass(nullptr); 51 renderPass->setRenderState(renderState); 52 renderPass->setResources(0, { WebGPU::UniformBufferObjectReference(buffer.get()), WebGPU::TextureReference(texture.get()) }); 53 … 54 renderPass->draw(3); 55 commandQueue->commitRenderPass(std::move(renderPass)); 56 commandQueue->present(); 57 58 The first argument to the setResources() call identifies which set to populate with the supplied resources. 59 60 One tenant of the low-level graphics APIs is that, if you’ve enabled double buffering (or 61 triple buffering), the GPU is executing one frame at the same time you are recording the 62 next frame. This often means that you need duplicate resources so the CPU and GPU don’t step 63 on each other’s toes. However, platforms have platform-specific requirements about whether 64 or not they can be double / triple buffered, and we don’t want to expose this to the Web for 65 fear of badly-authored programs. 66 67 To solve this, resources are reference counted, and the return type of getBuffer() is an 68 RAII type called BufferHolder which increments and decrements the reference count 69 automatically. The reference count is also incremented and decremented when the GPU is using 70 the resource in a Pass. When the reference count reaches 0, the resource isn’t destroyed; 71 instead, it’s simply moved to a “free list” which getBuffer() may pull from. Therefore, 72 applications don’t need to know whether the frame buffer is double buffered or triple 73 buffered; they can just getBuffer() each frame, and the correct number of buffers will be 74 created and recycled. 75 76 { 77 auto buffer = device->getBuffer(bufferSize); // These get recycled 78 … populate the buffer … 79 auto renderPass = commandQueue->createRenderPass(nullptr); 80 renderPass->setRenderState(renderState); 81 renderPass->setResources(0, { WebGPU::UniformBufferObjectReference(buffer.get()) }); 82 … 83 renderPass->draw(…); 84 commandQueue->commitRenderPass(std::move(renderPass)); 85 } 86 commandQueue->present(); 87 88 In Direct3D and Vulkan, vertex buffers and index buffers are not part of the resource sets 89 mentioned above. Instead, you tell the render state about the shape of the vertex and index 90 buffers, and you swap them out independently in the draw loop. Metal and Vulkan have almost 91 identical API to specify this shape of the vertex buffers, so I’ve mostly copied it. In this 92 example, we have two vertex attributes, a vec2 and a vec3, which both come from the same 93 buffer: 94 95 // { Attribute format, offset within stride, buffer to pull from } 96 std::vector<WebGPU::RenderState::VertexAttribute> vertexAttributes = { {WebGPU::RenderState::VertexFormat::Float2, 0, 0}, {WebGPU::RenderState::VertexFormat::Float3, sizeof(float) * 2, 0} }; 97 // A single vertex buffer, with a stride of 5 floats 98 auto& renderState = device->getRenderState(vertexShader, "main", fragmentShader, "main", { sizeof(float) * 5 }, vertexAttributes, resourceTypes, nullptr); 99 100 … later, in the draw() function … 101 102 auto renderPass = commandQueue->createRenderPass(nullptr); 103 renderPass->setRenderState(renderState); 104 renderPass->setVertexAttributeBuffers({ vertexBuffer.get() }); // The one vertex buffer which both attributes pull from 105 renderPass->setResources(…); 106 … 107 renderPass->draw(…); 108 commandQueue->commitRenderPass(std::move(renderPass)); 109 commandQueue->present(); 110 111 You can also tell the RenderState about how many render targets you have and their formats, 112 and then when you create the RenderPass, you specify the specific textures you want to 113 render into. 114 115 std::vector<WebGPU::PixelFormat> colorPixelFormats = { WebGPU::PixelFormat::RGBA8, WebGPU::PixelFormat::RGBA8 }; // Two render targets, with these formats 116 auto& renderState = device->getRenderState(vertexShader, "main", fragmentShader, "main", vertexBufferStrides, vertexAttributes, resourceTypes, &colorPixelFormats); 117 118 … later, in the draw() function … 119 120 std::vector<std::reference_wrapper<WebGPU::Texture>> destinationTextures = { texture1->get(), texture2->get() }; 121 auto renderPass = commandQueue->createRenderPass(&destinationTextures); 122 renderPass->setRenderState(renderState); 123 … 124 renderPass->draw(…); 125 commandQueue->commitRenderPass(std::move(renderPass)); 126 127 // Now, draw one of the textures to the screen. Note that no synchronization is necessary here! 128 auto renderPass = commandQueue->createRenderPass(nullptr); 129 renderPass->setRenderState(renderState2); 130 renderPass->setResources(0, { WebGPU:: TextureReference(texture1.get()) }); 131 … 132 renderPass->draw(…); 133 commandQueue->commitRenderPass(std::move(renderPass)); 134 commandQueue->present(); 135 136 Just like how in Metal has Render Encoders and Compute Encoders, WebGPU has RenderPasses 137 and ComputePasses. 138 139 auto& computeState = device->getComputeState(computeShader, "main", resourceTypes); 140 … 141 auto computePass = commandQueue->createComputePass(); 142 computePass->setComputeState(computeState); 143 computePass->setResources(0, resources); 144 computePass->dispatch(width, height, depth); 145 commandQueue->commitComputePass(std::move(computePass)); 146 147 // Now, draw the resources we just computed. Note that no synchronization is necessary here! 148 auto renderPass = commandQueue->createRenderPass(nullptr); 149 renderPass->setRenderState(renderState); 150 renderPass->setResources(0, resources }); 151 … 152 renderPass->draw(…); 153 commandQueue->commitRenderPass(std::move(renderPass)); 154 commandQueue->present(); 155 156 There are also two other types of passes: one that corresponds to a Metal blit encoder, and 157 one that allows the CPU to change the contents of GPU buffers and textures. This last kind 158 of pass is a little interesting: you can’t just change the contents of a buffer at any time 159 you feel like it, because that resource might be in use by the GPU. Therefore, we need to do 160 the same kind of synchronization that we already do at render pass boundaries. 161 162 In addition, both Vulkan and Direct3D have a concept of a memory heap. A resource might 163 exist inside a heap which is fast, but invisible from the CPU, or in a heap which is slow, 164 but visible by the CPU. Certain operations are not possible from some types of images (e.g. 165 non-tiled textures may not be able to be sampled from). The usual way to get around this 166 problem is to have two resources: a slow staging resource which the CPU can see, and a fast 167 resource which the CPU can’t see. Uploading data is a two-pass algorithm, where the CPU 168 memcpy()s into the slow staging resource, and then a blit command is enqueued on the GPU to 169 copy the contents of the staging resource to the real resource. This requires that the 170 upload have access to the commandQueue so it can possibly enqueue a blit between the staging 171 and real resources. Therefore, a pass is the right level of abstraction for these facilities. 172 173 std::queue<boost::unique_future<std::vector<uint8_t>>> futureQueue; // Promises for data downloads from the GPU 174 175 … later, in the draw() function … 176 177 // See if any of the previously-enqueued downloads are finished 178 while (!futureQueue.empty() && futureQueue.front(). has_value()) { 179 std::vector<uint8_t>& data = futureQueue.front().get(); 180 // Use the downloaded data 181 futureQueue.pop(); 182 } 183 … 184 auto hostAccessPass = commandQueue->createHostAccessPass(); 185 hostAccessPass->overwriteBuffer(buffer->get(), bufferContents); // Upload data to a resource 186 187 futureQueue.emplace(hostAccessPass->getBufferContents(buffer->get())); 188 commandQueue->commitHostAccessPass(std::move(hostAccessPass)); 189 190 You can also issue copy commands between resources entirely on the GPU: 191 192 auto blitPass = commandQueue->createBlitPass(); 193 blitPass->copyTexture(source->get(), destination->get(), sourceX, sourceY, destinationX, destinationY, width, height); 194 commandQueue->commitBlitPass(std::move(blitPass)); 195 196 * Scripts/webkitpy/style/checker.py: 197 * WebGPUAPIStructure/Example/Example.cpp: Added. 198 (readFile): 199 (drawWebGPU): 200 (wWinMain): 201 (MyRegisterClass): 202 (InitInstance): 203 (WndProc): 204 * WebGPUAPIStructure/Example/Example.h: Added. 205 * WebGPUAPIStructure/Example/Example.ico: Added. 206 * WebGPUAPIStructure/Example/Example.rc: Added. 207 * WebGPUAPIStructure/Example/Example.vcxproj: Added. 208 * WebGPUAPIStructure/Example/Example.vcxproj.filters: Added. 209 * WebGPUAPIStructure/Example/Example.vcxproj.user: Added. 210 * WebGPUAPIStructure/Example/resource.h: Added. 211 * WebGPUAPIStructure/Example/small.ico: Added. 212 * WebGPUAPIStructure/Example/stdafx.cpp: Added. 213 * WebGPUAPIStructure/Example/stdafx.h: Added. 214 * WebGPUAPIStructure/Example/targetver.h: Added. 215 * WebGPUAPIStructure/WebGPU-Common/WebGPU-Common.vcxproj: Added. 216 * WebGPUAPIStructure/WebGPU-Common/WebGPU-Common.vcxproj.filters: Added. 217 * WebGPUAPIStructure/WebGPU-Common/WebGPU.cpp: Added. 218 (WebGPU::BufferHolder::BufferHolder): 219 (WebGPU::BufferHolder::~BufferHolder): 220 (WebGPU::TextureHolder::TextureHolder): 221 (WebGPU::TextureHolder::~TextureHolder): 222 (WebGPU::SamplerHolder::SamplerHolder): 223 (WebGPU::SamplerHolder::~SamplerHolder): 224 * WebGPUAPIStructure/WebGPU-Common/WebGPU.h: Added. 225 (WebGPU::Queue::~Queue): 226 (WebGPU::RenderState::~RenderState): 227 (WebGPU::ComputeState::~ComputeState): 228 (WebGPU::Buffer::~Buffer): 229 (WebGPU::Texture::~Texture): 230 (WebGPU::Sampler::~Sampler): 231 (WebGPU::TextureReference::TextureReference): 232 (WebGPU::TextureReference::get const): 233 (WebGPU::SamplerReference::SamplerReference): 234 (WebGPU::SamplerReference::get const): 235 (WebGPU::UniformBufferObjectReference::UniformBufferObjectReference): 236 (WebGPU::UniformBufferObjectReference::get const): 237 (WebGPU::ShaderStorageBufferObjectReference::ShaderStorageBufferObjectReference): 238 (WebGPU::ShaderStorageBufferObjectReference::get const): 239 (WebGPU::RenderPass::~RenderPass): 240 (WebGPU::ComputePass::~ComputePass): 241 (WebGPU::BlitPass::~BlitPass): 242 (WebGPU::HostAccessPass::~HostAccessPass): 243 (WebGPU::BufferHolder::get): 244 (WebGPU::TextureHolder::get): 245 (WebGPU::SamplerHolder::get): 246 (WebGPU::Device::~Device): 247 * WebGPUAPIStructure/WebGPU-Vulkan/BlitPassImpl.cpp: Added. 248 (WebGPU::BlitPassImpl::BlitPassImpl): 249 (WebGPU::BlitPassImpl::copyTexture): 250 * WebGPUAPIStructure/WebGPU-Vulkan/BlitPassImpl.h: Added. 251 * WebGPUAPIStructure/WebGPU-Vulkan/BufferImpl.cpp: Added. 252 (WebGPU::BufferImpl::BufferImpl): 253 (WebGPU::BufferImpl::decrementReferenceCount): 254 * WebGPUAPIStructure/WebGPU-Vulkan/BufferImpl.h: Added. 255 (WebGPU::BufferImpl::getBuffer const): 256 (WebGPU::BufferImpl::getDeviceMemory const): 257 (WebGPU::BufferImpl::incrementReferenceCount): 258 (WebGPU::BufferImpl::getLength const): 259 * WebGPUAPIStructure/WebGPU-Vulkan/ComputePassImpl.cpp: Added. 260 (WebGPU::ComputePassImpl::ComputePassImpl): 261 (WebGPU::ComputePassImpl::setComputeState): 262 (WebGPU::ComputePassImpl::setResources): 263 (WebGPU::ComputePassImpl::dispatch): 264 * WebGPUAPIStructure/WebGPU-Vulkan/ComputePassImpl.h: Added. 265 * WebGPUAPIStructure/WebGPU-Vulkan/ComputeStateImpl.cpp: Added. 266 (WebGPU::ComputeStateImpl::ComputeStateImpl): 267 * WebGPUAPIStructure/WebGPU-Vulkan/ComputeStateImpl.h: Added. 268 (WebGPU::ComputeStateImpl::getPipeline const): 269 (WebGPU::ComputeStateImpl::getPipelineLayout const): 270 (WebGPU::ComputeStateImpl::getDescriptorSetLayouts const): 271 * WebGPUAPIStructure/WebGPU-Vulkan/DeviceImpl.cpp: Added. 272 (WebGPU::Device::create): 273 (WebGPU::convertPixelFormat): 274 (WebGPU::convertFormat): 275 (WebGPU::debugReport): 276 (WebGPU::DeviceImpl::DeviceImpl): 277 (WebGPU::DeviceImpl::getCommandQueue): 278 (WebGPU::DeviceImpl::prepareShader): 279 (WebGPU::DeviceImpl::createPipelineLayout): 280 (WebGPU::DeviceImpl::createCompatibleRenderPass): 281 (WebGPU::convertVertexFormat): 282 (WebGPU::DeviceImpl::getRenderState): 283 (WebGPU::DeviceImpl::getComputeState): 284 (WebGPU::DeviceImpl::getBuffer): 285 (WebGPU::DeviceImpl::returnBuffer): 286 (WebGPU::DeviceImpl::getTexture): 287 (WebGPU::DeviceImpl::returnTexture): 288 (WebGPU::DeviceImpl::getSampler): 289 (WebGPU::DeviceImpl::returnSampler): 290 (WebGPU::DeviceImpl::~DeviceImpl): 291 * WebGPUAPIStructure/WebGPU-Vulkan/DeviceImpl.h: Added. 292 (WebGPU::DeviceImpl::UniqueDebugReportCallbackEXT::UniqueDebugReportCallbackEXT): 293 (WebGPU::DeviceImpl::UniqueDebugReportCallbackEXT::operator=): 294 (WebGPU::DeviceImpl::UniqueDebugReportCallbackEXT::~UniqueDebugReportCallbackEXT): 295 (WebGPU::DeviceImpl::UniqueDebugReportCallbackEXT::destroy): 296 (WebGPU::DeviceImpl::TextureParameters::operator== const): 297 (WebGPU::DeviceImpl::TextureParametersHash::operator() const): 298 * WebGPUAPIStructure/WebGPU-Vulkan/HostAccessPassImpl.cpp: Added. 299 (WebGPU::HostAccessPassImpl::HostAccessPassImpl): 300 (WebGPU::HostAccessPassImpl::overwriteBuffer): 301 (WebGPU::HostAccessPassImpl::getBufferContents): 302 (WebGPU::HostAccessPassImpl::execute): 303 * WebGPUAPIStructure/WebGPU-Vulkan/HostAccessPassImpl.h: Added. 304 (WebGPU::HostAccessPassImpl::getFinishedEvent const): 305 * WebGPUAPIStructure/WebGPU-Vulkan/PassImpl.cpp: Added. 306 (WebGPU::PassImpl::PassImpl): 307 (WebGPU::ResourceVisitor::operator()): 308 (WebGPU::ResourceVisitor::getBindings const): 309 (WebGPU::ResourceVisitor::releaseWriteDescriptorSets): 310 (WebGPU::ResourceVisitor::getDescriptorImageInfos const): 311 (WebGPU::ResourceVisitor::getDescriptorBufferInfos const): 312 (WebGPU::ResourceVisitor::getBuffers const): 313 (WebGPU::ResourceVisitor::getTextures const): 314 (WebGPU::ResourceVisitor::getSamplers const): 315 (WebGPU::ResourceVisitor::getImageCount const): 316 (WebGPU::ResourceVisitor::getSamplerCount const): 317 (WebGPU::ResourceVisitor::getUniformBufferCount const): 318 (WebGPU::ResourceVisitor::getStorageBufferCount const): 319 (WebGPU::PassImpl::setResources): 320 (WebGPU::PassImpl::insertBuffer): 321 (WebGPU::PassImpl::insertTexture): 322 (WebGPU::PassImpl::insertSampler): 323 * WebGPUAPIStructure/WebGPU-Vulkan/PassImpl.h: Added. 324 (WebGPU::PassImpl::getCommandBuffer const): 325 (WebGPU::PassImpl::iterateBuffers): 326 (WebGPU::PassImpl::iterateTextures): 327 (WebGPU::PassImpl::ResourceReference::ResourceReference): 328 (WebGPU::PassImpl::ResourceReference::~ResourceReference): 329 (WebGPU::PassImpl::ResourceReference::operator=): 330 (WebGPU::PassImpl::ResourceReference::operator== const): 331 (WebGPU::PassImpl::ResourceReference::get const): 332 (WebGPU::PassImpl::ResourceReference::release): 333 (WebGPU::PassImpl::ResourceReferenceHash::operator() const): 334 * WebGPUAPIStructure/WebGPU-Vulkan/QueueImpl.cpp: Added. 335 (WebGPU::QueueImpl::QueueImpl): 336 (WebGPU::QueueImpl::prepareCurrentFrame): 337 (WebGPU::QueueImpl::createSpecificRenderPass): 338 (WebGPU::QueueImpl::createFramebuffer): 339 (WebGPU::QueueImpl::createRenderPass): 340 (WebGPU::QueueImpl::commitRenderPass): 341 (WebGPU::QueueImpl::createComputePass): 342 (WebGPU::QueueImpl::commitComputePass): 343 (WebGPU::QueueImpl::createBlitPass): 344 (WebGPU::QueueImpl::commitBlitPass): 345 (WebGPU::QueueImpl::createHostAccessPass): 346 (WebGPU::QueueImpl::commitHostAccessPass): 347 (WebGPU::QueueImpl::present): 348 (WebGPU::QueueImpl::commitPass): 349 (WebGPU::QueueImpl::synchronizeResources): 350 (WebGPU::QueueImpl::~QueueImpl): 351 * WebGPUAPIStructure/WebGPU-Vulkan/QueueImpl.h: Added. 352 * WebGPUAPIStructure/WebGPU-Vulkan/RenderPassImpl.cpp: Added. 353 (WebGPU::RenderPassImpl::RenderPassImpl): 354 (WebGPU::RenderPassImpl::setRenderState): 355 (WebGPU::RenderPassImpl::setVertexAttributeBuffers): 356 (WebGPU::RenderPassImpl::setResources): 357 (WebGPU::RenderPassImpl::setViewport): 358 (WebGPU::RenderPassImpl::setScissorRect): 359 (WebGPU::RenderPassImpl::draw): 360 * WebGPUAPIStructure/WebGPU-Vulkan/RenderPassImpl.h: Added. 361 * WebGPUAPIStructure/WebGPU-Vulkan/RenderStateImpl.cpp: Added. 362 (WebGPU::RenderStateImpl::RenderStateImpl): 363 * WebGPUAPIStructure/WebGPU-Vulkan/RenderStateImpl.h: Added. 364 (WebGPU::RenderStateImpl::getPipeline const): 365 (WebGPU::RenderStateImpl::getPipelineLayout const): 366 (WebGPU::RenderStateImpl::getDescriptorSetLayouts const): 367 * WebGPUAPIStructure/WebGPU-Vulkan/SamplerImpl.cpp: Added. 368 (WebGPU::SamplerImpl::SamplerImpl): 369 (WebGPU::SamplerImpl::decrementReferenceCount): 370 * WebGPUAPIStructure/WebGPU-Vulkan/SamplerImpl.h: Added. 371 (WebGPU::SamplerImpl::getSampler): 372 (WebGPU::SamplerImpl::incrementReferenceCount): 373 (WebGPU::SamplerImpl::getFilter): 374 (WebGPU::SamplerImpl::getMipmapMode): 375 (WebGPU::SamplerImpl::getAddressMode): 376 * WebGPUAPIStructure/WebGPU-Vulkan/TextureImpl.cpp: Added. 377 (WebGPU::TextureImpl::TextureImpl): 378 (WebGPU::TextureImpl::decrementReferenceCount): 379 * WebGPUAPIStructure/WebGPU-Vulkan/TextureImpl.h: Added. 380 (WebGPU::TextureImpl::getImage const): 381 (WebGPU::TextureImpl::getImageView const): 382 (WebGPU::TextureImpl::getFormat const): 383 (WebGPU::TextureImpl::incrementReferenceCount): 384 (WebGPU::TextureImpl::getWidth const): 385 (WebGPU::TextureImpl::getHeight const): 386 (WebGPU::TextureImpl::getTransferredToGPU const): 387 (WebGPU::TextureImpl::setTransferredToGPU): 388 * WebGPUAPIStructure/WebGPU-Vulkan/WebGPU-Vulkan.vcxproj: Added. 389 * WebGPUAPIStructure/WebGPU-Vulkan/WebGPU-Vulkan.vcxproj.filters: Added. 390 * WebGPUAPIStructure/WebGPU.sln: Added. 391 1 392 2017-10-26 Eric Carlson <eric.carlson@apple.com> 2 393 -
trunk/Tools/Scripts/webkitpy/style/checker.py
r224014 r224065 214 214 ([os.path.join('webkitpy', 'thirdparty'), 215 215 os.path.join('Source', 'ThirdParty', 'ANGLE'), 216 os.path.join('Source', 'ThirdParty', 'xdgmime')], 216 os.path.join('Source', 'ThirdParty', 'xdgmime'), 217 os.path.join('Tools', 'WebGPUAPIStructure')], 217 218 ["-", 218 219 "+pep8/W191", # Tabs
Note: See TracChangeset
for help on using the changeset viewer.