• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include "VkBuffer.hpp"
18 #include "VkConfig.hpp"
19 #include "VkDevice.hpp"
20 #include "VkEvent.hpp"
21 #include "VkFence.hpp"
22 #include "VkFramebuffer.hpp"
23 #include "VkImage.hpp"
24 #include "VkImageView.hpp"
25 #include "VkPipeline.hpp"
26 #include "VkPipelineLayout.hpp"
27 #include "VkQueryPool.hpp"
28 #include "VkRenderPass.hpp"
29 #include "Device/Renderer.hpp"
30 
31 #include "./Debug/Context.hpp"
32 #include "./Debug/File.hpp"
33 #include "./Debug/Thread.hpp"
34 
35 #include "marl/defer.h"
36 
37 #include <bitset>
38 #include <cstring>
39 
40 namespace {
41 
42 class CmdBeginRenderPass : public vk::CommandBuffer::Command
43 {
44 public:
CmdBeginRenderPass(vk::RenderPass * renderPass,vk::Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * pClearValues)45 	CmdBeginRenderPass(vk::RenderPass *renderPass, vk::Framebuffer *framebuffer, VkRect2D renderArea,
46 	                   uint32_t clearValueCount, const VkClearValue *pClearValues)
47 	    : renderPass(renderPass)
48 	    , framebuffer(framebuffer)
49 	    , renderArea(renderArea)
50 	    , clearValueCount(clearValueCount)
51 	{
52 		// FIXME(b/119409619): use an allocator here so we can control all memory allocations
53 		clearValues = new VkClearValue[clearValueCount];
54 		memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
55 	}
56 
~CmdBeginRenderPass()57 	~CmdBeginRenderPass() override
58 	{
59 		delete[] clearValues;
60 	}
61 
execute(vk::CommandBuffer::ExecutionState & executionState)62 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
63 	{
64 		executionState.renderPass = renderPass;
65 		executionState.renderPassFramebuffer = framebuffer;
66 		executionState.subpassIndex = 0;
67 
68 		// Vulkan specifies that the attachments' `loadOp` gets executed "at the beginning of the subpass where it is first used."
69 		// Since we don't discard any contents between subpasses, this is equivalent to executing it at the start of the renderpass.
70 		framebuffer->executeLoadOp(executionState.renderPass, clearValueCount, clearValues, renderArea);
71 	}
72 
description()73 	std::string description() override { return "vkCmdBeginRenderPass()"; }
74 
75 private:
76 	vk::RenderPass *const renderPass;
77 	vk::Framebuffer *const framebuffer;
78 	const VkRect2D renderArea;
79 	const uint32_t clearValueCount;
80 	VkClearValue *clearValues;
81 };
82 
83 class CmdNextSubpass : public vk::CommandBuffer::Command
84 {
85 public:
execute(vk::CommandBuffer::ExecutionState & executionState)86 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
87 	{
88 		bool hasResolveAttachments = (executionState.renderPass->getSubpass(executionState.subpassIndex).pResolveAttachments != nullptr);
89 		if(hasResolveAttachments)
90 		{
91 			// TODO(b/197691918): Avoid halt-the-world synchronization.
92 			executionState.renderer->synchronize();
93 
94 			// TODO(b/197691917): Eliminate redundant resolve operations.
95 			executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
96 		}
97 
98 		executionState.subpassIndex++;
99 	}
100 
description()101 	std::string description() override { return "vkCmdNextSubpass()"; }
102 };
103 
104 class CmdEndRenderPass : public vk::CommandBuffer::Command
105 {
106 public:
execute(vk::CommandBuffer::ExecutionState & executionState)107 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
108 	{
109 		// Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL.
110 		// TODO(b/197691918): Avoid halt-the-world synchronization.
111 		executionState.renderer->synchronize();
112 
113 		// TODO(b/197691917): Eliminate redundant resolve operations.
114 		executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
115 
116 		executionState.renderPass = nullptr;
117 		executionState.renderPassFramebuffer = nullptr;
118 	}
119 
description()120 	std::string description() override { return "vkCmdEndRenderPass()"; }
121 };
122 
123 class CmdExecuteCommands : public vk::CommandBuffer::Command
124 {
125 public:
CmdExecuteCommands(const vk::CommandBuffer * commandBuffer)126 	CmdExecuteCommands(const vk::CommandBuffer *commandBuffer)
127 	    : commandBuffer(commandBuffer)
128 	{
129 	}
130 
execute(vk::CommandBuffer::ExecutionState & executionState)131 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
132 	{
133 		commandBuffer->submitSecondary(executionState);
134 	}
135 
description()136 	std::string description() override { return "vkCmdExecuteCommands()"; }
137 
138 private:
139 	const vk::CommandBuffer *const commandBuffer;
140 };
141 
142 class CmdPipelineBind : public vk::CommandBuffer::Command
143 {
144 public:
CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint,vk::Pipeline * pipeline)145 	CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint, vk::Pipeline *pipeline)
146 	    : pipelineBindPoint(pipelineBindPoint)
147 	    , pipeline(pipeline)
148 	{
149 	}
150 
execute(vk::CommandBuffer::ExecutionState & executionState)151 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
152 	{
153 		executionState.pipelineState[pipelineBindPoint].pipeline = pipeline;
154 	}
155 
description()156 	std::string description() override { return "vkCmdPipelineBind()"; }
157 
158 private:
159 	const VkPipelineBindPoint pipelineBindPoint;
160 	vk::Pipeline *const pipeline;
161 };
162 
163 class CmdDispatch : public vk::CommandBuffer::Command
164 {
165 public:
CmdDispatch(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)166 	CmdDispatch(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
167 	    : baseGroupX(baseGroupX)
168 	    , baseGroupY(baseGroupY)
169 	    , baseGroupZ(baseGroupZ)
170 	    , groupCountX(groupCountX)
171 	    , groupCountY(groupCountY)
172 	    , groupCountZ(groupCountZ)
173 	{
174 	}
175 
execute(vk::CommandBuffer::ExecutionState & executionState)176 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
177 	{
178 		auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
179 
180 		vk::ComputePipeline *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
181 		pipeline->run(baseGroupX, baseGroupY, baseGroupZ,
182 		              groupCountX, groupCountY, groupCountZ,
183 		              pipelineState.descriptorSetObjects,
184 		              pipelineState.descriptorSets,
185 		              pipelineState.descriptorDynamicOffsets,
186 		              executionState.pushConstants);
187 	}
188 
description()189 	std::string description() override { return "vkCmdDispatch()"; }
190 
191 private:
192 	const uint32_t baseGroupX;
193 	const uint32_t baseGroupY;
194 	const uint32_t baseGroupZ;
195 	const uint32_t groupCountX;
196 	const uint32_t groupCountY;
197 	const uint32_t groupCountZ;
198 };
199 
200 class CmdDispatchIndirect : public vk::CommandBuffer::Command
201 {
202 public:
CmdDispatchIndirect(vk::Buffer * buffer,VkDeviceSize offset)203 	CmdDispatchIndirect(vk::Buffer *buffer, VkDeviceSize offset)
204 	    : buffer(buffer)
205 	    , offset(offset)
206 	{
207 	}
208 
execute(vk::CommandBuffer::ExecutionState & executionState)209 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
210 	{
211 		auto cmd = reinterpret_cast<VkDispatchIndirectCommand const *>(buffer->getOffsetPointer(offset));
212 
213 		auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
214 
215 		auto pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
216 		pipeline->run(0, 0, 0, cmd->x, cmd->y, cmd->z,
217 		              pipelineState.descriptorSetObjects,
218 		              pipelineState.descriptorSets,
219 		              pipelineState.descriptorDynamicOffsets,
220 		              executionState.pushConstants);
221 	}
222 
description()223 	std::string description() override { return "vkCmdDispatchIndirect()"; }
224 
225 private:
226 	const vk::Buffer *const buffer;
227 	const VkDeviceSize offset;
228 };
229 
230 class CmdVertexBufferBind : public vk::CommandBuffer::Command
231 {
232 public:
CmdVertexBufferBind(uint32_t binding,vk::Buffer * buffer,const VkDeviceSize offset)233 	CmdVertexBufferBind(uint32_t binding, vk::Buffer *buffer, const VkDeviceSize offset)
234 	    : binding(binding)
235 	    , buffer(buffer)
236 	    , offset(offset)
237 	{
238 	}
239 
execute(vk::CommandBuffer::ExecutionState & executionState)240 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
241 	{
242 		executionState.vertexInputBindings[binding] = { buffer, offset };
243 	}
244 
description()245 	std::string description() override { return "vkCmdVertexBufferBind()"; }
246 
247 private:
248 	const uint32_t binding;
249 	vk::Buffer *const buffer;
250 	const VkDeviceSize offset;
251 };
252 
253 class CmdIndexBufferBind : public vk::CommandBuffer::Command
254 {
255 public:
CmdIndexBufferBind(vk::Buffer * buffer,const VkDeviceSize offset,const VkIndexType indexType)256 	CmdIndexBufferBind(vk::Buffer *buffer, const VkDeviceSize offset, const VkIndexType indexType)
257 	    : buffer(buffer)
258 	    , offset(offset)
259 	    , indexType(indexType)
260 	{
261 	}
262 
execute(vk::CommandBuffer::ExecutionState & executionState)263 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
264 	{
265 		executionState.indexBufferBinding = { buffer, offset };
266 		executionState.indexType = indexType;
267 	}
268 
description()269 	std::string description() override { return "vkCmdIndexBufferBind()"; }
270 
271 private:
272 	vk::Buffer *const buffer;
273 	const VkDeviceSize offset;
274 	const VkIndexType indexType;
275 };
276 
277 class CmdSetViewport : public vk::CommandBuffer::Command
278 {
279 public:
CmdSetViewport(const VkViewport & viewport,uint32_t viewportID)280 	CmdSetViewport(const VkViewport &viewport, uint32_t viewportID)
281 	    : viewport(viewport)
282 	    , viewportID(viewportID)
283 	{
284 	}
285 
execute(vk::CommandBuffer::ExecutionState & executionState)286 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
287 	{
288 		executionState.dynamicState.viewport = viewport;
289 	}
290 
description()291 	std::string description() override { return "vkCmdSetViewport()"; }
292 
293 private:
294 	const VkViewport viewport;
295 	const uint32_t viewportID;
296 };
297 
298 class CmdSetScissor : public vk::CommandBuffer::Command
299 {
300 public:
CmdSetScissor(const VkRect2D & scissor,uint32_t scissorID)301 	CmdSetScissor(const VkRect2D &scissor, uint32_t scissorID)
302 	    : scissor(scissor)
303 	    , scissorID(scissorID)
304 	{
305 	}
306 
execute(vk::CommandBuffer::ExecutionState & executionState)307 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
308 	{
309 		executionState.dynamicState.scissor = scissor;
310 	}
311 
description()312 	std::string description() override { return "vkCmdSetScissor()"; }
313 
314 private:
315 	const VkRect2D scissor;
316 	const uint32_t scissorID;
317 };
318 
319 class CmdSetDepthBias : public vk::CommandBuffer::Command
320 {
321 public:
CmdSetDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)322 	CmdSetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
323 	    : depthBiasConstantFactor(depthBiasConstantFactor)
324 	    , depthBiasClamp(depthBiasClamp)
325 	    , depthBiasSlopeFactor(depthBiasSlopeFactor)
326 	{
327 	}
328 
execute(vk::CommandBuffer::ExecutionState & executionState)329 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
330 	{
331 		executionState.dynamicState.depthBiasConstantFactor = depthBiasConstantFactor;
332 		executionState.dynamicState.depthBiasClamp = depthBiasClamp;
333 		executionState.dynamicState.depthBiasSlopeFactor = depthBiasSlopeFactor;
334 	}
335 
description()336 	std::string description() override { return "vkCmdSetDepthBias()"; }
337 
338 private:
339 	const float depthBiasConstantFactor;
340 	const float depthBiasClamp;
341 	const float depthBiasSlopeFactor;
342 };
343 
344 class CmdSetBlendConstants : public vk::CommandBuffer::Command
345 {
346 public:
CmdSetBlendConstants(const float blendConstants[4])347 	CmdSetBlendConstants(const float blendConstants[4])
348 	{
349 		memcpy(this->blendConstants, blendConstants, sizeof(this->blendConstants));
350 	}
351 
execute(vk::CommandBuffer::ExecutionState & executionState)352 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
353 	{
354 		memcpy(&(executionState.dynamicState.blendConstants[0]), blendConstants, sizeof(blendConstants));
355 	}
356 
description()357 	std::string description() override { return "vkCmdSetBlendConstants()"; }
358 
359 private:
360 	float blendConstants[4];
361 };
362 
363 class CmdSetDepthBounds : public vk::CommandBuffer::Command
364 {
365 public:
CmdSetDepthBounds(float minDepthBounds,float maxDepthBounds)366 	CmdSetDepthBounds(float minDepthBounds, float maxDepthBounds)
367 	    : minDepthBounds(minDepthBounds)
368 	    , maxDepthBounds(maxDepthBounds)
369 	{
370 	}
371 
execute(vk::CommandBuffer::ExecutionState & executionState)372 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
373 	{
374 		executionState.dynamicState.minDepthBounds = minDepthBounds;
375 		executionState.dynamicState.maxDepthBounds = maxDepthBounds;
376 	}
377 
description()378 	std::string description() override { return "vkCmdSetDepthBounds()"; }
379 
380 private:
381 	const float minDepthBounds;
382 	const float maxDepthBounds;
383 };
384 
385 class CmdSetStencilCompareMask : public vk::CommandBuffer::Command
386 {
387 public:
CmdSetStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)388 	CmdSetStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
389 	    : faceMask(faceMask)
390 	    , compareMask(compareMask)
391 	{
392 	}
393 
execute(vk::CommandBuffer::ExecutionState & executionState)394 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
395 	{
396 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
397 		{
398 			executionState.dynamicState.compareMask[0] = compareMask;
399 		}
400 
401 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
402 		{
403 			executionState.dynamicState.compareMask[1] = compareMask;
404 		}
405 	}
406 
description()407 	std::string description() override { return "vkCmdSetStencilCompareMask()"; }
408 
409 private:
410 	const VkStencilFaceFlags faceMask;
411 	const uint32_t compareMask;
412 };
413 
414 class CmdSetStencilWriteMask : public vk::CommandBuffer::Command
415 {
416 public:
CmdSetStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)417 	CmdSetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
418 	    : faceMask(faceMask)
419 	    , writeMask(writeMask)
420 	{
421 	}
422 
execute(vk::CommandBuffer::ExecutionState & executionState)423 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
424 	{
425 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
426 		{
427 			executionState.dynamicState.writeMask[0] = writeMask;
428 		}
429 
430 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
431 		{
432 			executionState.dynamicState.writeMask[1] = writeMask;
433 		}
434 	}
435 
description()436 	std::string description() override { return "vkCmdSetStencilWriteMask()"; }
437 
438 private:
439 	const VkStencilFaceFlags faceMask;
440 	const uint32_t writeMask;
441 };
442 
443 class CmdSetStencilReference : public vk::CommandBuffer::Command
444 {
445 public:
CmdSetStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)446 	CmdSetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
447 	    : faceMask(faceMask)
448 	    , reference(reference)
449 	{
450 	}
451 
execute(vk::CommandBuffer::ExecutionState & executionState)452 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
453 	{
454 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
455 		{
456 			executionState.dynamicState.reference[0] = reference;
457 		}
458 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
459 		{
460 			executionState.dynamicState.reference[1] = reference;
461 		}
462 	}
463 
description()464 	std::string description() override { return "vkCmdSetStencilReference()"; }
465 
466 private:
467 	const VkStencilFaceFlags faceMask;
468 	const uint32_t reference;
469 };
470 
471 class CmdDrawBase : public vk::CommandBuffer::Command
472 {
473 public:
draw(vk::CommandBuffer::ExecutionState & executionState,bool indexed,uint32_t count,uint32_t instanceCount,uint32_t first,int32_t vertexOffset,uint32_t firstInstance)474 	void draw(vk::CommandBuffer::ExecutionState &executionState, bool indexed,
475 	          uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
476 	{
477 		auto const &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
478 
479 		auto *pipeline = static_cast<vk::GraphicsPipeline *>(pipelineState.pipeline);
480 
481 		vk::Attachments &attachments = pipeline->getAttachments();
482 		executionState.bindAttachments(&attachments);
483 
484 		vk::Inputs &inputs = pipeline->getInputs();
485 		inputs.updateDescriptorSets(pipelineState.descriptorSetObjects,
486 		                            pipelineState.descriptorSets,
487 		                            pipelineState.descriptorDynamicOffsets);
488 		inputs.setVertexInputBinding(executionState.vertexInputBindings);
489 		inputs.bindVertexInputs(firstInstance);
490 
491 		vk::IndexBuffer &indexBuffer = pipeline->getIndexBuffer();
492 		indexBuffer.setIndexBufferBinding(executionState.indexBufferBinding, executionState.indexType);
493 
494 		std::vector<std::pair<uint32_t, void *>> indexBuffers;
495 		pipeline->getIndexBuffers(count, first, indexed, &indexBuffers);
496 
497 		for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
498 		{
499 			// FIXME: reconsider instances/views nesting.
500 			auto viewMask = executionState.renderPass->getViewMask(executionState.subpassIndex);
501 			while(viewMask)
502 			{
503 				int viewID = sw::log2i(viewMask);
504 				viewMask &= ~(1 << viewID);
505 
506 				for(auto indexBuffer : indexBuffers)
507 				{
508 					executionState.renderer->draw(pipeline, executionState.dynamicState, indexBuffer.first, vertexOffset,
509 					                              executionState.events, instance, viewID, indexBuffer.second,
510 					                              executionState.renderPassFramebuffer->getExtent(),
511 					                              executionState.pushConstants);
512 				}
513 			}
514 
515 			inputs.advanceInstanceAttributes();
516 		}
517 	}
518 };
519 
520 class CmdDraw : public CmdDrawBase
521 {
522 public:
CmdDraw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)523 	CmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
524 	    : vertexCount(vertexCount)
525 	    , instanceCount(instanceCount)
526 	    , firstVertex(firstVertex)
527 	    , firstInstance(firstInstance)
528 	{
529 	}
530 
execute(vk::CommandBuffer::ExecutionState & executionState)531 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
532 	{
533 		draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
534 	}
535 
description()536 	std::string description() override { return "vkCmdDraw()"; }
537 
538 private:
539 	const uint32_t vertexCount;
540 	const uint32_t instanceCount;
541 	const uint32_t firstVertex;
542 	const uint32_t firstInstance;
543 };
544 
545 class CmdDrawIndexed : public CmdDrawBase
546 {
547 public:
CmdDrawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)548 	CmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
549 	    : indexCount(indexCount)
550 	    , instanceCount(instanceCount)
551 	    , firstIndex(firstIndex)
552 	    , vertexOffset(vertexOffset)
553 	    , firstInstance(firstInstance)
554 	{
555 	}
556 
execute(vk::CommandBuffer::ExecutionState & executionState)557 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
558 	{
559 		draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
560 	}
561 
description()562 	std::string description() override { return "vkCmdDrawIndexed()"; }
563 
564 private:
565 	const uint32_t indexCount;
566 	const uint32_t instanceCount;
567 	const uint32_t firstIndex;
568 	const int32_t vertexOffset;
569 	const uint32_t firstInstance;
570 };
571 
572 class CmdDrawIndirect : public CmdDrawBase
573 {
574 public:
CmdDrawIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)575 	CmdDrawIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
576 	    : buffer(buffer)
577 	    , offset(offset)
578 	    , drawCount(drawCount)
579 	    , stride(stride)
580 	{
581 	}
582 
execute(vk::CommandBuffer::ExecutionState & executionState)583 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
584 	{
585 		for(auto drawId = 0u; drawId < drawCount; drawId++)
586 		{
587 			auto cmd = reinterpret_cast<VkDrawIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride));
588 			draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
589 		}
590 	}
591 
description()592 	std::string description() override { return "vkCmdDrawIndirect()"; }
593 
594 private:
595 	const vk::Buffer *const buffer;
596 	const VkDeviceSize offset;
597 	const uint32_t drawCount;
598 	const uint32_t stride;
599 };
600 
601 class CmdDrawIndexedIndirect : public CmdDrawBase
602 {
603 public:
CmdDrawIndexedIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)604 	CmdDrawIndexedIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
605 	    : buffer(buffer)
606 	    , offset(offset)
607 	    , drawCount(drawCount)
608 	    , stride(stride)
609 	{
610 	}
611 
execute(vk::CommandBuffer::ExecutionState & executionState)612 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
613 	{
614 		for(auto drawId = 0u; drawId < drawCount; drawId++)
615 		{
616 			auto cmd = reinterpret_cast<VkDrawIndexedIndirectCommand const *>(buffer->getOffsetPointer(offset + drawId * stride));
617 			draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
618 		}
619 	}
620 
description()621 	std::string description() override { return "vkCmdDrawIndexedIndirect()"; }
622 
623 private:
624 	const vk::Buffer *const buffer;
625 	const VkDeviceSize offset;
626 	const uint32_t drawCount;
627 	const uint32_t stride;
628 };
629 
630 class CmdCopyImage : public vk::CommandBuffer::Command
631 {
632 public:
CmdCopyImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageCopy2KHR & region)633 	CmdCopyImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageCopy2KHR &region)
634 	    : srcImage(srcImage)
635 	    , dstImage(dstImage)
636 	    , region(region)
637 	{
638 	}
639 
execute(vk::CommandBuffer::ExecutionState & executionState)640 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
641 	{
642 		srcImage->copyTo(dstImage, region);
643 	}
644 
description()645 	std::string description() override { return "vkCmdCopyImage()"; }
646 
647 private:
648 	const vk::Image *const srcImage;
649 	vk::Image *const dstImage;
650 	const VkImageCopy2KHR region;
651 };
652 
653 class CmdCopyBuffer : public vk::CommandBuffer::Command
654 {
655 public:
CmdCopyBuffer(const vk::Buffer * srcBuffer,vk::Buffer * dstBuffer,const VkBufferCopy2KHR & region)656 	CmdCopyBuffer(const vk::Buffer *srcBuffer, vk::Buffer *dstBuffer, const VkBufferCopy2KHR &region)
657 	    : srcBuffer(srcBuffer)
658 	    , dstBuffer(dstBuffer)
659 	    , region(region)
660 	{
661 	}
662 
execute(vk::CommandBuffer::ExecutionState & executionState)663 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
664 	{
665 		srcBuffer->copyTo(dstBuffer, region);
666 	}
667 
description()668 	std::string description() override { return "vkCmdCopyBuffer()"; }
669 
670 private:
671 	const vk::Buffer *const srcBuffer;
672 	vk::Buffer *const dstBuffer;
673 	const VkBufferCopy2KHR region;
674 };
675 
676 class CmdCopyImageToBuffer : public vk::CommandBuffer::Command
677 {
678 public:
CmdCopyImageToBuffer(vk::Image * srcImage,vk::Buffer * dstBuffer,const VkBufferImageCopy2KHR & region)679 	CmdCopyImageToBuffer(vk::Image *srcImage, vk::Buffer *dstBuffer, const VkBufferImageCopy2KHR &region)
680 	    : srcImage(srcImage)
681 	    , dstBuffer(dstBuffer)
682 	    , region(region)
683 	{
684 	}
685 
execute(vk::CommandBuffer::ExecutionState & executionState)686 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
687 	{
688 		srcImage->copyTo(dstBuffer, region);
689 	}
690 
description()691 	std::string description() override { return "vkCmdCopyImageToBuffer()"; }
692 
693 private:
694 	vk::Image *const srcImage;
695 	vk::Buffer *const dstBuffer;
696 	const VkBufferImageCopy2KHR region;
697 };
698 
699 class CmdCopyBufferToImage : public vk::CommandBuffer::Command
700 {
701 public:
CmdCopyBufferToImage(vk::Buffer * srcBuffer,vk::Image * dstImage,const VkBufferImageCopy2KHR & region)702 	CmdCopyBufferToImage(vk::Buffer *srcBuffer, vk::Image *dstImage, const VkBufferImageCopy2KHR &region)
703 	    : srcBuffer(srcBuffer)
704 	    , dstImage(dstImage)
705 	    , region(region)
706 	{
707 	}
708 
execute(vk::CommandBuffer::ExecutionState & executionState)709 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
710 	{
711 		dstImage->copyFrom(srcBuffer, region);
712 	}
713 
description()714 	std::string description() override { return "vkCmdCopyBufferToImage()"; }
715 
716 private:
717 	vk::Buffer *const srcBuffer;
718 	vk::Image *const dstImage;
719 	const VkBufferImageCopy2KHR region;
720 };
721 
722 class CmdFillBuffer : public vk::CommandBuffer::Command
723 {
724 public:
CmdFillBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)725 	CmdFillBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
726 	    : dstBuffer(dstBuffer)
727 	    , dstOffset(dstOffset)
728 	    , size(size)
729 	    , data(data)
730 	{
731 	}
732 
execute(vk::CommandBuffer::ExecutionState & executionState)733 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
734 	{
735 		dstBuffer->fill(dstOffset, size, data);
736 	}
737 
description()738 	std::string description() override { return "vkCmdFillBuffer()"; }
739 
740 private:
741 	vk::Buffer *const dstBuffer;
742 	const VkDeviceSize dstOffset;
743 	const VkDeviceSize size;
744 	const uint32_t data;
745 };
746 
747 class CmdUpdateBuffer : public vk::CommandBuffer::Command
748 {
749 public:
CmdUpdateBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const uint8_t * pData)750 	CmdUpdateBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint8_t *pData)
751 	    : dstBuffer(dstBuffer)
752 	    , dstOffset(dstOffset)
753 	    , data(pData, &pData[dataSize])
754 	{
755 	}
756 
execute(vk::CommandBuffer::ExecutionState & executionState)757 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
758 	{
759 		dstBuffer->update(dstOffset, data.size(), data.data());
760 	}
761 
description()762 	std::string description() override { return "vkCmdUpdateBuffer()"; }
763 
764 private:
765 	vk::Buffer *const dstBuffer;
766 	const VkDeviceSize dstOffset;
767 	const std::vector<uint8_t> data;  // FIXME(b/119409619): replace this vector by an allocator so we can control all memory allocations
768 };
769 
770 class CmdClearColorImage : public vk::CommandBuffer::Command
771 {
772 public:
CmdClearColorImage(vk::Image * image,const VkClearColorValue & color,const VkImageSubresourceRange & range)773 	CmdClearColorImage(vk::Image *image, const VkClearColorValue &color, const VkImageSubresourceRange &range)
774 	    : image(image)
775 	    , color(color)
776 	    , range(range)
777 	{
778 	}
779 
execute(vk::CommandBuffer::ExecutionState & executionState)780 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
781 	{
782 		image->clear(color, range);
783 	}
784 
description()785 	std::string description() override { return "vkCmdClearColorImage()"; }
786 
787 private:
788 	vk::Image *const image;
789 	const VkClearColorValue color;
790 	const VkImageSubresourceRange range;
791 };
792 
793 class CmdClearDepthStencilImage : public vk::CommandBuffer::Command
794 {
795 public:
CmdClearDepthStencilImage(vk::Image * image,const VkClearDepthStencilValue & depthStencil,const VkImageSubresourceRange & range)796 	CmdClearDepthStencilImage(vk::Image *image, const VkClearDepthStencilValue &depthStencil, const VkImageSubresourceRange &range)
797 	    : image(image)
798 	    , depthStencil(depthStencil)
799 	    , range(range)
800 	{
801 	}
802 
execute(vk::CommandBuffer::ExecutionState & executionState)803 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
804 	{
805 		image->clear(depthStencil, range);
806 	}
807 
description()808 	std::string description() override { return "vkCmdClearDepthStencilImage()"; }
809 
810 private:
811 	vk::Image *const image;
812 	const VkClearDepthStencilValue depthStencil;
813 	const VkImageSubresourceRange range;
814 };
815 
816 class CmdClearAttachment : public vk::CommandBuffer::Command
817 {
818 public:
CmdClearAttachment(const VkClearAttachment & attachment,const VkClearRect & rect)819 	CmdClearAttachment(const VkClearAttachment &attachment, const VkClearRect &rect)
820 	    : attachment(attachment)
821 	    , rect(rect)
822 	{
823 	}
824 
execute(vk::CommandBuffer::ExecutionState & executionState)825 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
826 	{
827 		// attachment clears are drawing operations, and so have rasterization-order guarantees.
828 		// however, we don't do the clear through the rasterizer, so need to ensure prior drawing
829 		// has completed first.
830 		executionState.renderer->synchronize();
831 		executionState.renderPassFramebuffer->clearAttachment(executionState.renderPass, executionState.subpassIndex, attachment, rect);
832 	}
833 
description()834 	std::string description() override { return "vkCmdClearAttachment()"; }
835 
836 private:
837 	const VkClearAttachment attachment;
838 	const VkClearRect rect;
839 };
840 
841 class CmdBlitImage : public vk::CommandBuffer::Command
842 {
843 public:
CmdBlitImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageBlit2KHR & region,VkFilter filter)844 	CmdBlitImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageBlit2KHR &region, VkFilter filter)
845 	    : srcImage(srcImage)
846 	    , dstImage(dstImage)
847 	    , region(region)
848 	    , filter(filter)
849 	{
850 	}
851 
execute(vk::CommandBuffer::ExecutionState & executionState)852 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
853 	{
854 		srcImage->blitTo(dstImage, region, filter);
855 	}
856 
description()857 	std::string description() override { return "vkCmdBlitImage()"; }
858 
859 private:
860 	const vk::Image *const srcImage;
861 	vk::Image *const dstImage;
862 	const VkImageBlit2KHR region;
863 	const VkFilter filter;
864 };
865 
866 class CmdResolveImage : public vk::CommandBuffer::Command
867 {
868 public:
CmdResolveImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageResolve2KHR & region)869 	CmdResolveImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageResolve2KHR &region)
870 	    : srcImage(srcImage)
871 	    , dstImage(dstImage)
872 	    , region(region)
873 	{
874 	}
875 
execute(vk::CommandBuffer::ExecutionState & executionState)876 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
877 	{
878 		srcImage->resolveTo(dstImage, region);
879 	}
880 
description()881 	std::string description() override { return "vkCmdBlitImage()"; }
882 
883 private:
884 	const vk::Image *const srcImage;
885 	vk::Image *const dstImage;
886 	const VkImageResolve2KHR region;
887 };
888 
889 class CmdPipelineBarrier : public vk::CommandBuffer::Command
890 {
891 public:
execute(vk::CommandBuffer::ExecutionState & executionState)892 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
893 	{
894 		// This is a very simple implementation that simply calls sw::Renderer::synchronize(),
895 		// since the driver is free to move the source stage towards the bottom of the pipe
896 		// and the target stage towards the top, so a full pipeline sync is spec compliant.
897 		executionState.renderer->synchronize();
898 
899 		// Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
900 
901 		// Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
902 	}
903 
description()904 	std::string description() override { return "vkCmdPipelineBarrier()"; }
905 };
906 
907 class CmdSignalEvent : public vk::CommandBuffer::Command
908 {
909 public:
CmdSignalEvent(vk::Event * ev,VkPipelineStageFlags stageMask)910 	CmdSignalEvent(vk::Event *ev, VkPipelineStageFlags stageMask)
911 	    : ev(ev)
912 	    , stageMask(stageMask)
913 	{
914 	}
915 
execute(vk::CommandBuffer::ExecutionState & executionState)916 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
917 	{
918 		executionState.renderer->synchronize();
919 		ev->signal();
920 	}
921 
description()922 	std::string description() override { return "vkCmdSignalEvent()"; }
923 
924 private:
925 	vk::Event *const ev;
926 	const VkPipelineStageFlags stageMask;  // TODO(b/117835459): We currently ignore the flags and signal the event at the last stage
927 };
928 
929 class CmdResetEvent : public vk::CommandBuffer::Command
930 {
931 public:
CmdResetEvent(vk::Event * ev,VkPipelineStageFlags stageMask)932 	CmdResetEvent(vk::Event *ev, VkPipelineStageFlags stageMask)
933 	    : ev(ev)
934 	    , stageMask(stageMask)
935 	{
936 	}
937 
execute(vk::CommandBuffer::ExecutionState & executionState)938 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
939 	{
940 		ev->reset();
941 	}
942 
description()943 	std::string description() override { return "vkCmdResetEvent()"; }
944 
945 private:
946 	vk::Event *const ev;
947 	const VkPipelineStageFlags stageMask;  // FIXME(b/117835459): We currently ignore the flags and reset the event at the last stage
948 };
949 
950 class CmdWaitEvent : public vk::CommandBuffer::Command
951 {
952 public:
CmdWaitEvent(vk::Event * ev)953 	CmdWaitEvent(vk::Event *ev)
954 	    : ev(ev)
955 	{
956 	}
957 
execute(vk::CommandBuffer::ExecutionState & executionState)958 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
959 	{
960 		executionState.renderer->synchronize();
961 		ev->wait();
962 	}
963 
description()964 	std::string description() override { return "vkCmdWaitEvent()"; }
965 
966 private:
967 	vk::Event *const ev;
968 };
969 
970 class CmdBindDescriptorSets : public vk::CommandBuffer::Command
971 {
972 public:
CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t firstDynamicOffset,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)973 	CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
974 	                      uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
975 	                      uint32_t firstDynamicOffset, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
976 	    : pipelineBindPoint(pipelineBindPoint)
977 	    , firstSet(firstSet)
978 	    , descriptorSetCount(descriptorSetCount)
979 	    , firstDynamicOffset(firstDynamicOffset)
980 	    , dynamicOffsetCount(dynamicOffsetCount)
981 	{
982 		for(uint32_t i = 0; i < descriptorSetCount; i++)
983 		{
984 			// We need both a descriptor set object for updates and a descriptor set data pointer for routines
985 			descriptorSetObjects[firstSet + i] = vk::Cast(pDescriptorSets[i]);
986 			descriptorSets[firstSet + i] = vk::Cast(pDescriptorSets[i])->data;
987 		}
988 
989 		for(uint32_t i = 0; i < dynamicOffsetCount; i++)
990 		{
991 			dynamicOffsets[firstDynamicOffset + i] = pDynamicOffsets[i];
992 		}
993 	}
994 
execute(vk::CommandBuffer::ExecutionState & executionState)995 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
996 	{
997 		ASSERT((size_t)pipelineBindPoint < executionState.pipelineState.size());
998 		ASSERT(firstSet + descriptorSetCount <= vk::MAX_BOUND_DESCRIPTOR_SETS);
999 		ASSERT(firstDynamicOffset + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
1000 
1001 		auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
1002 
1003 		for(uint32_t i = firstSet; i < firstSet + descriptorSetCount; i++)
1004 		{
1005 			pipelineState.descriptorSetObjects[i] = descriptorSetObjects[i];
1006 			pipelineState.descriptorSets[i] = descriptorSets[i];
1007 		}
1008 
1009 		for(uint32_t i = firstDynamicOffset; i < firstDynamicOffset + dynamicOffsetCount; i++)
1010 		{
1011 			pipelineState.descriptorDynamicOffsets[i] = dynamicOffsets[i];
1012 		}
1013 	}
1014 
description()1015 	std::string description() override { return "vkCmdBindDescriptorSets()"; }
1016 
1017 private:
1018 	const VkPipelineBindPoint pipelineBindPoint;
1019 	const uint32_t firstSet;
1020 	const uint32_t descriptorSetCount;
1021 	const uint32_t firstDynamicOffset;
1022 	const uint32_t dynamicOffsetCount;
1023 
1024 	vk::DescriptorSet::Array descriptorSetObjects;
1025 	vk::DescriptorSet::Bindings descriptorSets;
1026 	vk::DescriptorSet::DynamicOffsets dynamicOffsets;
1027 };
1028 
1029 class CmdSetPushConstants : public vk::CommandBuffer::Command
1030 {
1031 public:
CmdSetPushConstants(uint32_t offset,uint32_t size,void const * pValues)1032 	CmdSetPushConstants(uint32_t offset, uint32_t size, void const *pValues)
1033 	    : offset(offset)
1034 	    , size(size)
1035 	{
1036 		ASSERT(offset < vk::MAX_PUSH_CONSTANT_SIZE);
1037 		ASSERT(offset + size <= vk::MAX_PUSH_CONSTANT_SIZE);
1038 
1039 		memcpy(data, pValues, size);
1040 	}
1041 
execute(vk::CommandBuffer::ExecutionState & executionState)1042 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1043 	{
1044 		memcpy(&executionState.pushConstants.data[offset], data, size);
1045 	}
1046 
description()1047 	std::string description() override { return "vkCmdSetPushConstants()"; }
1048 
1049 private:
1050 	const uint32_t offset;
1051 	const uint32_t size;
1052 	unsigned char data[vk::MAX_PUSH_CONSTANT_SIZE];
1053 };
1054 
1055 class CmdBeginQuery : public vk::CommandBuffer::Command
1056 {
1057 public:
CmdBeginQuery(vk::QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1058 	CmdBeginQuery(vk::QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1059 	    : queryPool(queryPool)
1060 	    , query(query)
1061 	    , flags(flags)
1062 	{
1063 	}
1064 
execute(vk::CommandBuffer::ExecutionState & executionState)1065 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1066 	{
1067 		// "If queries are used while executing a render pass instance that has multiview enabled, the query uses
1068 		//  N consecutive query indices in the query pool (starting at `query`)"
1069 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1070 		{
1071 			queryPool->begin(query + i, flags);
1072 		}
1073 
1074 		// The renderer accumulates the result into a single query.
1075 		ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1076 		executionState.renderer->addQuery(queryPool->getQuery(query));
1077 	}
1078 
description()1079 	std::string description() override { return "vkCmdBeginQuery()"; }
1080 
1081 private:
1082 	vk::QueryPool *const queryPool;
1083 	const uint32_t query;
1084 	const VkQueryControlFlags flags;
1085 };
1086 
1087 class CmdEndQuery : public vk::CommandBuffer::Command
1088 {
1089 public:
CmdEndQuery(vk::QueryPool * queryPool,uint32_t query)1090 	CmdEndQuery(vk::QueryPool *queryPool, uint32_t query)
1091 	    : queryPool(queryPool)
1092 	    , query(query)
1093 	{
1094 	}
1095 
execute(vk::CommandBuffer::ExecutionState & executionState)1096 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1097 	{
1098 		// The renderer accumulates the result into a single query.
1099 		ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1100 		executionState.renderer->removeQuery(queryPool->getQuery(query));
1101 
1102 		// "implementations may write the total result to the first query and write zero to the other queries."
1103 		for(uint32_t i = 1; i < executionState.viewCount(); i++)
1104 		{
1105 			queryPool->getQuery(query + i)->set(0);
1106 		}
1107 
1108 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1109 		{
1110 			queryPool->end(query + i);
1111 		}
1112 	}
1113 
description()1114 	std::string description() override { return "vkCmdEndQuery()"; }
1115 
1116 private:
1117 	vk::QueryPool *const queryPool;
1118 	const uint32_t query;
1119 };
1120 
1121 class CmdResetQueryPool : public vk::CommandBuffer::Command
1122 {
1123 public:
CmdResetQueryPool(vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1124 	CmdResetQueryPool(vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1125 	    : queryPool(queryPool)
1126 	    , firstQuery(firstQuery)
1127 	    , queryCount(queryCount)
1128 	{
1129 	}
1130 
execute(vk::CommandBuffer::ExecutionState & executionState)1131 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1132 	{
1133 		queryPool->reset(firstQuery, queryCount);
1134 	}
1135 
description()1136 	std::string description() override { return "vkCmdResetQueryPool()"; }
1137 
1138 private:
1139 	vk::QueryPool *const queryPool;
1140 	const uint32_t firstQuery;
1141 	const uint32_t queryCount;
1142 };
1143 
1144 class CmdWriteTimeStamp : public vk::CommandBuffer::Command
1145 {
1146 public:
CmdWriteTimeStamp(vk::QueryPool * queryPool,uint32_t query,VkPipelineStageFlagBits stage)1147 	CmdWriteTimeStamp(vk::QueryPool *queryPool, uint32_t query, VkPipelineStageFlagBits stage)
1148 	    : queryPool(queryPool)
1149 	    , query(query)
1150 	    , stage(stage)
1151 	{
1152 	}
1153 
execute(vk::CommandBuffer::ExecutionState & executionState)1154 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1155 	{
1156 		if(stage & ~(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT))
1157 		{
1158 			// The `top of pipe` and `draw indirect` stages are handled in command buffer processing so a timestamp write
1159 			// done in those stages can just be done here without any additional synchronization.
1160 			// Everything else is deferred to the Renderer; we will treat those stages all as if they were
1161 			// `bottom of pipe`.
1162 			//
1163 			// FIXME(chrisforbes): once Marl is integrated, do this in a task so we don't have to stall here.
1164 			executionState.renderer->synchronize();
1165 		}
1166 
1167 		// "the timestamp uses N consecutive query indices in the query pool (starting at `query`) where
1168 		//  N is the number of bits set in the view mask of the subpass the command is executed in."
1169 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1170 		{
1171 			queryPool->writeTimestamp(query + i);
1172 		}
1173 	}
1174 
description()1175 	std::string description() override { return "vkCmdWriteTimeStamp()"; }
1176 
1177 private:
1178 	vk::QueryPool *const queryPool;
1179 	const uint32_t query;
1180 	const VkPipelineStageFlagBits stage;
1181 };
1182 
1183 class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command
1184 {
1185 public:
CmdCopyQueryPoolResults(const vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1186 	CmdCopyQueryPoolResults(const vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1187 	                        vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1188 	    : queryPool(queryPool)
1189 	    , firstQuery(firstQuery)
1190 	    , queryCount(queryCount)
1191 	    , dstBuffer(dstBuffer)
1192 	    , dstOffset(dstOffset)
1193 	    , stride(stride)
1194 	    , flags(flags)
1195 	{
1196 	}
1197 
execute(vk::CommandBuffer::ExecutionState & executionState)1198 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1199 	{
1200 		queryPool->getResults(firstQuery, queryCount, dstBuffer->getSize() - dstOffset,
1201 		                      dstBuffer->getOffsetPointer(dstOffset), stride, flags);
1202 	}
1203 
description()1204 	std::string description() override { return "vkCmdCopyQueryPoolResults()"; }
1205 
1206 private:
1207 	const vk::QueryPool *const queryPool;
1208 	const uint32_t firstQuery;
1209 	const uint32_t queryCount;
1210 	vk::Buffer *const dstBuffer;
1211 	const VkDeviceSize dstOffset;
1212 	const VkDeviceSize stride;
1213 	const VkQueryResultFlags flags;
1214 };
1215 
1216 }  // anonymous namespace
1217 
1218 namespace vk {
1219 
CommandBuffer(Device * device,VkCommandBufferLevel pLevel)1220 CommandBuffer::CommandBuffer(Device *device, VkCommandBufferLevel pLevel)
1221     : device(device)
1222     , level(pLevel)
1223 {
1224 }
1225 
destroy(const VkAllocationCallbacks * pAllocator)1226 void CommandBuffer::destroy(const VkAllocationCallbacks *pAllocator)
1227 {
1228 }
1229 
resetState()1230 void CommandBuffer::resetState()
1231 {
1232 	// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
1233 	commands.clear();
1234 
1235 	state = INITIAL;
1236 }
1237 
begin(VkCommandBufferUsageFlags flags,const VkCommandBufferInheritanceInfo * pInheritanceInfo)1238 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo *pInheritanceInfo)
1239 {
1240 	ASSERT((state != RECORDING) && (state != PENDING));
1241 
1242 	// Nothing interesting to do based on flags. We don't have any optimizations
1243 	// to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
1244 	// must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
1245 	(void)flags;
1246 
1247 	// pInheritanceInfo merely contains optimization hints, so we currently ignore it
1248 
1249 	// "pInheritanceInfo is a pointer to a VkCommandBufferInheritanceInfo structure, used if commandBuffer is a
1250 	//  secondary command buffer. If this is a primary command buffer, then this value is ignored."
1251 	if(level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
1252 	{
1253 		if(pInheritanceInfo->queryFlags != 0)
1254 		{
1255 			// "If the inherited queries feature is not enabled, queryFlags must be 0"
1256 			UNSUPPORTED("VkPhysicalDeviceFeatures::inheritedQueries");
1257 		}
1258 	}
1259 
1260 	if(state != INITIAL)
1261 	{
1262 		// Implicit reset
1263 		resetState();
1264 	}
1265 
1266 	state = RECORDING;
1267 
1268 	return VK_SUCCESS;
1269 }
1270 
end()1271 VkResult CommandBuffer::end()
1272 {
1273 	ASSERT(state == RECORDING);
1274 
1275 	state = EXECUTABLE;
1276 
1277 #ifdef ENABLE_VK_DEBUGGER
1278 	auto debuggerContext = device->getDebuggerContext();
1279 	if(debuggerContext)
1280 	{
1281 		std::string source;
1282 		for(auto &command : commands)
1283 		{
1284 			source += command->description() + "\n";
1285 		}
1286 		debuggerFile = debuggerContext->lock().createVirtualFile("VkCommandBuffer", source.c_str());
1287 	}
1288 #endif  // ENABLE_VK_DEBUGGER
1289 
1290 	return VK_SUCCESS;
1291 }
1292 
reset(VkCommandPoolResetFlags flags)1293 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
1294 {
1295 	ASSERT(state != PENDING);
1296 
1297 	resetState();
1298 
1299 	return VK_SUCCESS;
1300 }
1301 
1302 template<typename T, typename... Args>
addCommand(Args &&...args)1303 void CommandBuffer::addCommand(Args &&... args)
1304 {
1305 	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
1306 	commands.push_back(std::make_unique<T>(std::forward<Args>(args)...));
1307 }
1308 
beginRenderPass(RenderPass * renderPass,Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * clearValues,VkSubpassContents contents,const VkRenderPassAttachmentBeginInfo * attachmentInfo)1309 void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
1310                                     uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents,
1311                                     const VkRenderPassAttachmentBeginInfo *attachmentInfo)
1312 {
1313 	ASSERT(state == RECORDING);
1314 
1315 	if(attachmentInfo)
1316 	{
1317 		for(uint32_t i = 0; i < attachmentInfo->attachmentCount; i++)
1318 		{
1319 			framebuffer->setAttachment(vk::Cast(attachmentInfo->pAttachments[i]), i);
1320 		}
1321 	}
1322 	addCommand<::CmdBeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
1323 }
1324 
nextSubpass(VkSubpassContents contents)1325 void CommandBuffer::nextSubpass(VkSubpassContents contents)
1326 {
1327 	ASSERT(state == RECORDING);
1328 
1329 	addCommand<::CmdNextSubpass>();
1330 }
1331 
endRenderPass()1332 void CommandBuffer::endRenderPass()
1333 {
1334 	addCommand<::CmdEndRenderPass>();
1335 }
1336 
executeCommands(uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)1337 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
1338 {
1339 	ASSERT(state == RECORDING);
1340 
1341 	for(uint32_t i = 0; i < commandBufferCount; ++i)
1342 	{
1343 		addCommand<::CmdExecuteCommands>(vk::Cast(pCommandBuffers[i]));
1344 	}
1345 }
1346 
setDeviceMask(uint32_t deviceMask)1347 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
1348 {
1349 	// SwiftShader only has one device, so we ignore the device mask
1350 }
1351 
dispatchBase(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1352 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
1353                                  uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1354 {
1355 	addCommand<::CmdDispatch>(baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
1356 }
1357 
pipelineBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkDependencyFlags dependencyFlags,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)1358 void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1359                                     VkDependencyFlags dependencyFlags,
1360                                     uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1361                                     uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1362                                     uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers)
1363 {
1364 	addCommand<::CmdPipelineBarrier>();
1365 }
1366 
bindPipeline(VkPipelineBindPoint pipelineBindPoint,Pipeline * pipeline)1367 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline *pipeline)
1368 {
1369 	switch(pipelineBindPoint)
1370 	{
1371 	case VK_PIPELINE_BIND_POINT_COMPUTE:
1372 	case VK_PIPELINE_BIND_POINT_GRAPHICS:
1373 		addCommand<::CmdPipelineBind>(pipelineBindPoint, pipeline);
1374 		break;
1375 	default:
1376 		UNSUPPORTED("VkPipelineBindPoint %d", int(pipelineBindPoint));
1377 	}
1378 }
1379 
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets)1380 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
1381                                       const VkBuffer *pBuffers, const VkDeviceSize *pOffsets)
1382 {
1383 	for(uint32_t i = 0; i < bindingCount; ++i)
1384 	{
1385 		addCommand<::CmdVertexBufferBind>(i + firstBinding, vk::Cast(pBuffers[i]), pOffsets[i]);
1386 	}
1387 }
1388 
beginQuery(QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1389 void CommandBuffer::beginQuery(QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1390 {
1391 	addCommand<::CmdBeginQuery>(queryPool, query, flags);
1392 }
1393 
endQuery(QueryPool * queryPool,uint32_t query)1394 void CommandBuffer::endQuery(QueryPool *queryPool, uint32_t query)
1395 {
1396 	addCommand<::CmdEndQuery>(queryPool, query);
1397 }
1398 
resetQueryPool(QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1399 void CommandBuffer::resetQueryPool(QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1400 {
1401 	addCommand<::CmdResetQueryPool>(queryPool, firstQuery, queryCount);
1402 }
1403 
writeTimestamp(VkPipelineStageFlagBits pipelineStage,QueryPool * queryPool,uint32_t query)1404 void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage, QueryPool *queryPool, uint32_t query)
1405 {
1406 	addCommand<::CmdWriteTimeStamp>(queryPool, query, pipelineStage);
1407 }
1408 
copyQueryPoolResults(const QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1409 void CommandBuffer::copyQueryPoolResults(const QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1410                                          Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1411 {
1412 	addCommand<::CmdCopyQueryPoolResults>(queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
1413 }
1414 
pushConstants(PipelineLayout * layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)1415 void CommandBuffer::pushConstants(PipelineLayout *layout, VkShaderStageFlags stageFlags,
1416                                   uint32_t offset, uint32_t size, const void *pValues)
1417 {
1418 	addCommand<::CmdSetPushConstants>(offset, size, pValues);
1419 }
1420 
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)1421 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports)
1422 {
1423 	if(firstViewport != 0 || viewportCount > 1)
1424 	{
1425 		UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1426 	}
1427 
1428 	for(uint32_t i = 0; i < viewportCount; i++)
1429 	{
1430 		addCommand<::CmdSetViewport>(pViewports[i], i + firstViewport);
1431 	}
1432 }
1433 
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)1434 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors)
1435 {
1436 	if(firstScissor != 0 || scissorCount > 1)
1437 	{
1438 		UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1439 	}
1440 
1441 	for(uint32_t i = 0; i < scissorCount; i++)
1442 	{
1443 		addCommand<::CmdSetScissor>(pScissors[i], i + firstScissor);
1444 	}
1445 }
1446 
setLineWidth(float lineWidth)1447 void CommandBuffer::setLineWidth(float lineWidth)
1448 {
1449 	// If the wide lines feature is not enabled, lineWidth must be 1.0
1450 	ASSERT(lineWidth == 1.0f);
1451 }
1452 
setDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)1453 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
1454 {
1455 	addCommand<::CmdSetDepthBias>(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1456 }
1457 
setBlendConstants(const float blendConstants[4])1458 void CommandBuffer::setBlendConstants(const float blendConstants[4])
1459 {
1460 	addCommand<::CmdSetBlendConstants>(blendConstants);
1461 }
1462 
setDepthBounds(float minDepthBounds,float maxDepthBounds)1463 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
1464 {
1465 	addCommand<::CmdSetDepthBounds>(minDepthBounds, maxDepthBounds);
1466 }
1467 
setStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)1468 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
1469 {
1470 	// faceMask must not be 0
1471 	ASSERT(faceMask != 0);
1472 
1473 	addCommand<::CmdSetStencilCompareMask>(faceMask, compareMask);
1474 }
1475 
setStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)1476 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
1477 {
1478 	// faceMask must not be 0
1479 	ASSERT(faceMask != 0);
1480 
1481 	addCommand<::CmdSetStencilWriteMask>(faceMask, writeMask);
1482 }
1483 
setStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)1484 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
1485 {
1486 	// faceMask must not be 0
1487 	ASSERT(faceMask != 0);
1488 
1489 	addCommand<::CmdSetStencilReference>(faceMask, reference);
1490 }
1491 
bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,const PipelineLayout * pipelineLayout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)1492 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout *pipelineLayout,
1493                                        uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
1494                                        uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
1495 {
1496 	ASSERT(state == RECORDING);
1497 
1498 	auto firstDynamicOffset = (dynamicOffsetCount != 0) ? pipelineLayout->getDynamicOffsetIndex(firstSet, 0) : 0;
1499 
1500 	addCommand<::CmdBindDescriptorSets>(
1501 	    pipelineBindPoint, firstSet, descriptorSetCount, pDescriptorSets,
1502 	    firstDynamicOffset, dynamicOffsetCount, pDynamicOffsets);
1503 }
1504 
bindIndexBuffer(Buffer * buffer,VkDeviceSize offset,VkIndexType indexType)1505 void CommandBuffer::bindIndexBuffer(Buffer *buffer, VkDeviceSize offset, VkIndexType indexType)
1506 {
1507 	addCommand<::CmdIndexBufferBind>(buffer, offset, indexType);
1508 }
1509 
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1510 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1511 {
1512 	addCommand<::CmdDispatch>(0, 0, 0, groupCountX, groupCountY, groupCountZ);
1513 }
1514 
dispatchIndirect(Buffer * buffer,VkDeviceSize offset)1515 void CommandBuffer::dispatchIndirect(Buffer *buffer, VkDeviceSize offset)
1516 {
1517 	addCommand<::CmdDispatchIndirect>(buffer, offset);
1518 }
1519 
copyBuffer(const VkCopyBufferInfo2KHR & copyBufferInfo)1520 void CommandBuffer::copyBuffer(const VkCopyBufferInfo2KHR &copyBufferInfo)
1521 {
1522 	ASSERT(state == RECORDING);
1523 
1524 	for(uint32_t i = 0; i < copyBufferInfo.regionCount; i++)
1525 	{
1526 		addCommand<::CmdCopyBuffer>(
1527 		    vk::Cast(copyBufferInfo.srcBuffer),
1528 		    vk::Cast(copyBufferInfo.dstBuffer),
1529 		    copyBufferInfo.pRegions[i]);
1530 	}
1531 }
1532 
copyImage(const VkCopyImageInfo2KHR & copyImageInfo)1533 void CommandBuffer::copyImage(const VkCopyImageInfo2KHR &copyImageInfo)
1534 {
1535 	ASSERT(state == RECORDING);
1536 	ASSERT(copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1537 	       copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1538 	ASSERT(copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1539 	       copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1540 
1541 	for(uint32_t i = 0; i < copyImageInfo.regionCount; i++)
1542 	{
1543 		addCommand<::CmdCopyImage>(
1544 		    vk::Cast(copyImageInfo.srcImage),
1545 		    vk::Cast(copyImageInfo.dstImage),
1546 		    copyImageInfo.pRegions[i]);
1547 	}
1548 }
1549 
blitImage(const VkBlitImageInfo2KHR & blitImageInfo)1550 void CommandBuffer::blitImage(const VkBlitImageInfo2KHR &blitImageInfo)
1551 {
1552 	ASSERT(state == RECORDING);
1553 	ASSERT(blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1554 	       blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1555 	ASSERT(blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1556 	       blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1557 
1558 	for(uint32_t i = 0; i < blitImageInfo.regionCount; i++)
1559 	{
1560 		addCommand<::CmdBlitImage>(
1561 		    vk::Cast(blitImageInfo.srcImage),
1562 		    vk::Cast(blitImageInfo.dstImage),
1563 		    blitImageInfo.pRegions[i],
1564 		    blitImageInfo.filter);
1565 	}
1566 }
1567 
copyBufferToImage(const VkCopyBufferToImageInfo2KHR & copyBufferToImageInfo)1568 void CommandBuffer::copyBufferToImage(const VkCopyBufferToImageInfo2KHR &copyBufferToImageInfo)
1569 {
1570 	ASSERT(state == RECORDING);
1571 
1572 	for(uint32_t i = 0; i < copyBufferToImageInfo.regionCount; i++)
1573 	{
1574 		addCommand<::CmdCopyBufferToImage>(
1575 		    vk::Cast(copyBufferToImageInfo.srcBuffer),
1576 		    vk::Cast(copyBufferToImageInfo.dstImage),
1577 		    copyBufferToImageInfo.pRegions[i]);
1578 	}
1579 }
1580 
copyImageToBuffer(const VkCopyImageToBufferInfo2KHR & copyImageToBufferInfo)1581 void CommandBuffer::copyImageToBuffer(const VkCopyImageToBufferInfo2KHR &copyImageToBufferInfo)
1582 {
1583 	ASSERT(state == RECORDING);
1584 	ASSERT(copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1585 	       copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1586 
1587 	for(uint32_t i = 0; i < copyImageToBufferInfo.regionCount; i++)
1588 	{
1589 		addCommand<::CmdCopyImageToBuffer>(
1590 		    vk::Cast(copyImageToBufferInfo.srcImage),
1591 		    vk::Cast(copyImageToBufferInfo.dstBuffer),
1592 		    copyImageToBufferInfo.pRegions[i]);
1593 	}
1594 }
1595 
updateBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)1596 void CommandBuffer::updateBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData)
1597 {
1598 	ASSERT(state == RECORDING);
1599 
1600 	addCommand<::CmdUpdateBuffer>(dstBuffer, dstOffset, dataSize, reinterpret_cast<const uint8_t *>(pData));
1601 }
1602 
fillBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1603 void CommandBuffer::fillBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1604 {
1605 	ASSERT(state == RECORDING);
1606 
1607 	addCommand<::CmdFillBuffer>(dstBuffer, dstOffset, size, data);
1608 }
1609 
clearColorImage(Image * image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)1610 void CommandBuffer::clearColorImage(Image *image, VkImageLayout imageLayout, const VkClearColorValue *pColor,
1611                                     uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
1612 {
1613 	ASSERT(state == RECORDING);
1614 
1615 	for(uint32_t i = 0; i < rangeCount; i++)
1616 	{
1617 		addCommand<::CmdClearColorImage>(image, *pColor, pRanges[i]);
1618 	}
1619 }
1620 
clearDepthStencilImage(Image * image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)1621 void CommandBuffer::clearDepthStencilImage(Image *image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pDepthStencil,
1622                                            uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
1623 {
1624 	ASSERT(state == RECORDING);
1625 
1626 	for(uint32_t i = 0; i < rangeCount; i++)
1627 	{
1628 		addCommand<::CmdClearDepthStencilImage>(image, *pDepthStencil, pRanges[i]);
1629 	}
1630 }
1631 
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)1632 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment *pAttachments,
1633                                      uint32_t rectCount, const VkClearRect *pRects)
1634 {
1635 	ASSERT(state == RECORDING);
1636 
1637 	for(uint32_t i = 0; i < attachmentCount; i++)
1638 	{
1639 		for(uint32_t j = 0; j < rectCount; j++)
1640 		{
1641 			addCommand<::CmdClearAttachment>(pAttachments[i], pRects[j]);
1642 		}
1643 	}
1644 }
1645 
resolveImage(const VkResolveImageInfo2KHR & resolveImageInfo)1646 void CommandBuffer::resolveImage(const VkResolveImageInfo2KHR &resolveImageInfo)
1647 {
1648 	ASSERT(state == RECORDING);
1649 	ASSERT(resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
1650 	       resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1651 	ASSERT(resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
1652 	       resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
1653 
1654 	for(uint32_t i = 0; i < resolveImageInfo.regionCount; i++)
1655 	{
1656 		addCommand<::CmdResolveImage>(
1657 		    vk::Cast(resolveImageInfo.srcImage),
1658 		    vk::Cast(resolveImageInfo.dstImage),
1659 		    resolveImageInfo.pRegions[i]);
1660 	}
1661 }
1662 
setEvent(Event * event,VkPipelineStageFlags stageMask)1663 void CommandBuffer::setEvent(Event *event, VkPipelineStageFlags stageMask)
1664 {
1665 	ASSERT(state == RECORDING);
1666 
1667 	addCommand<::CmdSignalEvent>(event, stageMask);
1668 }
1669 
resetEvent(Event * event,VkPipelineStageFlags stageMask)1670 void CommandBuffer::resetEvent(Event *event, VkPipelineStageFlags stageMask)
1671 {
1672 	ASSERT(state == RECORDING);
1673 
1674 	addCommand<::CmdResetEvent>(event, stageMask);
1675 }
1676 
waitEvents(uint32_t eventCount,const VkEvent * pEvents,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)1677 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
1678                                VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1679                                uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1680                                uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers)
1681 {
1682 	ASSERT(state == RECORDING);
1683 
1684 	// TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
1685 
1686 	// Note: srcStageMask and dstStageMask are currently ignored
1687 	for(uint32_t i = 0; i < eventCount; i++)
1688 	{
1689 		addCommand<::CmdWaitEvent>(vk::Cast(pEvents[i]));
1690 	}
1691 }
1692 
draw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)1693 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
1694 {
1695 	addCommand<::CmdDraw>(vertexCount, instanceCount, firstVertex, firstInstance);
1696 }
1697 
drawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1698 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1699 {
1700 	addCommand<::CmdDrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1701 }
1702 
drawIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1703 void CommandBuffer::drawIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1704 {
1705 	addCommand<::CmdDrawIndirect>(buffer, offset, drawCount, stride);
1706 }
1707 
drawIndexedIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1708 void CommandBuffer::drawIndexedIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1709 {
1710 	addCommand<::CmdDrawIndexedIndirect>(buffer, offset, drawCount, stride);
1711 }
1712 
beginDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)1713 void CommandBuffer::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
1714 {
1715 	// Optional debug label region
1716 }
1717 
endDebugUtilsLabel()1718 void CommandBuffer::endDebugUtilsLabel()
1719 {
1720 	// Close debug label region opened with beginDebugUtilsLabel()
1721 }
1722 
insertDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)1723 void CommandBuffer::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
1724 {
1725 	// Optional single debug label
1726 }
1727 
submit(CommandBuffer::ExecutionState & executionState)1728 void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
1729 {
1730 	// Perform recorded work
1731 	state = PENDING;
1732 
1733 #ifdef ENABLE_VK_DEBUGGER
1734 	std::shared_ptr<vk::dbg::Thread> debuggerThread;
1735 	auto debuggerContext = device->getDebuggerContext();
1736 	if(debuggerContext)
1737 	{
1738 		debuggerThread = debuggerContext->lock().currentThread();
1739 		debuggerThread->setName("vkQueue processor");
1740 		debuggerThread->enter(debuggerFile, "vkCommandBuffer::submit");
1741 	}
1742 	defer(if(debuggerThread) { debuggerThread->exit(); });
1743 	int line = 1;
1744 #endif  // ENABLE_VK_DEBUGGER
1745 
1746 	for(auto &command : commands)
1747 	{
1748 #ifdef ENABLE_VK_DEBUGGER
1749 		if(debuggerThread)
1750 		{
1751 			debuggerThread->update(true, [&](vk::dbg::Frame &frame) {
1752 				frame.location = { debuggerFile, line++, 0 };
1753 			});
1754 		}
1755 #endif  // ENABLE_VK_DEBUGGER
1756 
1757 		command->execute(executionState);
1758 	}
1759 
1760 	// After work is completed
1761 	state = EXECUTABLE;
1762 }
1763 
submitSecondary(CommandBuffer::ExecutionState & executionState) const1764 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState &executionState) const
1765 {
1766 	for(auto &command : commands)
1767 	{
1768 		command->execute(executionState);
1769 	}
1770 }
1771 
bindAttachments(Attachments * attachments)1772 void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments)
1773 {
1774 	// Binds all the attachments for the current subpass
1775 	// Ideally this would be performed by BeginRenderPass and NextSubpass, but
1776 	// there is too much stomping of the renderer's state by setContext() in
1777 	// draws.
1778 
1779 	auto const &subpass = renderPass->getSubpass(subpassIndex);
1780 
1781 	for(auto i = 0u; i < subpass.colorAttachmentCount; i++)
1782 	{
1783 		auto attachmentReference = subpass.pColorAttachments[i];
1784 		if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
1785 		{
1786 			attachments->colorBuffer[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
1787 		}
1788 	}
1789 
1790 	auto attachmentReference = subpass.pDepthStencilAttachment;
1791 	if(attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
1792 	{
1793 		auto attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
1794 		if(attachment->hasDepthAspect())
1795 		{
1796 			attachments->depthBuffer = attachment;
1797 		}
1798 		if(attachment->hasStencilAspect())
1799 		{
1800 			attachments->stencilBuffer = attachment;
1801 		}
1802 	}
1803 }
1804 
1805 // Returns the number of bits set in the view mask, or 1 if multiview is disabled.
viewCount() const1806 uint32_t CommandBuffer::ExecutionState::viewCount() const
1807 {
1808 	uint32_t viewMask = 1;
1809 
1810 	if(renderPass)
1811 	{
1812 		viewMask = renderPass->getViewMask(subpassIndex);
1813 	}
1814 
1815 	return static_cast<uint32_t>(std::bitset<32>(viewMask).count());
1816 }
1817 
1818 }  // namespace vk
1819