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