1 | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "VkCommandBuffer.hpp" |
16 | #include "VkBuffer.hpp" |
17 | #include "VkEvent.hpp" |
18 | #include "VkFence.hpp" |
19 | #include "VkFramebuffer.hpp" |
20 | #include "VkImage.hpp" |
21 | #include "VkImageView.hpp" |
22 | #include "VkPipeline.hpp" |
23 | #include "VkPipelineLayout.hpp" |
24 | #include "VkQueryPool.hpp" |
25 | #include "VkRenderPass.hpp" |
26 | #include "Device/Renderer.hpp" |
27 | |
28 | #include <cstring> |
29 | |
30 | namespace vk |
31 | { |
32 | |
33 | class CommandBuffer::Command |
34 | { |
35 | public: |
36 | // FIXME (b/119421344): change the commandBuffer argument to a CommandBuffer state |
37 | virtual void play(CommandBuffer::ExecutionState& executionState) = 0; |
38 | virtual ~Command() {} |
39 | }; |
40 | |
41 | class BeginRenderPass : public CommandBuffer::Command |
42 | { |
43 | public: |
44 | BeginRenderPass(RenderPass* renderPass, Framebuffer* framebuffer, VkRect2D renderArea, |
45 | uint32_t clearValueCount, const VkClearValue* pClearValues) : |
46 | renderPass(renderPass), framebuffer(framebuffer), renderArea(renderArea), |
47 | clearValueCount(clearValueCount) |
48 | { |
49 | // FIXME (b/119409619): use an allocator here so we can control all memory allocations |
50 | clearValues = new VkClearValue[clearValueCount]; |
51 | memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue)); |
52 | } |
53 | |
54 | ~BeginRenderPass() override |
55 | { |
56 | delete [] clearValues; |
57 | } |
58 | |
59 | protected: |
60 | void play(CommandBuffer::ExecutionState& executionState) override |
61 | { |
62 | executionState.renderPass = renderPass; |
63 | executionState.renderPassFramebuffer = framebuffer; |
64 | executionState.subpassIndex = 0; |
65 | framebuffer->clear(executionState.renderPass, clearValueCount, clearValues, renderArea); |
66 | } |
67 | |
68 | private: |
69 | RenderPass* renderPass; |
70 | Framebuffer* framebuffer; |
71 | VkRect2D renderArea; |
72 | uint32_t clearValueCount; |
73 | VkClearValue* clearValues; |
74 | }; |
75 | |
76 | class NextSubpass : public CommandBuffer::Command |
77 | { |
78 | public: |
79 | NextSubpass() |
80 | { |
81 | } |
82 | |
83 | protected: |
84 | void play(CommandBuffer::ExecutionState& executionState) override |
85 | { |
86 | bool hasResolveAttachments = (executionState.renderPass->getSubpass(executionState.subpassIndex).pResolveAttachments != nullptr); |
87 | if(hasResolveAttachments) |
88 | { |
89 | // FIXME(sugoi): remove the following lines and resolve in Renderer::finishRendering() |
90 | // for a Draw command or after the last command of the current subpass |
91 | // which modifies pixels. |
92 | executionState.renderer->synchronize(); |
93 | executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex); |
94 | } |
95 | |
96 | ++executionState.subpassIndex; |
97 | } |
98 | }; |
99 | |
100 | class EndRenderPass : public CommandBuffer::Command |
101 | { |
102 | public: |
103 | EndRenderPass() |
104 | { |
105 | } |
106 | |
107 | protected: |
108 | void play(CommandBuffer::ExecutionState& executionState) override |
109 | { |
110 | // Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL |
111 | // This is somewhat heavier than the actual ordering required. |
112 | executionState.renderer->synchronize(); |
113 | |
114 | // FIXME(sugoi): remove the following line and resolve in Renderer::finishRendering() |
115 | // for a Draw command or after the last command of the current subpass |
116 | // which modifies pixels. |
117 | executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex); |
118 | executionState.renderPass = nullptr; |
119 | executionState.renderPassFramebuffer = nullptr; |
120 | } |
121 | }; |
122 | |
123 | class ExecuteCommands : public CommandBuffer::Command |
124 | { |
125 | public: |
126 | ExecuteCommands(const CommandBuffer* commandBuffer) : commandBuffer(commandBuffer) |
127 | { |
128 | } |
129 | |
130 | protected: |
131 | void play(CommandBuffer::ExecutionState& executionState) override |
132 | { |
133 | commandBuffer->submitSecondary(executionState); |
134 | } |
135 | |
136 | private: |
137 | const CommandBuffer* commandBuffer; |
138 | }; |
139 | |
140 | class PipelineBind : public CommandBuffer::Command |
141 | { |
142 | public: |
143 | PipelineBind(VkPipelineBindPoint pipelineBindPoint, Pipeline* pipeline) : |
144 | pipelineBindPoint(pipelineBindPoint), pipeline(pipeline) |
145 | { |
146 | } |
147 | |
148 | protected: |
149 | void play(CommandBuffer::ExecutionState& executionState) override |
150 | { |
151 | executionState.pipelineState[pipelineBindPoint].pipeline = pipeline; |
152 | } |
153 | |
154 | private: |
155 | VkPipelineBindPoint pipelineBindPoint; |
156 | Pipeline* pipeline; |
157 | }; |
158 | |
159 | class Dispatch : public CommandBuffer::Command |
160 | { |
161 | public: |
162 | Dispatch(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) : |
163 | baseGroupX(baseGroupX), baseGroupY(baseGroupY), baseGroupZ(baseGroupZ), |
164 | groupCountX(groupCountX), groupCountY(groupCountY), groupCountZ(groupCountZ) |
165 | { |
166 | } |
167 | |
168 | protected: |
169 | void play(CommandBuffer::ExecutionState& executionState) override |
170 | { |
171 | auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE]; |
172 | |
173 | ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline); |
174 | pipeline->run(baseGroupX, baseGroupY, baseGroupZ, |
175 | groupCountX, groupCountY, groupCountZ, |
176 | pipelineState.descriptorSets, |
177 | pipelineState.descriptorDynamicOffsets, |
178 | executionState.pushConstants); |
179 | } |
180 | |
181 | private: |
182 | uint32_t baseGroupX; |
183 | uint32_t baseGroupY; |
184 | uint32_t baseGroupZ; |
185 | uint32_t groupCountX; |
186 | uint32_t groupCountY; |
187 | uint32_t groupCountZ; |
188 | }; |
189 | |
190 | class DispatchIndirect : public CommandBuffer::Command |
191 | { |
192 | public: |
193 | DispatchIndirect(Buffer* buffer, VkDeviceSize offset) : |
194 | buffer(buffer), offset(offset) |
195 | { |
196 | } |
197 | |
198 | protected: |
199 | void play(CommandBuffer::ExecutionState& executionState) override |
200 | { |
201 | auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(buffer->getOffsetPointer(offset)); |
202 | |
203 | auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE]; |
204 | |
205 | ComputePipeline* pipeline = static_cast<ComputePipeline*>(pipelineState.pipeline); |
206 | pipeline->run(0, 0, 0, cmd->x, cmd->y, cmd->z, |
207 | pipelineState.descriptorSets, |
208 | pipelineState.descriptorDynamicOffsets, |
209 | executionState.pushConstants); |
210 | } |
211 | |
212 | private: |
213 | const Buffer* buffer; |
214 | VkDeviceSize offset; |
215 | }; |
216 | |
217 | struct VertexBufferBind : public CommandBuffer::Command |
218 | { |
219 | VertexBufferBind(uint32_t binding, Buffer* buffer, const VkDeviceSize offset) : |
220 | binding(binding), buffer(buffer), offset(offset) |
221 | { |
222 | } |
223 | |
224 | void play(CommandBuffer::ExecutionState& executionState) override |
225 | { |
226 | executionState.vertexInputBindings[binding] = { buffer, offset }; |
227 | } |
228 | |
229 | private: |
230 | uint32_t binding; |
231 | Buffer* buffer; |
232 | const VkDeviceSize offset; |
233 | }; |
234 | |
235 | struct IndexBufferBind : public CommandBuffer::Command |
236 | { |
237 | IndexBufferBind(Buffer* buffer, const VkDeviceSize offset, const VkIndexType indexType) : |
238 | buffer(buffer), offset(offset), indexType(indexType) |
239 | { |
240 | |
241 | } |
242 | |
243 | void play(CommandBuffer::ExecutionState& executionState) override |
244 | { |
245 | executionState.indexBufferBinding = { buffer, offset }; |
246 | executionState.indexType = indexType; |
247 | } |
248 | |
249 | private: |
250 | Buffer* buffer; |
251 | const VkDeviceSize offset; |
252 | const VkIndexType indexType; |
253 | }; |
254 | |
255 | struct SetViewport : public CommandBuffer::Command |
256 | { |
257 | SetViewport(const VkViewport& viewport, uint32_t viewportID) : |
258 | viewport(viewport), viewportID(viewportID) |
259 | { |
260 | } |
261 | |
262 | void play(CommandBuffer::ExecutionState& executionState) override |
263 | { |
264 | executionState.dynamicState.viewport = viewport; |
265 | } |
266 | |
267 | private: |
268 | const VkViewport viewport; |
269 | uint32_t viewportID; |
270 | }; |
271 | |
272 | struct SetScissor : public CommandBuffer::Command |
273 | { |
274 | SetScissor(const VkRect2D& scissor, uint32_t scissorID) : |
275 | scissor(scissor), scissorID(scissorID) |
276 | { |
277 | } |
278 | |
279 | void play(CommandBuffer::ExecutionState& executionState) override |
280 | { |
281 | executionState.dynamicState.scissor = scissor; |
282 | } |
283 | |
284 | private: |
285 | const VkRect2D scissor; |
286 | uint32_t scissorID; |
287 | }; |
288 | |
289 | struct SetDepthBias : public CommandBuffer::Command |
290 | { |
291 | SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) : |
292 | depthBiasConstantFactor(depthBiasConstantFactor), depthBiasClamp(depthBiasClamp), depthBiasSlopeFactor(depthBiasSlopeFactor) |
293 | { |
294 | } |
295 | |
296 | void play(CommandBuffer::ExecutionState& executionState) override |
297 | { |
298 | executionState.dynamicState.depthBiasConstantFactor = depthBiasConstantFactor; |
299 | executionState.dynamicState.depthBiasClamp = depthBiasClamp; |
300 | executionState.dynamicState.depthBiasSlopeFactor = depthBiasSlopeFactor; |
301 | } |
302 | |
303 | private: |
304 | float depthBiasConstantFactor; |
305 | float depthBiasClamp; |
306 | float depthBiasSlopeFactor; |
307 | }; |
308 | |
309 | struct SetBlendConstants : public CommandBuffer::Command |
310 | { |
311 | SetBlendConstants(const float blendConstants[4]) |
312 | { |
313 | memcpy(this->blendConstants, blendConstants, sizeof(this->blendConstants)); |
314 | } |
315 | |
316 | void play(CommandBuffer::ExecutionState& executionState) override |
317 | { |
318 | memcpy(&(executionState.dynamicState.blendConstants[0]), blendConstants, sizeof(blendConstants)); |
319 | } |
320 | |
321 | private: |
322 | float blendConstants[4]; |
323 | }; |
324 | |
325 | struct SetDepthBounds : public CommandBuffer::Command |
326 | { |
327 | SetDepthBounds(float minDepthBounds, float maxDepthBounds) : |
328 | minDepthBounds(minDepthBounds), maxDepthBounds(maxDepthBounds) |
329 | { |
330 | } |
331 | |
332 | void play(CommandBuffer::ExecutionState& executionState) override |
333 | { |
334 | executionState.dynamicState.minDepthBounds = minDepthBounds; |
335 | executionState.dynamicState.maxDepthBounds = maxDepthBounds; |
336 | } |
337 | |
338 | private: |
339 | float minDepthBounds; |
340 | float maxDepthBounds; |
341 | }; |
342 | struct SetStencilCompareMask : public CommandBuffer::Command |
343 | { |
344 | SetStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask) : |
345 | faceMask(faceMask), compareMask(compareMask) |
346 | { |
347 | } |
348 | |
349 | void play(CommandBuffer::ExecutionState& executionState) override |
350 | { |
351 | if(faceMask & VK_STENCIL_FACE_FRONT_BIT) |
352 | { |
353 | executionState.dynamicState.compareMask[0] = compareMask; |
354 | } |
355 | if(faceMask & VK_STENCIL_FACE_BACK_BIT) |
356 | { |
357 | executionState.dynamicState.compareMask[1] = compareMask; |
358 | } |
359 | } |
360 | |
361 | private: |
362 | VkStencilFaceFlags faceMask; |
363 | uint32_t compareMask; |
364 | }; |
365 | |
366 | struct SetStencilWriteMask : public CommandBuffer::Command |
367 | { |
368 | SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask) : |
369 | faceMask(faceMask), writeMask(writeMask) |
370 | { |
371 | } |
372 | |
373 | void play(CommandBuffer::ExecutionState& executionState) override |
374 | { |
375 | if(faceMask & VK_STENCIL_FACE_FRONT_BIT) |
376 | { |
377 | executionState.dynamicState.writeMask[0] = writeMask; |
378 | } |
379 | if(faceMask & VK_STENCIL_FACE_BACK_BIT) |
380 | { |
381 | executionState.dynamicState.writeMask[1] = writeMask; |
382 | } |
383 | } |
384 | |
385 | private: |
386 | VkStencilFaceFlags faceMask; |
387 | uint32_t writeMask; |
388 | }; |
389 | |
390 | struct SetStencilReference : public CommandBuffer::Command |
391 | { |
392 | SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference) : |
393 | faceMask(faceMask), reference(reference) |
394 | { |
395 | } |
396 | |
397 | void play(CommandBuffer::ExecutionState& executionState) override |
398 | { |
399 | if(faceMask & VK_STENCIL_FACE_FRONT_BIT) |
400 | { |
401 | executionState.dynamicState.reference[0] = reference; |
402 | } |
403 | if(faceMask & VK_STENCIL_FACE_BACK_BIT) |
404 | { |
405 | executionState.dynamicState.reference[1] = reference; |
406 | } |
407 | } |
408 | |
409 | private: |
410 | VkStencilFaceFlags faceMask; |
411 | uint32_t reference; |
412 | }; |
413 | |
414 | void CommandBuffer::ExecutionState::bindVertexInputs(sw::Context& context, int firstInstance) |
415 | { |
416 | for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++) |
417 | { |
418 | auto &attrib = context.input[i]; |
419 | if (attrib.count) |
420 | { |
421 | const auto &vertexInput = vertexInputBindings[attrib.binding]; |
422 | VkDeviceSize offset = attrib.offset + vertexInput.offset + |
423 | attrib.instanceStride * firstInstance; |
424 | attrib.buffer = vertexInput.buffer ? vertexInput.buffer->getOffsetPointer(offset) : nullptr; |
425 | |
426 | VkDeviceSize size = vertexInput.buffer ? vertexInput.buffer->getSize() : 0; |
427 | attrib.robustnessSize = (size > offset) ? size - offset : 0; |
428 | } |
429 | } |
430 | } |
431 | |
432 | void CommandBuffer::ExecutionState::bindAttachments(sw::Context& context) |
433 | { |
434 | // Binds all the attachments for the current subpass |
435 | // Ideally this would be performed by BeginRenderPass and NextSubpass, but |
436 | // there is too much stomping of the renderer's state by setContext() in |
437 | // draws. |
438 | |
439 | auto const & subpass = renderPass->getSubpass(subpassIndex); |
440 | |
441 | for (auto i = 0u; i < subpass.colorAttachmentCount; i++) |
442 | { |
443 | auto attachmentReference = subpass.pColorAttachments[i]; |
444 | if (attachmentReference.attachment != VK_ATTACHMENT_UNUSED) |
445 | { |
446 | context.renderTarget[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment); |
447 | } |
448 | } |
449 | |
450 | auto attachmentReference = subpass.pDepthStencilAttachment; |
451 | if (attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED) |
452 | { |
453 | auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment); |
454 | if (attachment->hasDepthAspect()) |
455 | { |
456 | context.depthBuffer = attachment; |
457 | } |
458 | if (attachment->hasStencilAspect()) |
459 | { |
460 | context.stencilBuffer = attachment; |
461 | } |
462 | } |
463 | } |
464 | |
465 | struct DrawBase : public CommandBuffer::Command |
466 | { |
467 | int bytesPerIndex(CommandBuffer::ExecutionState const& executionState) |
468 | { |
469 | return executionState.indexType == VK_INDEX_TYPE_UINT16 ? 2 : 4; |
470 | } |
471 | |
472 | template<typename T> |
473 | void processPrimitiveRestart(T* indexBuffer, |
474 | uint32_t count, |
475 | GraphicsPipeline* pipeline, |
476 | std::vector<std::pair<uint32_t, void*>>& indexBuffers) |
477 | { |
478 | static const T RestartIndex = static_cast<T>(-1); |
479 | T* indexBufferStart = indexBuffer; |
480 | uint32_t vertexCount = 0; |
481 | for(uint32_t i = 0; i < count; i++) |
482 | { |
483 | if(indexBuffer[i] == RestartIndex) |
484 | { |
485 | // Record previous segment |
486 | if(vertexCount > 0) |
487 | { |
488 | uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount); |
489 | if(primitiveCount > 0) |
490 | { |
491 | indexBuffers.push_back({ primitiveCount, indexBufferStart }); |
492 | } |
493 | } |
494 | vertexCount = 0; |
495 | } |
496 | else |
497 | { |
498 | if(vertexCount == 0) |
499 | { |
500 | indexBufferStart = indexBuffer + i; |
501 | } |
502 | vertexCount++; |
503 | } |
504 | } |
505 | |
506 | // Record last segment |
507 | if(vertexCount > 0) |
508 | { |
509 | uint32_t primitiveCount = pipeline->computePrimitiveCount(vertexCount); |
510 | if(primitiveCount > 0) |
511 | { |
512 | indexBuffers.push_back({ primitiveCount, indexBufferStart }); |
513 | } |
514 | } |
515 | } |
516 | |
517 | void draw(CommandBuffer::ExecutionState& executionState, bool indexed, |
518 | uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance) |
519 | { |
520 | auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS]; |
521 | |
522 | GraphicsPipeline *pipeline = static_cast<GraphicsPipeline *>(pipelineState.pipeline); |
523 | |
524 | sw::Context context = pipeline->getContext(); |
525 | |
526 | executionState.bindVertexInputs(context, firstInstance); |
527 | |
528 | context.descriptorSets = pipelineState.descriptorSets; |
529 | context.descriptorDynamicOffsets = pipelineState.descriptorDynamicOffsets; |
530 | |
531 | // Apply either pipeline state or dynamic state |
532 | executionState.renderer->setScissor(pipeline->hasDynamicState(VK_DYNAMIC_STATE_SCISSOR) ? |
533 | executionState.dynamicState.scissor : pipeline->getScissor()); |
534 | executionState.renderer->setViewport(pipeline->hasDynamicState(VK_DYNAMIC_STATE_VIEWPORT) ? |
535 | executionState.dynamicState.viewport : pipeline->getViewport()); |
536 | executionState.renderer->setBlendConstant(pipeline->hasDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS) ? |
537 | executionState.dynamicState.blendConstants : pipeline->getBlendConstants()); |
538 | |
539 | if (pipeline->hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS)) |
540 | { |
541 | // If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0 |
542 | ASSERT(executionState.dynamicState.depthBiasClamp == 0.0f); |
543 | |
544 | context.depthBias = executionState.dynamicState.depthBiasConstantFactor; |
545 | context.slopeDepthBias = executionState.dynamicState.depthBiasSlopeFactor; |
546 | } |
547 | if (pipeline->hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS) && context.depthBoundsTestEnable) |
548 | { |
549 | // Unless the VK_EXT_depth_range_unrestricted extension is enabled minDepthBounds and maxDepthBounds must be between 0.0 and 1.0, inclusive |
550 | ASSERT(executionState.dynamicState.minDepthBounds >= 0.0f && |
551 | executionState.dynamicState.minDepthBounds <= 1.0f); |
552 | ASSERT(executionState.dynamicState.maxDepthBounds >= 0.0f && |
553 | executionState.dynamicState.maxDepthBounds <= 1.0f); |
554 | |
555 | UNIMPLEMENTED("depthBoundsTestEnable" ); |
556 | } |
557 | if (pipeline->hasDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) && context.stencilEnable) |
558 | { |
559 | context.frontStencil.compareMask = executionState.dynamicState.compareMask[0]; |
560 | context.backStencil.compareMask = executionState.dynamicState.compareMask[1]; |
561 | } |
562 | if (pipeline->hasDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) && context.stencilEnable) |
563 | { |
564 | context.frontStencil.writeMask = executionState.dynamicState.writeMask[0]; |
565 | context.backStencil.writeMask = executionState.dynamicState.writeMask[1]; |
566 | } |
567 | if (pipeline->hasDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE) && context.stencilEnable) |
568 | { |
569 | context.frontStencil.reference = executionState.dynamicState.reference[0]; |
570 | context.backStencil.reference = executionState.dynamicState.reference[1]; |
571 | } |
572 | |
573 | executionState.bindAttachments(context); |
574 | |
575 | context.occlusionEnabled = executionState.renderer->hasOcclusionQuery(); |
576 | |
577 | std::vector<std::pair<uint32_t, void *>> indexBuffers; |
578 | if (indexed) |
579 | { |
580 | void *indexBuffer = executionState.indexBufferBinding.buffer->getOffsetPointer( |
581 | executionState.indexBufferBinding.offset + first * bytesPerIndex(executionState)); |
582 | if (pipeline->hasPrimitiveRestartEnable()) |
583 | { |
584 | switch (executionState.indexType) |
585 | { |
586 | case VK_INDEX_TYPE_UINT16: |
587 | processPrimitiveRestart(static_cast<uint16_t *>(indexBuffer), count, pipeline, indexBuffers); |
588 | break; |
589 | case VK_INDEX_TYPE_UINT32: |
590 | processPrimitiveRestart(static_cast<uint32_t *>(indexBuffer), count, pipeline, indexBuffers); |
591 | break; |
592 | default: |
593 | UNIMPLEMENTED("executionState.indexType %d" , int(executionState.indexType)); |
594 | } |
595 | } |
596 | else |
597 | { |
598 | indexBuffers.push_back({pipeline->computePrimitiveCount(count), indexBuffer}); |
599 | } |
600 | } |
601 | else |
602 | { |
603 | indexBuffers.push_back({pipeline->computePrimitiveCount(count), nullptr}); |
604 | } |
605 | |
606 | for (uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++) |
607 | { |
608 | // FIXME: reconsider instances/views nesting. |
609 | auto viewMask = executionState.renderPass->getViewMask(executionState.subpassIndex); |
610 | while (viewMask) |
611 | { |
612 | int viewID = sw::log2i(viewMask); |
613 | viewMask &= ~(1 << viewID); |
614 | |
615 | for (auto indexBuffer : indexBuffers) |
616 | { |
617 | executionState.renderer->draw(&context, executionState.indexType, indexBuffer.first, vertexOffset, |
618 | executionState.events, instance, viewID, indexBuffer.second, |
619 | executionState.renderPassFramebuffer->getExtent(), |
620 | executionState.pushConstants); |
621 | } |
622 | } |
623 | |
624 | executionState.renderer->advanceInstanceAttributes(context.input); |
625 | } |
626 | } |
627 | }; |
628 | |
629 | struct Draw : public DrawBase |
630 | { |
631 | Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) |
632 | : vertexCount(vertexCount), instanceCount(instanceCount), firstVertex(firstVertex), firstInstance(firstInstance) |
633 | { |
634 | } |
635 | |
636 | void play(CommandBuffer::ExecutionState& executionState) override |
637 | { |
638 | draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance); |
639 | } |
640 | |
641 | private: |
642 | uint32_t vertexCount; |
643 | uint32_t instanceCount; |
644 | uint32_t firstVertex; |
645 | uint32_t firstInstance; |
646 | }; |
647 | |
648 | struct DrawIndexed : public DrawBase |
649 | { |
650 | DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) |
651 | : indexCount(indexCount), instanceCount(instanceCount), firstIndex(firstIndex), vertexOffset(vertexOffset), firstInstance(firstInstance) |
652 | { |
653 | } |
654 | |
655 | void play(CommandBuffer::ExecutionState& executionState) override |
656 | { |
657 | draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); |
658 | } |
659 | |
660 | private: |
661 | uint32_t indexCount; |
662 | uint32_t instanceCount; |
663 | uint32_t firstIndex; |
664 | int32_t vertexOffset; |
665 | uint32_t firstInstance; |
666 | }; |
667 | |
668 | struct DrawIndirect : public DrawBase |
669 | { |
670 | DrawIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) |
671 | : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride) |
672 | { |
673 | } |
674 | |
675 | void play(CommandBuffer::ExecutionState& executionState) override |
676 | { |
677 | for (auto drawId = 0u; drawId < drawCount; drawId++) |
678 | { |
679 | auto cmd = reinterpret_cast<VkDrawIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride)); |
680 | draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance); |
681 | } |
682 | } |
683 | |
684 | private: |
685 | const Buffer* buffer; |
686 | VkDeviceSize offset; |
687 | uint32_t drawCount; |
688 | uint32_t stride; |
689 | }; |
690 | |
691 | struct DrawIndexedIndirect : public DrawBase |
692 | { |
693 | DrawIndexedIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) |
694 | : buffer(buffer), offset(offset), drawCount(drawCount), stride(stride) |
695 | { |
696 | } |
697 | |
698 | void play(CommandBuffer::ExecutionState& executionState) override |
699 | { |
700 | for (auto drawId = 0u; drawId < drawCount; drawId++) |
701 | { |
702 | auto cmd = reinterpret_cast<VkDrawIndexedIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride)); |
703 | draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance); |
704 | } |
705 | } |
706 | |
707 | private: |
708 | const Buffer* buffer; |
709 | VkDeviceSize offset; |
710 | uint32_t drawCount; |
711 | uint32_t stride; |
712 | }; |
713 | |
714 | struct ImageToImageCopy : public CommandBuffer::Command |
715 | { |
716 | ImageToImageCopy(const Image* srcImage, Image* dstImage, const VkImageCopy& region) : |
717 | srcImage(srcImage), dstImage(dstImage), region(region) |
718 | { |
719 | } |
720 | |
721 | void play(CommandBuffer::ExecutionState& executionState) override |
722 | { |
723 | srcImage->copyTo(dstImage, region); |
724 | } |
725 | |
726 | private: |
727 | const Image* srcImage; |
728 | Image* dstImage; |
729 | const VkImageCopy region; |
730 | }; |
731 | |
732 | struct BufferToBufferCopy : public CommandBuffer::Command |
733 | { |
734 | BufferToBufferCopy(const Buffer* srcBuffer, Buffer* dstBuffer, const VkBufferCopy& region) : |
735 | srcBuffer(srcBuffer), dstBuffer(dstBuffer), region(region) |
736 | { |
737 | } |
738 | |
739 | void play(CommandBuffer::ExecutionState& executionState) override |
740 | { |
741 | srcBuffer->copyTo(dstBuffer, region); |
742 | } |
743 | |
744 | private: |
745 | const Buffer* srcBuffer; |
746 | Buffer* dstBuffer; |
747 | const VkBufferCopy region; |
748 | }; |
749 | |
750 | struct ImageToBufferCopy : public CommandBuffer::Command |
751 | { |
752 | ImageToBufferCopy(Image* srcImage, Buffer* dstBuffer, const VkBufferImageCopy& region) : |
753 | srcImage(srcImage), dstBuffer(dstBuffer), region(region) |
754 | { |
755 | } |
756 | |
757 | void play(CommandBuffer::ExecutionState& executionState) override |
758 | { |
759 | srcImage->copyTo(dstBuffer, region); |
760 | } |
761 | |
762 | private: |
763 | Image* srcImage; |
764 | Buffer* dstBuffer; |
765 | const VkBufferImageCopy region; |
766 | }; |
767 | |
768 | struct BufferToImageCopy : public CommandBuffer::Command |
769 | { |
770 | BufferToImageCopy(Buffer* srcBuffer, Image* dstImage, const VkBufferImageCopy& region) : |
771 | srcBuffer(srcBuffer), dstImage(dstImage), region(region) |
772 | { |
773 | } |
774 | |
775 | void play(CommandBuffer::ExecutionState& executionState) override |
776 | { |
777 | dstImage->copyFrom(srcBuffer, region); |
778 | } |
779 | |
780 | private: |
781 | Buffer* srcBuffer; |
782 | Image* dstImage; |
783 | const VkBufferImageCopy region; |
784 | }; |
785 | |
786 | struct FillBuffer : public CommandBuffer::Command |
787 | { |
788 | FillBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) : |
789 | dstBuffer(dstBuffer), dstOffset(dstOffset), size(size), data(data) |
790 | { |
791 | } |
792 | |
793 | void play(CommandBuffer::ExecutionState& executionState) override |
794 | { |
795 | dstBuffer->fill(dstOffset, size, data); |
796 | } |
797 | |
798 | private: |
799 | Buffer* dstBuffer; |
800 | VkDeviceSize dstOffset; |
801 | VkDeviceSize size; |
802 | uint32_t data; |
803 | }; |
804 | |
805 | struct UpdateBuffer : public CommandBuffer::Command |
806 | { |
807 | UpdateBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint8_t* pData) : |
808 | dstBuffer(dstBuffer), dstOffset(dstOffset), data(pData, &pData[dataSize]) |
809 | { |
810 | } |
811 | |
812 | void play(CommandBuffer::ExecutionState& executionState) override |
813 | { |
814 | dstBuffer->update(dstOffset, data.size(), data.data()); |
815 | } |
816 | |
817 | private: |
818 | Buffer* dstBuffer; |
819 | VkDeviceSize dstOffset; |
820 | std::vector<uint8_t> data; // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations |
821 | }; |
822 | |
823 | struct ClearColorImage : public CommandBuffer::Command |
824 | { |
825 | ClearColorImage(Image* image, const VkClearColorValue& color, const VkImageSubresourceRange& range) : |
826 | image(image), color(color), range(range) |
827 | { |
828 | } |
829 | |
830 | void play(CommandBuffer::ExecutionState& executionState) override |
831 | { |
832 | image->clear(color, range); |
833 | } |
834 | |
835 | private: |
836 | Image* image; |
837 | const VkClearColorValue color; |
838 | const VkImageSubresourceRange range; |
839 | }; |
840 | |
841 | struct ClearDepthStencilImage : public CommandBuffer::Command |
842 | { |
843 | ClearDepthStencilImage(Image* image, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range) : |
844 | image(image), depthStencil(depthStencil), range(range) |
845 | { |
846 | } |
847 | |
848 | void play(CommandBuffer::ExecutionState& executionState) override |
849 | { |
850 | image->clear(depthStencil, range); |
851 | } |
852 | |
853 | private: |
854 | Image* image; |
855 | const VkClearDepthStencilValue depthStencil; |
856 | const VkImageSubresourceRange range; |
857 | }; |
858 | |
859 | struct ClearAttachment : public CommandBuffer::Command |
860 | { |
861 | ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect) : |
862 | attachment(attachment), rect(rect) |
863 | { |
864 | } |
865 | |
866 | void play(CommandBuffer::ExecutionState& executionState) override |
867 | { |
868 | // attachment clears are drawing operations, and so have rasterization-order guarantees. |
869 | // however, we don't do the clear through the rasterizer, so need to ensure prior drawing |
870 | // has completed first. |
871 | executionState.renderer->synchronize(); |
872 | executionState.renderPassFramebuffer->clearAttachment(executionState.renderPass, executionState.subpassIndex, attachment, rect); |
873 | } |
874 | |
875 | private: |
876 | const VkClearAttachment attachment; |
877 | const VkClearRect rect; |
878 | }; |
879 | |
880 | struct BlitImage : public CommandBuffer::Command |
881 | { |
882 | BlitImage(const Image* srcImage, Image* dstImage, const VkImageBlit& region, VkFilter filter) : |
883 | srcImage(srcImage), dstImage(dstImage), region(region), filter(filter) |
884 | { |
885 | } |
886 | |
887 | void play(CommandBuffer::ExecutionState& executionState) override |
888 | { |
889 | srcImage->blit(dstImage, region, filter); |
890 | } |
891 | |
892 | private: |
893 | const Image* srcImage; |
894 | Image* dstImage; |
895 | VkImageBlit region; |
896 | VkFilter filter; |
897 | }; |
898 | |
899 | struct ResolveImage : public CommandBuffer::Command |
900 | { |
901 | ResolveImage(const Image* srcImage, Image* dstImage, const VkImageResolve& region) : |
902 | srcImage(srcImage), dstImage(dstImage), region(region) |
903 | { |
904 | } |
905 | |
906 | void play(CommandBuffer::ExecutionState& executionState) override |
907 | { |
908 | srcImage->resolve(dstImage, region); |
909 | } |
910 | |
911 | private: |
912 | const Image* srcImage; |
913 | Image* dstImage; |
914 | VkImageResolve region; |
915 | }; |
916 | |
917 | struct PipelineBarrier : public CommandBuffer::Command |
918 | { |
919 | PipelineBarrier() |
920 | { |
921 | } |
922 | |
923 | void play(CommandBuffer::ExecutionState& executionState) override |
924 | { |
925 | // This is a very simple implementation that simply calls sw::Renderer::synchronize(), |
926 | // since the driver is free to move the source stage towards the bottom of the pipe |
927 | // and the target stage towards the top, so a full pipeline sync is spec compliant. |
928 | executionState.renderer->synchronize(); |
929 | |
930 | // Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs. |
931 | |
932 | // Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary. |
933 | } |
934 | |
935 | private: |
936 | }; |
937 | |
938 | struct SignalEvent : public CommandBuffer::Command |
939 | { |
940 | SignalEvent(Event* ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask) |
941 | { |
942 | } |
943 | |
944 | void play(CommandBuffer::ExecutionState& executionState) override |
945 | { |
946 | executionState.renderer->synchronize(); |
947 | ev->signal(); |
948 | } |
949 | |
950 | private: |
951 | Event* ev; |
952 | VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and signal the event at the last stage |
953 | }; |
954 | |
955 | struct ResetEvent : public CommandBuffer::Command |
956 | { |
957 | ResetEvent(Event* ev, VkPipelineStageFlags stageMask) : ev(ev), stageMask(stageMask) |
958 | { |
959 | } |
960 | |
961 | void play(CommandBuffer::ExecutionState& executionState) override |
962 | { |
963 | ev->reset(); |
964 | } |
965 | |
966 | private: |
967 | Event* ev; |
968 | VkPipelineStageFlags stageMask; // FIXME(b/117835459) : We currently ignore the flags and reset the event at the last stage |
969 | }; |
970 | |
971 | struct WaitEvent : public CommandBuffer::Command |
972 | { |
973 | WaitEvent(Event* ev) : ev(ev) |
974 | { |
975 | } |
976 | |
977 | void play(CommandBuffer::ExecutionState& executionState) override |
978 | { |
979 | executionState.renderer->synchronize(); |
980 | ev->wait(); |
981 | } |
982 | |
983 | private: |
984 | Event* ev; |
985 | }; |
986 | |
987 | struct BindDescriptorSet : public CommandBuffer::Command |
988 | { |
989 | BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout *pipelineLayout, uint32_t set, DescriptorSet* descriptorSet, |
990 | uint32_t dynamicOffsetCount, uint32_t const *dynamicOffsets) |
991 | : pipelineBindPoint(pipelineBindPoint), pipelineLayout(pipelineLayout), set(set), descriptorSet(descriptorSet), |
992 | dynamicOffsetCount(dynamicOffsetCount) |
993 | { |
994 | for (uint32_t i = 0; i < dynamicOffsetCount; i++) |
995 | { |
996 | this->dynamicOffsets[i] = dynamicOffsets[i]; |
997 | } |
998 | } |
999 | |
1000 | void play(CommandBuffer::ExecutionState& executionState) |
1001 | { |
1002 | ASSERT_OR_RETURN((pipelineBindPoint < VK_PIPELINE_BIND_POINT_RANGE_SIZE) && (set < MAX_BOUND_DESCRIPTOR_SETS)); |
1003 | auto &pipelineState = executionState.pipelineState[pipelineBindPoint]; |
1004 | auto dynamicOffsetBase = pipelineLayout->getDynamicOffsetBase(set); |
1005 | ASSERT_OR_RETURN(dynamicOffsetBase + dynamicOffsetCount <= MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC); |
1006 | |
1007 | pipelineState.descriptorSets[set] = descriptorSet; |
1008 | for (uint32_t i = 0; i < dynamicOffsetCount; i++) |
1009 | { |
1010 | pipelineState.descriptorDynamicOffsets[dynamicOffsetBase + i] = dynamicOffsets[i]; |
1011 | } |
1012 | } |
1013 | |
1014 | private: |
1015 | VkPipelineBindPoint pipelineBindPoint; |
1016 | const PipelineLayout *pipelineLayout; |
1017 | uint32_t set; |
1018 | vk::DescriptorSet* descriptorSet; |
1019 | uint32_t dynamicOffsetCount; |
1020 | DescriptorSet::DynamicOffsets dynamicOffsets; |
1021 | }; |
1022 | |
1023 | struct SetPushConstants : public CommandBuffer::Command |
1024 | { |
1025 | SetPushConstants(uint32_t offset, uint32_t size, void const *pValues) |
1026 | : offset(offset), size(size) |
1027 | { |
1028 | ASSERT(offset < MAX_PUSH_CONSTANT_SIZE); |
1029 | ASSERT(offset + size <= MAX_PUSH_CONSTANT_SIZE); |
1030 | |
1031 | memcpy(data, pValues, size); |
1032 | } |
1033 | |
1034 | void play(CommandBuffer::ExecutionState& executionState) |
1035 | { |
1036 | memcpy(&executionState.pushConstants.data[offset], data, size); |
1037 | } |
1038 | |
1039 | private: |
1040 | uint32_t offset; |
1041 | uint32_t size; |
1042 | unsigned char data[MAX_PUSH_CONSTANT_SIZE]; |
1043 | }; |
1044 | |
1045 | struct BeginQuery : public CommandBuffer::Command |
1046 | { |
1047 | BeginQuery(QueryPool* queryPool, uint32_t query, VkQueryControlFlags flags) |
1048 | : queryPool(queryPool), query(query), flags(flags) |
1049 | { |
1050 | } |
1051 | |
1052 | void play(CommandBuffer::ExecutionState& executionState) |
1053 | { |
1054 | queryPool->begin(query, flags); |
1055 | executionState.renderer->addQuery(queryPool->getQuery(query)); |
1056 | } |
1057 | |
1058 | private: |
1059 | QueryPool* queryPool; |
1060 | uint32_t query; |
1061 | VkQueryControlFlags flags; |
1062 | }; |
1063 | |
1064 | struct EndQuery : public CommandBuffer::Command |
1065 | { |
1066 | EndQuery(QueryPool* queryPool, uint32_t query) |
1067 | : queryPool(queryPool), query(query) |
1068 | { |
1069 | } |
1070 | |
1071 | void play(CommandBuffer::ExecutionState& executionState) |
1072 | { |
1073 | executionState.renderer->removeQuery(queryPool->getQuery(query)); |
1074 | queryPool->end(query); |
1075 | } |
1076 | |
1077 | private: |
1078 | QueryPool* queryPool; |
1079 | uint32_t query; |
1080 | }; |
1081 | |
1082 | struct ResetQueryPool : public CommandBuffer::Command |
1083 | { |
1084 | ResetQueryPool(QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount) |
1085 | : queryPool(queryPool), firstQuery(firstQuery), queryCount(queryCount) |
1086 | { |
1087 | } |
1088 | |
1089 | void play(CommandBuffer::ExecutionState& executionState) |
1090 | { |
1091 | queryPool->reset(firstQuery, queryCount); |
1092 | } |
1093 | |
1094 | private: |
1095 | QueryPool* queryPool; |
1096 | uint32_t firstQuery; |
1097 | uint32_t queryCount; |
1098 | }; |
1099 | |
1100 | struct WriteTimeStamp : public CommandBuffer::Command |
1101 | { |
1102 | WriteTimeStamp(QueryPool* queryPool, uint32_t query, VkPipelineStageFlagBits stage) |
1103 | : queryPool(queryPool), query(query), stage(stage) |
1104 | { |
1105 | } |
1106 | |
1107 | void play(CommandBuffer::ExecutionState& executionState) |
1108 | { |
1109 | if (stage & ~(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT)) |
1110 | { |
1111 | // The `top of pipe` and `draw indirect` stages are handled in command buffer processing so a timestamp write |
1112 | // done in those stages can just be done here without any additional synchronization. |
1113 | // Everything else is deferred to the Renderer; we will treat those stages all as if they were |
1114 | // `bottom of pipe`. |
1115 | // |
1116 | // FIXME(chrisforbes): once Marl is integrated, do this in a task so we don't have to stall here. |
1117 | executionState.renderer->synchronize(); |
1118 | } |
1119 | |
1120 | queryPool->writeTimestamp(query); |
1121 | } |
1122 | |
1123 | private: |
1124 | QueryPool* queryPool; |
1125 | uint32_t query; |
1126 | VkPipelineStageFlagBits stage; |
1127 | }; |
1128 | |
1129 | struct CopyQueryPoolResults : public CommandBuffer::Command |
1130 | { |
1131 | CopyQueryPoolResults(const QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount, |
1132 | Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) |
1133 | : queryPool(queryPool), firstQuery(firstQuery), queryCount(queryCount), |
1134 | dstBuffer(dstBuffer), dstOffset(dstOffset), stride(stride), flags(flags) |
1135 | { |
1136 | } |
1137 | |
1138 | void play(CommandBuffer::ExecutionState& executionState) |
1139 | { |
1140 | queryPool->getResults(firstQuery, queryCount, dstBuffer->getSize() - dstOffset, |
1141 | dstBuffer->getOffsetPointer(dstOffset), stride, flags); |
1142 | } |
1143 | |
1144 | private: |
1145 | const QueryPool* queryPool; |
1146 | uint32_t firstQuery; |
1147 | uint32_t queryCount; |
1148 | Buffer* dstBuffer; |
1149 | VkDeviceSize dstOffset; |
1150 | VkDeviceSize stride; |
1151 | VkQueryResultFlags flags; |
1152 | }; |
1153 | |
1154 | CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) : level(pLevel) |
1155 | { |
1156 | // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations |
1157 | commands = new std::vector<std::unique_ptr<Command> >(); |
1158 | } |
1159 | |
1160 | void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator) |
1161 | { |
1162 | delete commands; |
1163 | } |
1164 | |
1165 | void CommandBuffer::resetState() |
1166 | { |
1167 | // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations |
1168 | commands->clear(); |
1169 | |
1170 | state = INITIAL; |
1171 | } |
1172 | |
1173 | VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo) |
1174 | { |
1175 | ASSERT((state != RECORDING) && (state != PENDING)); |
1176 | |
1177 | // Nothing interesting to do based on flags. We don't have any optimizations |
1178 | // to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE |
1179 | // must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below. |
1180 | (void) flags; |
1181 | |
1182 | // pInheritanceInfo merely contains optimization hints, so we currently ignore it |
1183 | |
1184 | if(state != INITIAL) |
1185 | { |
1186 | // Implicit reset |
1187 | resetState(); |
1188 | } |
1189 | |
1190 | state = RECORDING; |
1191 | |
1192 | return VK_SUCCESS; |
1193 | } |
1194 | |
1195 | VkResult CommandBuffer::end() |
1196 | { |
1197 | ASSERT(state == RECORDING); |
1198 | |
1199 | state = EXECUTABLE; |
1200 | |
1201 | return VK_SUCCESS; |
1202 | } |
1203 | |
1204 | VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags) |
1205 | { |
1206 | ASSERT(state != PENDING); |
1207 | |
1208 | resetState(); |
1209 | |
1210 | return VK_SUCCESS; |
1211 | } |
1212 | |
1213 | template<typename T, typename... Args> |
1214 | void CommandBuffer::addCommand(Args&&... args) |
1215 | { |
1216 | // FIXME (b/119409619): use an allocator here so we can control all memory allocations |
1217 | commands->push_back(std::unique_ptr<T>(new T(std::forward<Args>(args)...))); |
1218 | } |
1219 | |
1220 | void CommandBuffer::beginRenderPass(RenderPass* renderPass, Framebuffer* framebuffer, VkRect2D renderArea, |
1221 | uint32_t clearValueCount, const VkClearValue* clearValues, VkSubpassContents contents) |
1222 | { |
1223 | ASSERT(state == RECORDING); |
1224 | |
1225 | addCommand<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues); |
1226 | } |
1227 | |
1228 | void CommandBuffer::nextSubpass(VkSubpassContents contents) |
1229 | { |
1230 | ASSERT(state == RECORDING); |
1231 | |
1232 | addCommand<NextSubpass>(); |
1233 | } |
1234 | |
1235 | void CommandBuffer::endRenderPass() |
1236 | { |
1237 | addCommand<EndRenderPass>(); |
1238 | } |
1239 | |
1240 | void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) |
1241 | { |
1242 | ASSERT(state == RECORDING); |
1243 | |
1244 | for(uint32_t i = 0; i < commandBufferCount; ++i) |
1245 | { |
1246 | addCommand<ExecuteCommands>(vk::Cast(pCommandBuffers[i])); |
1247 | } |
1248 | } |
1249 | |
1250 | void CommandBuffer::setDeviceMask(uint32_t deviceMask) |
1251 | { |
1252 | // SwiftShader only has one device, so we ignore the device mask |
1253 | } |
1254 | |
1255 | void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, |
1256 | uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) |
1257 | { |
1258 | addCommand<Dispatch>(baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ); |
1259 | } |
1260 | |
1261 | void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, |
1262 | VkDependencyFlags dependencyFlags, |
1263 | uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, |
1264 | uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, |
1265 | uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) |
1266 | { |
1267 | addCommand<PipelineBarrier>(); |
1268 | } |
1269 | |
1270 | void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline* pipeline) |
1271 | { |
1272 | switch(pipelineBindPoint) |
1273 | { |
1274 | case VK_PIPELINE_BIND_POINT_COMPUTE: |
1275 | case VK_PIPELINE_BIND_POINT_GRAPHICS: |
1276 | addCommand<PipelineBind>(pipelineBindPoint, pipeline); |
1277 | break; |
1278 | default: |
1279 | UNIMPLEMENTED("pipelineBindPoint" ); |
1280 | } |
1281 | } |
1282 | |
1283 | void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount, |
1284 | const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) |
1285 | { |
1286 | for(uint32_t i = 0; i < bindingCount; ++i) |
1287 | { |
1288 | addCommand<VertexBufferBind>(i + firstBinding, vk::Cast(pBuffers[i]), pOffsets[i]); |
1289 | } |
1290 | } |
1291 | |
1292 | void CommandBuffer::beginQuery(QueryPool* queryPool, uint32_t query, VkQueryControlFlags flags) |
1293 | { |
1294 | addCommand<BeginQuery>(queryPool, query, flags); |
1295 | } |
1296 | |
1297 | void CommandBuffer::endQuery(QueryPool* queryPool, uint32_t query) |
1298 | { |
1299 | addCommand<EndQuery>(queryPool, query); |
1300 | } |
1301 | |
1302 | void CommandBuffer::resetQueryPool(QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount) |
1303 | { |
1304 | addCommand<ResetQueryPool>(queryPool, firstQuery, queryCount); |
1305 | } |
1306 | |
1307 | void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, QueryPool* queryPool, uint32_t query) |
1308 | { |
1309 | addCommand<WriteTimeStamp>(queryPool, query, pipelineStage); |
1310 | } |
1311 | |
1312 | void CommandBuffer::copyQueryPoolResults(const QueryPool* queryPool, uint32_t firstQuery, uint32_t queryCount, |
1313 | Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) |
1314 | { |
1315 | addCommand<CopyQueryPoolResults>(queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags); |
1316 | } |
1317 | |
1318 | void CommandBuffer::pushConstants(PipelineLayout* layout, VkShaderStageFlags stageFlags, |
1319 | uint32_t offset, uint32_t size, const void* pValues) |
1320 | { |
1321 | addCommand<SetPushConstants>(offset, size, pValues); |
1322 | } |
1323 | |
1324 | void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports) |
1325 | { |
1326 | if(firstViewport != 0 || viewportCount > 1) |
1327 | { |
1328 | UNIMPLEMENTED("viewport" ); |
1329 | } |
1330 | |
1331 | for(uint32_t i = 0; i < viewportCount; i++) |
1332 | { |
1333 | addCommand<SetViewport>(pViewports[i], i + firstViewport); |
1334 | } |
1335 | } |
1336 | |
1337 | void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors) |
1338 | { |
1339 | if(firstScissor != 0 || scissorCount > 1) |
1340 | { |
1341 | UNIMPLEMENTED("scissor" ); |
1342 | } |
1343 | |
1344 | for(uint32_t i = 0; i < scissorCount; i++) |
1345 | { |
1346 | addCommand<SetScissor>(pScissors[i], i + firstScissor); |
1347 | } |
1348 | } |
1349 | |
1350 | void CommandBuffer::setLineWidth(float lineWidth) |
1351 | { |
1352 | // If the wide lines feature is not enabled, lineWidth must be 1.0 |
1353 | ASSERT(lineWidth == 1.0f); |
1354 | } |
1355 | |
1356 | void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) |
1357 | { |
1358 | addCommand<SetDepthBias>(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); |
1359 | } |
1360 | |
1361 | void CommandBuffer::setBlendConstants(const float blendConstants[4]) |
1362 | { |
1363 | addCommand<SetBlendConstants>(blendConstants); |
1364 | } |
1365 | |
1366 | void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds) |
1367 | { |
1368 | addCommand<SetDepthBounds>(minDepthBounds, maxDepthBounds); |
1369 | } |
1370 | |
1371 | void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask) |
1372 | { |
1373 | // faceMask must not be 0 |
1374 | ASSERT(faceMask != 0); |
1375 | |
1376 | addCommand<SetStencilCompareMask>(faceMask, compareMask); |
1377 | } |
1378 | |
1379 | void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask) |
1380 | { |
1381 | // faceMask must not be 0 |
1382 | ASSERT(faceMask != 0); |
1383 | |
1384 | addCommand<SetStencilWriteMask>(faceMask, writeMask); |
1385 | } |
1386 | |
1387 | void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference) |
1388 | { |
1389 | // faceMask must not be 0 |
1390 | ASSERT(faceMask != 0); |
1391 | |
1392 | addCommand<SetStencilReference>(faceMask, reference); |
1393 | } |
1394 | |
1395 | void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout* layout, |
1396 | uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, |
1397 | uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) |
1398 | { |
1399 | ASSERT(state == RECORDING); |
1400 | |
1401 | for(uint32_t i = 0; i < descriptorSetCount; i++) |
1402 | { |
1403 | auto descriptorSetIndex = firstSet + i; |
1404 | auto setLayout = layout->getDescriptorSetLayout(descriptorSetIndex); |
1405 | |
1406 | auto numDynamicDescriptors = setLayout->getDynamicDescriptorCount(); |
1407 | ASSERT(numDynamicDescriptors == 0 || pDynamicOffsets != nullptr); |
1408 | ASSERT(dynamicOffsetCount >= numDynamicDescriptors); |
1409 | |
1410 | addCommand<BindDescriptorSet>( |
1411 | pipelineBindPoint, layout, descriptorSetIndex, vk::Cast(pDescriptorSets[i]), |
1412 | dynamicOffsetCount, pDynamicOffsets); |
1413 | |
1414 | pDynamicOffsets += numDynamicDescriptors; |
1415 | dynamicOffsetCount -= numDynamicDescriptors; |
1416 | } |
1417 | } |
1418 | |
1419 | void CommandBuffer::bindIndexBuffer(Buffer* buffer, VkDeviceSize offset, VkIndexType indexType) |
1420 | { |
1421 | addCommand<IndexBufferBind>(buffer, offset, indexType); |
1422 | } |
1423 | |
1424 | void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) |
1425 | { |
1426 | addCommand<Dispatch>(0, 0, 0, groupCountX, groupCountY, groupCountZ); |
1427 | } |
1428 | |
1429 | void CommandBuffer::dispatchIndirect(Buffer* buffer, VkDeviceSize offset) |
1430 | { |
1431 | addCommand<DispatchIndirect>(buffer, offset); |
1432 | } |
1433 | |
1434 | void CommandBuffer::copyBuffer(const Buffer* srcBuffer, Buffer* dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) |
1435 | { |
1436 | ASSERT(state == RECORDING); |
1437 | |
1438 | for(uint32_t i = 0; i < regionCount; i++) |
1439 | { |
1440 | addCommand<BufferToBufferCopy>(srcBuffer, dstBuffer, pRegions[i]); |
1441 | } |
1442 | } |
1443 | |
1444 | void CommandBuffer::copyImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
1445 | uint32_t regionCount, const VkImageCopy* pRegions) |
1446 | { |
1447 | ASSERT(state == RECORDING); |
1448 | ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || |
1449 | srcImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1450 | ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || |
1451 | dstImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1452 | |
1453 | for(uint32_t i = 0; i < regionCount; i++) |
1454 | { |
1455 | addCommand<ImageToImageCopy>(srcImage, dstImage, pRegions[i]); |
1456 | } |
1457 | } |
1458 | |
1459 | void CommandBuffer::blitImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
1460 | uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) |
1461 | { |
1462 | ASSERT(state == RECORDING); |
1463 | ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || |
1464 | srcImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1465 | ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || |
1466 | dstImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1467 | |
1468 | for(uint32_t i = 0; i < regionCount; i++) |
1469 | { |
1470 | addCommand<BlitImage>(srcImage, dstImage, pRegions[i], filter); |
1471 | } |
1472 | } |
1473 | |
1474 | void CommandBuffer::copyBufferToImage(Buffer* srcBuffer, Image* dstImage, VkImageLayout dstImageLayout, |
1475 | uint32_t regionCount, const VkBufferImageCopy* pRegions) |
1476 | { |
1477 | ASSERT(state == RECORDING); |
1478 | |
1479 | for(uint32_t i = 0; i < regionCount; i++) |
1480 | { |
1481 | addCommand<BufferToImageCopy>(srcBuffer, dstImage, pRegions[i]); |
1482 | } |
1483 | } |
1484 | |
1485 | void CommandBuffer::copyImageToBuffer(Image* srcImage, VkImageLayout srcImageLayout, Buffer* dstBuffer, |
1486 | uint32_t regionCount, const VkBufferImageCopy* pRegions) |
1487 | { |
1488 | ASSERT(state == RECORDING); |
1489 | ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || srcImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1490 | |
1491 | for(uint32_t i = 0; i < regionCount; i++) |
1492 | { |
1493 | addCommand<ImageToBufferCopy>(srcImage, dstBuffer, pRegions[i]); |
1494 | } |
1495 | } |
1496 | |
1497 | void CommandBuffer::updateBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData) |
1498 | { |
1499 | ASSERT(state == RECORDING); |
1500 | |
1501 | addCommand<UpdateBuffer>(dstBuffer, dstOffset, dataSize, reinterpret_cast<const uint8_t*>(pData)); |
1502 | } |
1503 | |
1504 | void CommandBuffer::fillBuffer(Buffer* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) |
1505 | { |
1506 | ASSERT(state == RECORDING); |
1507 | |
1508 | addCommand<FillBuffer>(dstBuffer, dstOffset, size, data); |
1509 | } |
1510 | |
1511 | void CommandBuffer::clearColorImage(Image* image, VkImageLayout imageLayout, const VkClearColorValue* pColor, |
1512 | uint32_t rangeCount, const VkImageSubresourceRange* pRanges) |
1513 | { |
1514 | ASSERT(state == RECORDING); |
1515 | |
1516 | for(uint32_t i = 0; i < rangeCount; i++) |
1517 | { |
1518 | addCommand<ClearColorImage>(image, *pColor, pRanges[i]); |
1519 | } |
1520 | } |
1521 | |
1522 | void CommandBuffer::clearDepthStencilImage(Image* image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, |
1523 | uint32_t rangeCount, const VkImageSubresourceRange* pRanges) |
1524 | { |
1525 | ASSERT(state == RECORDING); |
1526 | |
1527 | for(uint32_t i = 0; i < rangeCount; i++) |
1528 | { |
1529 | addCommand<ClearDepthStencilImage>(image, *pDepthStencil, pRanges[i]); |
1530 | } |
1531 | } |
1532 | |
1533 | void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment* pAttachments, |
1534 | uint32_t rectCount, const VkClearRect* pRects) |
1535 | { |
1536 | ASSERT(state == RECORDING); |
1537 | |
1538 | for(uint32_t i = 0; i < attachmentCount; i++) |
1539 | { |
1540 | for(uint32_t j = 0; j < rectCount; j++) |
1541 | { |
1542 | addCommand<ClearAttachment>(pAttachments[i], pRects[j]); |
1543 | } |
1544 | } |
1545 | } |
1546 | |
1547 | void CommandBuffer::resolveImage(const Image* srcImage, VkImageLayout srcImageLayout, Image* dstImage, VkImageLayout dstImageLayout, |
1548 | uint32_t regionCount, const VkImageResolve* pRegions) |
1549 | { |
1550 | ASSERT(state == RECORDING); |
1551 | ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL || |
1552 | srcImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1553 | ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL || |
1554 | dstImageLayout == VK_IMAGE_LAYOUT_GENERAL); |
1555 | |
1556 | for(uint32_t i = 0; i < regionCount; i++) |
1557 | { |
1558 | addCommand<ResolveImage>(srcImage, dstImage, pRegions[i]); |
1559 | } |
1560 | } |
1561 | |
1562 | void CommandBuffer::setEvent(Event* event, VkPipelineStageFlags stageMask) |
1563 | { |
1564 | ASSERT(state == RECORDING); |
1565 | |
1566 | addCommand<SignalEvent>(event, stageMask); |
1567 | } |
1568 | |
1569 | void CommandBuffer::resetEvent(Event* event, VkPipelineStageFlags stageMask) |
1570 | { |
1571 | ASSERT(state == RECORDING); |
1572 | |
1573 | addCommand<ResetEvent>(event, stageMask); |
1574 | } |
1575 | |
1576 | void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, |
1577 | VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, |
1578 | uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, |
1579 | uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) |
1580 | { |
1581 | ASSERT(state == RECORDING); |
1582 | |
1583 | // TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored |
1584 | |
1585 | // Note: srcStageMask and dstStageMask are currently ignored |
1586 | for(uint32_t i = 0; i < eventCount; i++) |
1587 | { |
1588 | addCommand<WaitEvent>(vk::Cast(pEvents[i])); |
1589 | } |
1590 | } |
1591 | |
1592 | void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) |
1593 | { |
1594 | addCommand<Draw>(vertexCount, instanceCount, firstVertex, firstInstance); |
1595 | } |
1596 | |
1597 | void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) |
1598 | { |
1599 | addCommand<DrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); |
1600 | } |
1601 | |
1602 | void CommandBuffer::drawIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) |
1603 | { |
1604 | addCommand<DrawIndirect>(buffer, offset, drawCount, stride); |
1605 | } |
1606 | |
1607 | void CommandBuffer::drawIndexedIndirect(Buffer* buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) |
1608 | { |
1609 | addCommand<DrawIndexedIndirect>(buffer, offset, drawCount, stride); |
1610 | } |
1611 | |
1612 | void CommandBuffer::submit(CommandBuffer::ExecutionState& executionState) |
1613 | { |
1614 | // Perform recorded work |
1615 | state = PENDING; |
1616 | |
1617 | for(auto& command : *commands) |
1618 | { |
1619 | command->play(executionState); |
1620 | } |
1621 | |
1622 | // After work is completed |
1623 | state = EXECUTABLE; |
1624 | } |
1625 | |
1626 | void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState& executionState) const |
1627 | { |
1628 | for(auto& command : *commands) |
1629 | { |
1630 | command->play(executionState); |
1631 | } |
1632 | } |
1633 | |
1634 | } // namespace vk |
1635 | |