• 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,const VkRenderPassAttachmentBeginInfo * attachmentInfo)45 	CmdBeginRenderPass(vk::RenderPass *renderPass, vk::Framebuffer *framebuffer, VkRect2D renderArea,
46 	                   uint32_t clearValueCount, const VkClearValue *pClearValues,
47 	                   const VkRenderPassAttachmentBeginInfo *attachmentInfo)
48 	    : renderPass(renderPass)
49 	    , framebuffer(framebuffer)
50 	    , renderArea(renderArea)
51 	    , clearValueCount(clearValueCount)
52 	    , attachmentCount(attachmentInfo ? attachmentInfo->attachmentCount : 0)
53 	    , attachments(nullptr)
54 	{
55 		// FIXME(b/119409619): use an allocator here so we can control all memory allocations
56 		clearValues = new VkClearValue[clearValueCount];
57 		memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
58 		if(attachmentCount > 0)
59 		{
60 			attachments = new vk::ImageView *[attachmentCount];
61 			for(uint32_t i = 0; i < attachmentCount; i++)
62 			{
63 				attachments[i] = vk::Cast(attachmentInfo->pAttachments[i]);
64 			}
65 		}
66 	}
67 
~CmdBeginRenderPass()68 	~CmdBeginRenderPass() override
69 	{
70 		delete[] clearValues;
71 		delete[] attachments;
72 	}
73 
execute(vk::CommandBuffer::ExecutionState & executionState)74 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
75 	{
76 		executionState.renderPass = renderPass;
77 		executionState.renderPassFramebuffer = framebuffer;
78 		executionState.subpassIndex = 0;
79 
80 		for(uint32_t i = 0; i < attachmentCount; i++)
81 		{
82 			framebuffer->setAttachment(attachments[i], i);
83 		}
84 
85 		// Vulkan specifies that the attachments' `loadOp` gets executed "at the beginning of the subpass where it is first used."
86 		// Since we don't discard any contents between subpasses, this is equivalent to executing it at the start of the renderpass.
87 		framebuffer->executeLoadOp(executionState.renderPass, clearValueCount, clearValues, renderArea);
88 	}
89 
description()90 	std::string description() override { return "vkCmdBeginRenderPass()"; }
91 
92 private:
93 	vk::RenderPass *const renderPass;
94 	vk::Framebuffer *const framebuffer;
95 	const VkRect2D renderArea;
96 	const uint32_t clearValueCount;
97 	VkClearValue *clearValues;
98 	uint32_t attachmentCount;
99 	vk::ImageView **attachments;
100 };
101 
102 class CmdNextSubpass : public vk::CommandBuffer::Command
103 {
104 public:
execute(vk::CommandBuffer::ExecutionState & executionState)105 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
106 	{
107 		bool hasResolveAttachments = (executionState.renderPass->getSubpass(executionState.subpassIndex).pResolveAttachments != nullptr);
108 		if(hasResolveAttachments)
109 		{
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 
117 		executionState.subpassIndex++;
118 	}
119 
description()120 	std::string description() override { return "vkCmdNextSubpass()"; }
121 };
122 
123 class CmdEndRenderPass : public vk::CommandBuffer::Command
124 {
125 public:
execute(vk::CommandBuffer::ExecutionState & executionState)126 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
127 	{
128 		// Execute (implicit or explicit) VkSubpassDependency to VK_SUBPASS_EXTERNAL.
129 		// TODO(b/197691918): Avoid halt-the-world synchronization.
130 		executionState.renderer->synchronize();
131 
132 		// TODO(b/197691917): Eliminate redundant resolve operations.
133 		executionState.renderPassFramebuffer->resolve(executionState.renderPass, executionState.subpassIndex);
134 
135 		executionState.renderPass = nullptr;
136 		executionState.renderPassFramebuffer = nullptr;
137 	}
138 
description()139 	std::string description() override { return "vkCmdEndRenderPass()"; }
140 };
141 
142 class CmdBeginRendering : public vk::CommandBuffer::Command
143 {
144 public:
CmdBeginRendering(const VkRenderingInfo * pRenderingInfo)145 	CmdBeginRendering(const VkRenderingInfo *pRenderingInfo)
146 	    : dynamicRendering(pRenderingInfo)
147 	{
148 	}
149 
execute(vk::CommandBuffer::ExecutionState & executionState)150 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
151 	{
152 		executionState.dynamicRendering = &dynamicRendering;
153 
154 		if(!executionState.dynamicRendering->resume())
155 		{
156 			VkClearRect rect = {};
157 			rect.rect = executionState.dynamicRendering->getRenderArea();
158 			rect.layerCount = executionState.dynamicRendering->getLayerCount();
159 			uint32_t viewMask = executionState.dynamicRendering->getViewMask();
160 
161 			// Vulkan specifies that the attachments' `loadOp` gets executed "at the beginning of the subpass where it is first used."
162 			// Since we don't discard any contents between subpasses, this is equivalent to executing it at the start of the renderpass.
163 			for(uint32_t i = 0; i < dynamicRendering.getColorAttachmentCount(); i++)
164 			{
165 				const VkRenderingAttachmentInfo *colorAttachment = dynamicRendering.getColorAttachment(i);
166 
167 				if(colorAttachment->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
168 				{
169 					vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
170 					if(imageView)
171 					{
172 						imageView->clear(colorAttachment->clearValue, VK_IMAGE_ASPECT_COLOR_BIT, rect, viewMask);
173 					}
174 				}
175 			}
176 
177 			const VkRenderingAttachmentInfo &stencilAttachment = dynamicRendering.getStencilAttachment();
178 			if(stencilAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
179 			{
180 				vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
181 				if(imageView)
182 				{
183 					imageView->clear(stencilAttachment.clearValue, VK_IMAGE_ASPECT_STENCIL_BIT, rect, viewMask);
184 				}
185 			}
186 
187 			const VkRenderingAttachmentInfo &depthAttachment = dynamicRendering.getDepthAttachment();
188 			if(depthAttachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
189 			{
190 				vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
191 
192 				if(imageView)
193 				{
194 					imageView->clear(depthAttachment.clearValue, VK_IMAGE_ASPECT_DEPTH_BIT, rect, viewMask);
195 				}
196 			}
197 		}
198 	}
199 
description()200 	std::string description() override { return "vkCmdBeginRendering()"; }
201 
202 private:
203 	vk::DynamicRendering dynamicRendering;
204 };
205 
206 class CmdEndRendering : public vk::CommandBuffer::Command
207 {
208 public:
execute(vk::CommandBuffer::ExecutionState & executionState)209 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
210 	{
211 		// TODO(b/197691918): Avoid halt-the-world synchronization.
212 		executionState.renderer->synchronize();
213 
214 		if(!executionState.dynamicRendering->suspend())
215 		{
216 			uint32_t viewMask = executionState.dynamicRendering->getViewMask();
217 
218 			// TODO(b/197691917): Eliminate redundant resolve operations.
219 			uint32_t colorAttachmentCount = executionState.dynamicRendering->getColorAttachmentCount();
220 			for(uint32_t i = 0; i < colorAttachmentCount; i++)
221 			{
222 				const VkRenderingAttachmentInfo *colorAttachment = executionState.dynamicRendering->getColorAttachment(i);
223 				if(colorAttachment && colorAttachment->resolveMode != VK_RESOLVE_MODE_NONE)
224 				{
225 					vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
226 					vk::ImageView *resolveImageView = vk::Cast(colorAttachment->resolveImageView);
227 					imageView->resolve(resolveImageView, viewMask);
228 				}
229 			}
230 
231 			const VkRenderingAttachmentInfo &depthAttachment = executionState.dynamicRendering->getDepthAttachment();
232 			if(depthAttachment.resolveMode != VK_RESOLVE_MODE_NONE)
233 			{
234 				vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
235 				vk::ImageView *resolveImageView = vk::Cast(depthAttachment.resolveImageView);
236 				imageView->resolveDepthStencil(resolveImageView, depthAttachment.resolveMode, VK_RESOLVE_MODE_NONE);
237 			}
238 
239 			const VkRenderingAttachmentInfo &stencilAttachment = executionState.dynamicRendering->getStencilAttachment();
240 			if(stencilAttachment.resolveMode != VK_RESOLVE_MODE_NONE)
241 			{
242 				vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
243 				vk::ImageView *resolveImageView = vk::Cast(stencilAttachment.resolveImageView);
244 				imageView->resolveDepthStencil(resolveImageView, VK_RESOLVE_MODE_NONE, stencilAttachment.resolveMode);
245 			}
246 		}
247 
248 		executionState.dynamicRendering = nullptr;
249 	}
250 
description()251 	std::string description() override { return "vkCmdEndRendering()"; }
252 };
253 
254 class CmdExecuteCommands : public vk::CommandBuffer::Command
255 {
256 public:
CmdExecuteCommands(const vk::CommandBuffer * commandBuffer)257 	CmdExecuteCommands(const vk::CommandBuffer *commandBuffer)
258 	    : commandBuffer(commandBuffer)
259 	{
260 	}
261 
execute(vk::CommandBuffer::ExecutionState & executionState)262 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
263 	{
264 		commandBuffer->submitSecondary(executionState);
265 	}
266 
description()267 	std::string description() override { return "vkCmdExecuteCommands()"; }
268 
269 private:
270 	const vk::CommandBuffer *const commandBuffer;
271 };
272 
273 class CmdPipelineBind : public vk::CommandBuffer::Command
274 {
275 public:
CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint,vk::Pipeline * pipeline)276 	CmdPipelineBind(VkPipelineBindPoint pipelineBindPoint, vk::Pipeline *pipeline)
277 	    : pipelineBindPoint(pipelineBindPoint)
278 	    , pipeline(pipeline)
279 	{
280 	}
281 
execute(vk::CommandBuffer::ExecutionState & executionState)282 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
283 	{
284 		executionState.pipelineState[pipelineBindPoint].pipeline = pipeline;
285 	}
286 
description()287 	std::string description() override { return "vkCmdPipelineBind()"; }
288 
289 private:
290 	const VkPipelineBindPoint pipelineBindPoint;
291 	vk::Pipeline *const pipeline;
292 };
293 
294 class CmdDispatch : public vk::CommandBuffer::Command
295 {
296 public:
CmdDispatch(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)297 	CmdDispatch(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
298 	    : baseGroupX(baseGroupX)
299 	    , baseGroupY(baseGroupY)
300 	    , baseGroupZ(baseGroupZ)
301 	    , groupCountX(groupCountX)
302 	    , groupCountY(groupCountY)
303 	    , groupCountZ(groupCountZ)
304 	{
305 	}
306 
execute(vk::CommandBuffer::ExecutionState & executionState)307 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
308 	{
309 		const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
310 
311 		vk::ComputePipeline *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
312 		pipeline->run(baseGroupX, baseGroupY, baseGroupZ,
313 		              groupCountX, groupCountY, groupCountZ,
314 		              pipelineState.descriptorSetObjects,
315 		              pipelineState.descriptorSets,
316 		              pipelineState.descriptorDynamicOffsets,
317 		              executionState.pushConstants);
318 	}
319 
description()320 	std::string description() override { return "vkCmdDispatch()"; }
321 
322 private:
323 	const uint32_t baseGroupX;
324 	const uint32_t baseGroupY;
325 	const uint32_t baseGroupZ;
326 	const uint32_t groupCountX;
327 	const uint32_t groupCountY;
328 	const uint32_t groupCountZ;
329 };
330 
331 class CmdDispatchIndirect : public vk::CommandBuffer::Command
332 {
333 public:
CmdDispatchIndirect(vk::Buffer * buffer,VkDeviceSize offset)334 	CmdDispatchIndirect(vk::Buffer *buffer, VkDeviceSize offset)
335 	    : buffer(buffer)
336 	    , offset(offset)
337 	{
338 	}
339 
execute(vk::CommandBuffer::ExecutionState & executionState)340 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
341 	{
342 		const auto *cmd = reinterpret_cast<const VkDispatchIndirectCommand *>(buffer->getOffsetPointer(offset));
343 
344 		const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_COMPUTE];
345 
346 		auto *pipeline = static_cast<vk::ComputePipeline *>(pipelineState.pipeline);
347 		pipeline->run(0, 0, 0, cmd->x, cmd->y, cmd->z,
348 		              pipelineState.descriptorSetObjects,
349 		              pipelineState.descriptorSets,
350 		              pipelineState.descriptorDynamicOffsets,
351 		              executionState.pushConstants);
352 	}
353 
description()354 	std::string description() override { return "vkCmdDispatchIndirect()"; }
355 
356 private:
357 	const vk::Buffer *const buffer;
358 	const VkDeviceSize offset;
359 };
360 
361 class CmdVertexBufferBind : public vk::CommandBuffer::Command
362 {
363 public:
CmdVertexBufferBind(uint32_t binding,vk::Buffer * buffer,const VkDeviceSize offset,const VkDeviceSize size,const VkDeviceSize stride)364 	CmdVertexBufferBind(uint32_t binding, vk::Buffer *buffer, const VkDeviceSize offset, const VkDeviceSize size, const VkDeviceSize stride)
365 	    : binding(binding)
366 	    , buffer(buffer)
367 	    , offset(offset)
368 	    , size(size)
369 	    , stride(stride)
370 	{
371 	}
372 
execute(vk::CommandBuffer::ExecutionState & executionState)373 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
374 	{
375 		executionState.vertexInputBindings[binding] = { buffer, offset, size, stride };
376 	}
377 
description()378 	std::string description() override { return "vkCmdVertexBufferBind()"; }
379 
380 private:
381 	const uint32_t binding;
382 	vk::Buffer *const buffer;
383 	const VkDeviceSize offset;
384 	const VkDeviceSize size;
385 	const VkDeviceSize stride;
386 };
387 
388 class CmdIndexBufferBind : public vk::CommandBuffer::Command
389 {
390 public:
CmdIndexBufferBind(vk::Buffer * buffer,const VkDeviceSize offset,const VkIndexType indexType)391 	CmdIndexBufferBind(vk::Buffer *buffer, const VkDeviceSize offset, const VkIndexType indexType)
392 	    : buffer(buffer)
393 	    , offset(offset)
394 	    , indexType(indexType)
395 	{
396 	}
397 
execute(vk::CommandBuffer::ExecutionState & executionState)398 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
399 	{
400 		executionState.indexBufferBinding = { buffer, offset, 0, 0 };
401 		executionState.indexType = indexType;
402 	}
403 
description()404 	std::string description() override { return "vkCmdIndexBufferBind()"; }
405 
406 private:
407 	vk::Buffer *const buffer;
408 	const VkDeviceSize offset;
409 	const VkIndexType indexType;
410 };
411 
412 class CmdSetViewport : public vk::CommandBuffer::Command
413 {
414 public:
CmdSetViewport(const VkViewport & viewport,uint32_t viewportID)415 	CmdSetViewport(const VkViewport &viewport, uint32_t viewportID)
416 	    : viewport(viewport)
417 	    , viewportID(viewportID)
418 	{
419 	}
420 
execute(vk::CommandBuffer::ExecutionState & executionState)421 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
422 	{
423 		executionState.dynamicState.viewport = viewport;
424 	}
425 
description()426 	std::string description() override { return "vkCmdSetViewport()"; }
427 
428 private:
429 	const VkViewport viewport;
430 	const uint32_t viewportID;
431 };
432 
433 class CmdSetScissor : public vk::CommandBuffer::Command
434 {
435 public:
CmdSetScissor(const VkRect2D & scissor,uint32_t scissorID)436 	CmdSetScissor(const VkRect2D &scissor, uint32_t scissorID)
437 	    : scissor(scissor)
438 	    , scissorID(scissorID)
439 	{
440 	}
441 
execute(vk::CommandBuffer::ExecutionState & executionState)442 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
443 	{
444 		executionState.dynamicState.scissor = scissor;
445 	}
446 
description()447 	std::string description() override { return "vkCmdSetScissor()"; }
448 
449 private:
450 	const VkRect2D scissor;
451 	const uint32_t scissorID;
452 };
453 
454 class CmdSetLineWidth : public vk::CommandBuffer::Command
455 {
456 public:
CmdSetLineWidth(float lineWidth)457 	CmdSetLineWidth(float lineWidth)
458 	    : lineWidth(lineWidth)
459 	{
460 	}
461 
execute(vk::CommandBuffer::ExecutionState & executionState)462 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
463 	{
464 		executionState.dynamicState.lineWidth = lineWidth;
465 	}
466 
description()467 	std::string description() override { return "vkCmdSetLineWidth()"; }
468 
469 private:
470 	const float lineWidth;
471 };
472 
473 class CmdSetDepthBias : public vk::CommandBuffer::Command
474 {
475 public:
CmdSetDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)476 	CmdSetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
477 	    : depthBiasConstantFactor(depthBiasConstantFactor)
478 	    , depthBiasClamp(depthBiasClamp)
479 	    , depthBiasSlopeFactor(depthBiasSlopeFactor)
480 	{
481 	}
482 
execute(vk::CommandBuffer::ExecutionState & executionState)483 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
484 	{
485 		executionState.dynamicState.depthBiasConstantFactor = depthBiasConstantFactor;
486 		executionState.dynamicState.depthBiasClamp = depthBiasClamp;
487 		executionState.dynamicState.depthBiasSlopeFactor = depthBiasSlopeFactor;
488 	}
489 
description()490 	std::string description() override { return "vkCmdSetDepthBias()"; }
491 
492 private:
493 	const float depthBiasConstantFactor;
494 	const float depthBiasClamp;
495 	const float depthBiasSlopeFactor;
496 };
497 
498 class CmdSetBlendConstants : public vk::CommandBuffer::Command
499 {
500 public:
CmdSetBlendConstants(const float blendConstants[4])501 	CmdSetBlendConstants(const float blendConstants[4])
502 	{
503 		memcpy(this->blendConstants, blendConstants, sizeof(this->blendConstants));
504 	}
505 
execute(vk::CommandBuffer::ExecutionState & executionState)506 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
507 	{
508 		memcpy(&(executionState.dynamicState.blendConstants[0]), blendConstants, sizeof(blendConstants));
509 	}
510 
description()511 	std::string description() override { return "vkCmdSetBlendConstants()"; }
512 
513 private:
514 	float blendConstants[4];
515 };
516 
517 class CmdSetDepthBounds : public vk::CommandBuffer::Command
518 {
519 public:
CmdSetDepthBounds(float minDepthBounds,float maxDepthBounds)520 	CmdSetDepthBounds(float minDepthBounds, float maxDepthBounds)
521 	    : minDepthBounds(minDepthBounds)
522 	    , maxDepthBounds(maxDepthBounds)
523 	{
524 	}
525 
execute(vk::CommandBuffer::ExecutionState & executionState)526 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
527 	{
528 		executionState.dynamicState.minDepthBounds = minDepthBounds;
529 		executionState.dynamicState.maxDepthBounds = maxDepthBounds;
530 	}
531 
description()532 	std::string description() override { return "vkCmdSetDepthBounds()"; }
533 
534 private:
535 	const float minDepthBounds;
536 	const float maxDepthBounds;
537 };
538 
539 class CmdSetStencilCompareMask : public vk::CommandBuffer::Command
540 {
541 public:
CmdSetStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)542 	CmdSetStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
543 	    : faceMask(faceMask)
544 	    , compareMask(compareMask)
545 	{
546 	}
547 
execute(vk::CommandBuffer::ExecutionState & executionState)548 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
549 	{
550 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
551 		{
552 			executionState.dynamicState.frontStencil.compareMask = compareMask;
553 		}
554 
555 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
556 		{
557 			executionState.dynamicState.backStencil.compareMask = compareMask;
558 		}
559 	}
560 
description()561 	std::string description() override { return "vkCmdSetStencilCompareMask()"; }
562 
563 private:
564 	const VkStencilFaceFlags faceMask;
565 	const uint32_t compareMask;
566 };
567 
568 class CmdSetStencilWriteMask : public vk::CommandBuffer::Command
569 {
570 public:
CmdSetStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)571 	CmdSetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
572 	    : faceMask(faceMask)
573 	    , writeMask(writeMask)
574 	{
575 	}
576 
execute(vk::CommandBuffer::ExecutionState & executionState)577 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
578 	{
579 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
580 		{
581 			executionState.dynamicState.frontStencil.writeMask = writeMask;
582 		}
583 
584 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
585 		{
586 			executionState.dynamicState.backStencil.writeMask = writeMask;
587 		}
588 	}
589 
description()590 	std::string description() override { return "vkCmdSetStencilWriteMask()"; }
591 
592 private:
593 	const VkStencilFaceFlags faceMask;
594 	const uint32_t writeMask;
595 };
596 
597 class CmdSetStencilReference : public vk::CommandBuffer::Command
598 {
599 public:
CmdSetStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)600 	CmdSetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
601 	    : faceMask(faceMask)
602 	    , reference(reference)
603 	{
604 	}
605 
execute(vk::CommandBuffer::ExecutionState & executionState)606 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
607 	{
608 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
609 		{
610 			executionState.dynamicState.frontStencil.reference = reference;
611 		}
612 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
613 		{
614 			executionState.dynamicState.backStencil.reference = reference;
615 		}
616 	}
617 
description()618 	std::string description() override { return "vkCmdSetStencilReference()"; }
619 
620 private:
621 	const VkStencilFaceFlags faceMask;
622 	const uint32_t reference;
623 };
624 
625 class CmdSetCullMode : public vk::CommandBuffer::Command
626 {
627 public:
CmdSetCullMode(VkCullModeFlags cullMode)628 	CmdSetCullMode(VkCullModeFlags cullMode)
629 	    : cullMode(cullMode)
630 	{}
631 
execute(vk::CommandBuffer::ExecutionState & executionState)632 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
633 	{
634 		executionState.dynamicState.cullMode = cullMode;
635 	}
636 
description()637 	std::string description() override { return "vkCmdSetCullModeEXT()"; }
638 
639 private:
640 	const VkCullModeFlags cullMode;
641 };
642 
643 class CmdSetDepthBoundsTestEnable : public vk::CommandBuffer::Command
644 {
645 public:
CmdSetDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)646 	CmdSetDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)
647 	    : depthBoundsTestEnable(depthBoundsTestEnable)
648 	{}
649 
execute(vk::CommandBuffer::ExecutionState & executionState)650 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
651 	{
652 		executionState.dynamicState.depthBoundsTestEnable = depthBoundsTestEnable;
653 	}
654 
description()655 	std::string description() override { return "vkCmdSetDepthBoundsTestEnableEXT()"; }
656 
657 private:
658 	const VkBool32 depthBoundsTestEnable;
659 };
660 
661 class CmdSetDepthCompareOp : public vk::CommandBuffer::Command
662 {
663 public:
CmdSetDepthCompareOp(VkCompareOp depthCompareOp)664 	CmdSetDepthCompareOp(VkCompareOp depthCompareOp)
665 	    : depthCompareOp(depthCompareOp)
666 	{}
667 
execute(vk::CommandBuffer::ExecutionState & executionState)668 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
669 	{
670 		executionState.dynamicState.depthCompareOp = depthCompareOp;
671 	}
672 
description()673 	std::string description() override { return "vkCmdSetDepthCompareOpEXT()"; }
674 
675 private:
676 	const VkCompareOp depthCompareOp;
677 };
678 
679 class CmdSetDepthTestEnable : public vk::CommandBuffer::Command
680 {
681 public:
CmdSetDepthTestEnable(VkBool32 depthTestEnable)682 	CmdSetDepthTestEnable(VkBool32 depthTestEnable)
683 	    : depthTestEnable(depthTestEnable)
684 	{}
685 
execute(vk::CommandBuffer::ExecutionState & executionState)686 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
687 	{
688 		executionState.dynamicState.depthTestEnable = depthTestEnable;
689 	}
690 
description()691 	std::string description() override { return "vkCmdSetDepthTestEnableEXT()"; }
692 
693 private:
694 	const VkBool32 depthTestEnable;
695 };
696 
697 class CmdSetDepthWriteEnable : public vk::CommandBuffer::Command
698 {
699 public:
CmdSetDepthWriteEnable(VkBool32 depthWriteEnable)700 	CmdSetDepthWriteEnable(VkBool32 depthWriteEnable)
701 	    : depthWriteEnable(depthWriteEnable)
702 	{}
703 
execute(vk::CommandBuffer::ExecutionState & executionState)704 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
705 	{
706 		executionState.dynamicState.depthWriteEnable = depthWriteEnable;
707 	}
708 
description()709 	std::string description() override { return "vkCmdSetDepthWriteEnableEXT()"; }
710 
711 private:
712 	const VkBool32 depthWriteEnable;
713 };
714 
715 class CmdSetFrontFace : public vk::CommandBuffer::Command
716 {
717 public:
CmdSetFrontFace(VkFrontFace frontFace)718 	CmdSetFrontFace(VkFrontFace frontFace)
719 	    : frontFace(frontFace)
720 	{}
721 
execute(vk::CommandBuffer::ExecutionState & executionState)722 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
723 	{
724 		executionState.dynamicState.frontFace = frontFace;
725 	}
726 
description()727 	std::string description() override { return "vkCmdSetFrontFaceEXT()"; }
728 
729 private:
730 	const VkFrontFace frontFace;
731 };
732 
733 class CmdSetPrimitiveTopology : public vk::CommandBuffer::Command
734 {
735 public:
CmdSetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)736 	CmdSetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
737 	    : primitiveTopology(primitiveTopology)
738 	{}
739 
execute(vk::CommandBuffer::ExecutionState & executionState)740 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
741 	{
742 		executionState.dynamicState.primitiveTopology = primitiveTopology;
743 	}
744 
description()745 	std::string description() override { return "vkCmdSetPrimitiveTopologyEXT()"; }
746 
747 private:
748 	const VkPrimitiveTopology primitiveTopology;
749 };
750 
751 class CmdSetScissorWithCount : public vk::CommandBuffer::Command
752 {
753 public:
CmdSetScissorWithCount(uint32_t scissorCount,const VkRect2D * pScissors)754 	CmdSetScissorWithCount(uint32_t scissorCount, const VkRect2D *pScissors)
755 	    : scissorCount(scissorCount)
756 	{
757 		memcpy(&(scissors[0]), pScissors, scissorCount * sizeof(VkRect2D));
758 	}
759 
execute(vk::CommandBuffer::ExecutionState & executionState)760 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
761 	{
762 		executionState.dynamicState.scissorCount = scissorCount;
763 		for(uint32_t i = 0; i < scissorCount; i++)
764 		{
765 			executionState.dynamicState.scissors[i] = scissors[i];
766 		}
767 	}
768 
description()769 	std::string description() override { return "vkCmdSetScissorWithCountEXT()"; }
770 
771 private:
772 	const uint32_t scissorCount;
773 	VkRect2D scissors[vk::MAX_VIEWPORTS];
774 };
775 
776 class CmdSetStencilOp : public vk::CommandBuffer::Command
777 {
778 public:
CmdSetStencilOp(VkStencilFaceFlags faceMask,VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp,VkCompareOp compareOp)779 	CmdSetStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp)
780 	    : faceMask(faceMask)
781 	    , failOp(failOp)
782 	    , passOp(passOp)
783 	    , depthFailOp(depthFailOp)
784 	    , compareOp(compareOp)
785 	{}
786 
execute(vk::CommandBuffer::ExecutionState & executionState)787 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
788 	{
789 		executionState.dynamicState.faceMask |= faceMask;
790 
791 		if(faceMask & VK_STENCIL_FACE_FRONT_BIT)
792 		{
793 			executionState.dynamicState.frontStencil.failOp = failOp;
794 			executionState.dynamicState.frontStencil.passOp = passOp;
795 			executionState.dynamicState.frontStencil.depthFailOp = depthFailOp;
796 			executionState.dynamicState.frontStencil.compareOp = compareOp;
797 		}
798 		if(faceMask & VK_STENCIL_FACE_BACK_BIT)
799 		{
800 			executionState.dynamicState.backStencil.failOp = failOp;
801 			executionState.dynamicState.backStencil.passOp = passOp;
802 			executionState.dynamicState.backStencil.depthFailOp = depthFailOp;
803 			executionState.dynamicState.backStencil.compareOp = compareOp;
804 		}
805 	}
806 
description()807 	std::string description() override { return "vkCmdSetStencilOpEXT()"; }
808 
809 private:
810 	const VkStencilFaceFlags faceMask;
811 	const VkStencilOp failOp;
812 	const VkStencilOp passOp;
813 	const VkStencilOp depthFailOp;
814 	const VkCompareOp compareOp;
815 };
816 
817 class CmdSetStencilTestEnable : public vk::CommandBuffer::Command
818 {
819 public:
CmdSetStencilTestEnable(VkBool32 stencilTestEnable)820 	CmdSetStencilTestEnable(VkBool32 stencilTestEnable)
821 	    : stencilTestEnable(stencilTestEnable)
822 	{}
823 
execute(vk::CommandBuffer::ExecutionState & executionState)824 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
825 	{
826 		executionState.dynamicState.stencilTestEnable = stencilTestEnable;
827 	}
828 
description()829 	std::string description() override { return "vkCmdSetStencilTestEnableEXT()"; }
830 
831 private:
832 	const VkBool32 stencilTestEnable;
833 };
834 
835 class CmdSetViewportWithCount : public vk::CommandBuffer::Command
836 {
837 public:
CmdSetViewportWithCount(uint32_t viewportCount,const VkViewport * pViewports)838 	CmdSetViewportWithCount(uint32_t viewportCount, const VkViewport *pViewports)
839 	    : viewportCount(viewportCount)
840 	{
841 		memcpy(&(viewports[0]), pViewports, viewportCount * sizeof(VkRect2D));
842 	}
843 
execute(vk::CommandBuffer::ExecutionState & executionState)844 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
845 	{
846 		executionState.dynamicState.viewportCount = viewportCount;
847 		for(uint32_t i = 0; i < viewportCount; i++)
848 		{
849 			executionState.dynamicState.viewports[i] = viewports[i];
850 		}
851 	}
852 
description()853 	std::string description() override { return "vkCmdSetViewportWithCountEXT()"; }
854 
855 private:
856 	const uint32_t viewportCount;
857 	VkRect2D viewports[vk::MAX_VIEWPORTS];
858 };
859 
860 class CmdSetRasterizerDiscardEnable : public vk::CommandBuffer::Command
861 {
862 public:
CmdSetRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)863 	CmdSetRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)
864 	    : rasterizerDiscardEnable(rasterizerDiscardEnable)
865 	{}
866 
execute(vk::CommandBuffer::ExecutionState & executionState)867 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
868 	{
869 		executionState.dynamicState.rasterizerDiscardEnable = rasterizerDiscardEnable;
870 	}
871 
description()872 	std::string description() override { return "vkCmdSetRasterizerDiscardEnable()"; }
873 
874 private:
875 	const VkBool32 rasterizerDiscardEnable;
876 };
877 
878 class CmdSetDepthBiasEnable : public vk::CommandBuffer::Command
879 {
880 public:
CmdSetDepthBiasEnable(VkBool32 depthBiasEnable)881 	CmdSetDepthBiasEnable(VkBool32 depthBiasEnable)
882 	    : depthBiasEnable(depthBiasEnable)
883 	{}
884 
execute(vk::CommandBuffer::ExecutionState & executionState)885 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
886 	{
887 		executionState.dynamicState.depthBiasEnable = depthBiasEnable;
888 	}
889 
description()890 	std::string description() override { return "vkCmdSetDepthBiasEnable()"; }
891 
892 private:
893 	const VkBool32 depthBiasEnable;
894 };
895 
896 class CmdSetPrimitiveRestartEnable : public vk::CommandBuffer::Command
897 {
898 public:
CmdSetPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)899 	CmdSetPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)
900 	    : primitiveRestartEnable(primitiveRestartEnable)
901 	{}
902 
execute(vk::CommandBuffer::ExecutionState & executionState)903 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
904 	{
905 		executionState.dynamicState.primitiveRestartEnable = primitiveRestartEnable;
906 	}
907 
description()908 	std::string description() override { return "vkCmdSetPrimitiveRestartEnable()"; }
909 
910 private:
911 	const VkBool32 primitiveRestartEnable;
912 };
913 
914 class CmdDrawBase : public vk::CommandBuffer::Command
915 {
916 public:
draw(vk::CommandBuffer::ExecutionState & executionState,bool indexed,uint32_t count,uint32_t instanceCount,uint32_t first,int32_t vertexOffset,uint32_t firstInstance)917 	void draw(vk::CommandBuffer::ExecutionState &executionState, bool indexed,
918 	          uint32_t count, uint32_t instanceCount, uint32_t first, int32_t vertexOffset, uint32_t firstInstance)
919 	{
920 		const auto &pipelineState = executionState.pipelineState[VK_PIPELINE_BIND_POINT_GRAPHICS];
921 
922 		auto *pipeline = static_cast<vk::GraphicsPipeline *>(pipelineState.pipeline);
923 		bool hasDynamicVertexStride = pipeline->hasDynamicVertexStride();
924 
925 		vk::Attachments &attachments = pipeline->getAttachments();
926 		executionState.bindAttachments(&attachments);
927 
928 		vk::Inputs &inputs = pipeline->getInputs();
929 		inputs.updateDescriptorSets(pipelineState.descriptorSetObjects,
930 		                            pipelineState.descriptorSets,
931 		                            pipelineState.descriptorDynamicOffsets);
932 		inputs.setVertexInputBinding(executionState.vertexInputBindings);
933 		inputs.bindVertexInputs(firstInstance, hasDynamicVertexStride);
934 
935 		if(indexed)
936 		{
937 			vk::IndexBuffer &indexBuffer = pipeline->getIndexBuffer();
938 			indexBuffer.setIndexBufferBinding(executionState.indexBufferBinding, executionState.indexType);
939 		}
940 
941 		std::vector<std::pair<uint32_t, void *>> indexBuffers;
942 		pipeline->getIndexBuffers(executionState.dynamicState, count, first, indexed, &indexBuffers);
943 
944 		VkRect2D renderArea = executionState.getRenderArea();
945 
946 		for(uint32_t instance = firstInstance; instance != firstInstance + instanceCount; instance++)
947 		{
948 			// FIXME: reconsider instances/views nesting.
949 			auto layerMask = executionState.getLayerMask();
950 			while(layerMask)
951 			{
952 				int layer = sw::log2i(layerMask);
953 				layerMask &= ~(1 << layer);
954 
955 				for(auto indexBuffer : indexBuffers)
956 				{
957 					executionState.renderer->draw(pipeline, executionState.dynamicState, indexBuffer.first, vertexOffset,
958 					                              executionState.events, instance, layer, indexBuffer.second,
959 					                              renderArea, executionState.pushConstants);
960 				}
961 			}
962 
963 			if(instanceCount > 1)
964 			{
965 				UNOPTIMIZED("Optimize instancing to use a single draw call.");  // TODO(b/137740918)
966 				inputs.advanceInstanceAttributes(hasDynamicVertexStride);
967 			}
968 		}
969 	}
970 };
971 
972 class CmdDraw : public CmdDrawBase
973 {
974 public:
CmdDraw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)975 	CmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
976 	    : vertexCount(vertexCount)
977 	    , instanceCount(instanceCount)
978 	    , firstVertex(firstVertex)
979 	    , firstInstance(firstInstance)
980 	{
981 	}
982 
execute(vk::CommandBuffer::ExecutionState & executionState)983 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
984 	{
985 		draw(executionState, false, vertexCount, instanceCount, 0, firstVertex, firstInstance);
986 	}
987 
description()988 	std::string description() override { return "vkCmdDraw()"; }
989 
990 private:
991 	const uint32_t vertexCount;
992 	const uint32_t instanceCount;
993 	const uint32_t firstVertex;
994 	const uint32_t firstInstance;
995 };
996 
997 class CmdDrawIndexed : public CmdDrawBase
998 {
999 public:
CmdDrawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)1000 	CmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
1001 	    : indexCount(indexCount)
1002 	    , instanceCount(instanceCount)
1003 	    , firstIndex(firstIndex)
1004 	    , vertexOffset(vertexOffset)
1005 	    , firstInstance(firstInstance)
1006 	{
1007 	}
1008 
execute(vk::CommandBuffer::ExecutionState & executionState)1009 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1010 	{
1011 		draw(executionState, true, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1012 	}
1013 
description()1014 	std::string description() override { return "vkCmdDrawIndexed()"; }
1015 
1016 private:
1017 	const uint32_t indexCount;
1018 	const uint32_t instanceCount;
1019 	const uint32_t firstIndex;
1020 	const int32_t vertexOffset;
1021 	const uint32_t firstInstance;
1022 };
1023 
1024 class CmdDrawIndirect : public CmdDrawBase
1025 {
1026 public:
CmdDrawIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1027 	CmdDrawIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1028 	    : buffer(buffer)
1029 	    , offset(offset)
1030 	    , drawCount(drawCount)
1031 	    , stride(stride)
1032 	{
1033 	}
1034 
execute(vk::CommandBuffer::ExecutionState & executionState)1035 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1036 	{
1037 		for(auto drawId = 0u; drawId < drawCount; drawId++)
1038 		{
1039 			const auto *cmd = reinterpret_cast<const VkDrawIndirectCommand *>(buffer->getOffsetPointer(offset + drawId * stride));
1040 			draw(executionState, false, cmd->vertexCount, cmd->instanceCount, 0, cmd->firstVertex, cmd->firstInstance);
1041 		}
1042 	}
1043 
description()1044 	std::string description() override { return "vkCmdDrawIndirect()"; }
1045 
1046 private:
1047 	const vk::Buffer *const buffer;
1048 	const VkDeviceSize offset;
1049 	const uint32_t drawCount;
1050 	const uint32_t stride;
1051 };
1052 
1053 class CmdDrawIndexedIndirect : public CmdDrawBase
1054 {
1055 public:
CmdDrawIndexedIndirect(vk::Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)1056 	CmdDrawIndexedIndirect(vk::Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
1057 	    : buffer(buffer)
1058 	    , offset(offset)
1059 	    , drawCount(drawCount)
1060 	    , stride(stride)
1061 	{
1062 	}
1063 
execute(vk::CommandBuffer::ExecutionState & executionState)1064 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1065 	{
1066 		for(auto drawId = 0u; drawId < drawCount; drawId++)
1067 		{
1068 			const auto *cmd = reinterpret_cast<const VkDrawIndexedIndirectCommand *>(buffer->getOffsetPointer(offset + drawId * stride));
1069 			draw(executionState, true, cmd->indexCount, cmd->instanceCount, cmd->firstIndex, cmd->vertexOffset, cmd->firstInstance);
1070 		}
1071 	}
1072 
description()1073 	std::string description() override { return "vkCmdDrawIndexedIndirect()"; }
1074 
1075 private:
1076 	const vk::Buffer *const buffer;
1077 	const VkDeviceSize offset;
1078 	const uint32_t drawCount;
1079 	const uint32_t stride;
1080 };
1081 
1082 class CmdCopyImage : public vk::CommandBuffer::Command
1083 {
1084 public:
CmdCopyImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageCopy2 & region)1085 	CmdCopyImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageCopy2 &region)
1086 	    : srcImage(srcImage)
1087 	    , dstImage(dstImage)
1088 	    , region(region)
1089 	{
1090 	}
1091 
execute(vk::CommandBuffer::ExecutionState & executionState)1092 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1093 	{
1094 		srcImage->copyTo(dstImage, region);
1095 	}
1096 
description()1097 	std::string description() override { return "vkCmdCopyImage()"; }
1098 
1099 private:
1100 	const vk::Image *const srcImage;
1101 	vk::Image *const dstImage;
1102 	const VkImageCopy2 region;
1103 };
1104 
1105 class CmdCopyBuffer : public vk::CommandBuffer::Command
1106 {
1107 public:
CmdCopyBuffer(const vk::Buffer * srcBuffer,vk::Buffer * dstBuffer,const VkBufferCopy2 & region)1108 	CmdCopyBuffer(const vk::Buffer *srcBuffer, vk::Buffer *dstBuffer, const VkBufferCopy2 &region)
1109 	    : srcBuffer(srcBuffer)
1110 	    , dstBuffer(dstBuffer)
1111 	    , region(region)
1112 	{
1113 	}
1114 
execute(vk::CommandBuffer::ExecutionState & executionState)1115 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1116 	{
1117 		srcBuffer->copyTo(dstBuffer, region);
1118 	}
1119 
description()1120 	std::string description() override { return "vkCmdCopyBuffer()"; }
1121 
1122 private:
1123 	const vk::Buffer *const srcBuffer;
1124 	vk::Buffer *const dstBuffer;
1125 	const VkBufferCopy2 region;
1126 };
1127 
1128 class CmdCopyImageToBuffer : public vk::CommandBuffer::Command
1129 {
1130 public:
CmdCopyImageToBuffer(vk::Image * srcImage,vk::Buffer * dstBuffer,const VkBufferImageCopy2 & region)1131 	CmdCopyImageToBuffer(vk::Image *srcImage, vk::Buffer *dstBuffer, const VkBufferImageCopy2 &region)
1132 	    : srcImage(srcImage)
1133 	    , dstBuffer(dstBuffer)
1134 	    , region(region)
1135 	{
1136 	}
1137 
execute(vk::CommandBuffer::ExecutionState & executionState)1138 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1139 	{
1140 		srcImage->copyTo(dstBuffer, region);
1141 	}
1142 
description()1143 	std::string description() override { return "vkCmdCopyImageToBuffer()"; }
1144 
1145 private:
1146 	vk::Image *const srcImage;
1147 	vk::Buffer *const dstBuffer;
1148 	const VkBufferImageCopy2 region;
1149 };
1150 
1151 class CmdCopyBufferToImage : public vk::CommandBuffer::Command
1152 {
1153 public:
CmdCopyBufferToImage(vk::Buffer * srcBuffer,vk::Image * dstImage,const VkBufferImageCopy2 & region)1154 	CmdCopyBufferToImage(vk::Buffer *srcBuffer, vk::Image *dstImage, const VkBufferImageCopy2 &region)
1155 	    : srcBuffer(srcBuffer)
1156 	    , dstImage(dstImage)
1157 	    , region(region)
1158 	{
1159 	}
1160 
execute(vk::CommandBuffer::ExecutionState & executionState)1161 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1162 	{
1163 		dstImage->copyFrom(srcBuffer, region);
1164 	}
1165 
description()1166 	std::string description() override { return "vkCmdCopyBufferToImage()"; }
1167 
1168 private:
1169 	vk::Buffer *const srcBuffer;
1170 	vk::Image *const dstImage;
1171 	const VkBufferImageCopy2 region;
1172 };
1173 
1174 class CmdFillBuffer : public vk::CommandBuffer::Command
1175 {
1176 public:
CmdFillBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)1177 	CmdFillBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
1178 	    : dstBuffer(dstBuffer)
1179 	    , dstOffset(dstOffset)
1180 	    , size(size)
1181 	    , data(data)
1182 	{
1183 	}
1184 
execute(vk::CommandBuffer::ExecutionState & executionState)1185 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1186 	{
1187 		dstBuffer->fill(dstOffset, size, data);
1188 	}
1189 
description()1190 	std::string description() override { return "vkCmdFillBuffer()"; }
1191 
1192 private:
1193 	vk::Buffer *const dstBuffer;
1194 	const VkDeviceSize dstOffset;
1195 	const VkDeviceSize size;
1196 	const uint32_t data;
1197 };
1198 
1199 class CmdUpdateBuffer : public vk::CommandBuffer::Command
1200 {
1201 public:
CmdUpdateBuffer(vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const uint8_t * pData)1202 	CmdUpdateBuffer(vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint8_t *pData)
1203 	    : dstBuffer(dstBuffer)
1204 	    , dstOffset(dstOffset)
1205 	    , data(pData, &pData[dataSize])
1206 	{
1207 	}
1208 
execute(vk::CommandBuffer::ExecutionState & executionState)1209 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1210 	{
1211 		dstBuffer->update(dstOffset, data.size(), data.data());
1212 	}
1213 
description()1214 	std::string description() override { return "vkCmdUpdateBuffer()"; }
1215 
1216 private:
1217 	vk::Buffer *const dstBuffer;
1218 	const VkDeviceSize dstOffset;
1219 	const std::vector<uint8_t> data;  // FIXME(b/119409619): replace this vector by an allocator so we can control all memory allocations
1220 };
1221 
1222 class CmdClearColorImage : public vk::CommandBuffer::Command
1223 {
1224 public:
CmdClearColorImage(vk::Image * image,const VkClearColorValue & color,const VkImageSubresourceRange & range)1225 	CmdClearColorImage(vk::Image *image, const VkClearColorValue &color, const VkImageSubresourceRange &range)
1226 	    : image(image)
1227 	    , color(color)
1228 	    , range(range)
1229 	{
1230 	}
1231 
execute(vk::CommandBuffer::ExecutionState & executionState)1232 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1233 	{
1234 		image->clear(color, range);
1235 	}
1236 
description()1237 	std::string description() override { return "vkCmdClearColorImage()"; }
1238 
1239 private:
1240 	vk::Image *const image;
1241 	const VkClearColorValue color;
1242 	const VkImageSubresourceRange range;
1243 };
1244 
1245 class CmdClearDepthStencilImage : public vk::CommandBuffer::Command
1246 {
1247 public:
CmdClearDepthStencilImage(vk::Image * image,const VkClearDepthStencilValue & depthStencil,const VkImageSubresourceRange & range)1248 	CmdClearDepthStencilImage(vk::Image *image, const VkClearDepthStencilValue &depthStencil, const VkImageSubresourceRange &range)
1249 	    : image(image)
1250 	    , depthStencil(depthStencil)
1251 	    , range(range)
1252 	{
1253 	}
1254 
execute(vk::CommandBuffer::ExecutionState & executionState)1255 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1256 	{
1257 		image->clear(depthStencil, range);
1258 	}
1259 
description()1260 	std::string description() override { return "vkCmdClearDepthStencilImage()"; }
1261 
1262 private:
1263 	vk::Image *const image;
1264 	const VkClearDepthStencilValue depthStencil;
1265 	const VkImageSubresourceRange range;
1266 };
1267 
1268 class CmdClearAttachment : public vk::CommandBuffer::Command
1269 {
1270 public:
CmdClearAttachment(const VkClearAttachment & attachment,const VkClearRect & rect)1271 	CmdClearAttachment(const VkClearAttachment &attachment, const VkClearRect &rect)
1272 	    : attachment(attachment)
1273 	    , rect(rect)
1274 	{
1275 	}
1276 
execute(vk::CommandBuffer::ExecutionState & executionState)1277 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1278 	{
1279 		// attachment clears are drawing operations, and so have rasterization-order guarantees.
1280 		// however, we don't do the clear through the rasterizer, so need to ensure prior drawing
1281 		// has completed first.
1282 		executionState.renderer->synchronize();
1283 
1284 		if(executionState.renderPassFramebuffer)
1285 		{
1286 			executionState.renderPassFramebuffer->clearAttachment(executionState.renderPass, executionState.subpassIndex, attachment, rect);
1287 		}
1288 		else if(executionState.dynamicRendering)
1289 		{
1290 			uint32_t viewMask = executionState.dynamicRendering->getViewMask();
1291 
1292 			if(attachment.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
1293 			{
1294 				ASSERT(attachment.colorAttachment < executionState.dynamicRendering->getColorAttachmentCount());
1295 
1296 				const VkRenderingAttachmentInfo *colorAttachment =
1297 				    executionState.dynamicRendering->getColorAttachment(attachment.colorAttachment);
1298 
1299 				if(colorAttachment)
1300 				{
1301 					vk::ImageView *imageView = vk::Cast(colorAttachment->imageView);
1302 					if(imageView)
1303 					{
1304 						imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_COLOR_BIT, rect, viewMask);
1305 					}
1306 				}
1307 			}
1308 
1309 			if(attachment.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
1310 			{
1311 				const VkRenderingAttachmentInfo &depthAttachment = executionState.dynamicRendering->getDepthAttachment();
1312 
1313 				vk::ImageView *imageView = vk::Cast(depthAttachment.imageView);
1314 				if(imageView)
1315 				{
1316 					imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_DEPTH_BIT, rect, viewMask);
1317 				}
1318 			}
1319 
1320 			if(attachment.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
1321 			{
1322 				const VkRenderingAttachmentInfo &stencilAttachment = executionState.dynamicRendering->getStencilAttachment();
1323 
1324 				vk::ImageView *imageView = vk::Cast(stencilAttachment.imageView);
1325 				if(imageView)
1326 				{
1327 					imageView->clear(attachment.clearValue, VK_IMAGE_ASPECT_STENCIL_BIT, rect, viewMask);
1328 				}
1329 			}
1330 		}
1331 	}
1332 
description()1333 	std::string description() override { return "vkCmdClearAttachment()"; }
1334 
1335 private:
1336 	const VkClearAttachment attachment;
1337 	const VkClearRect rect;
1338 };
1339 
1340 class CmdBlitImage : public vk::CommandBuffer::Command
1341 {
1342 public:
CmdBlitImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageBlit2 & region,VkFilter filter)1343 	CmdBlitImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageBlit2 &region, VkFilter filter)
1344 	    : srcImage(srcImage)
1345 	    , dstImage(dstImage)
1346 	    , region(region)
1347 	    , filter(filter)
1348 	{
1349 	}
1350 
execute(vk::CommandBuffer::ExecutionState & executionState)1351 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1352 	{
1353 		srcImage->blitTo(dstImage, region, filter);
1354 	}
1355 
description()1356 	std::string description() override { return "vkCmdBlitImage()"; }
1357 
1358 private:
1359 	const vk::Image *const srcImage;
1360 	vk::Image *const dstImage;
1361 	const VkImageBlit2 region;
1362 	const VkFilter filter;
1363 };
1364 
1365 class CmdResolveImage : public vk::CommandBuffer::Command
1366 {
1367 public:
CmdResolveImage(const vk::Image * srcImage,vk::Image * dstImage,const VkImageResolve2 & region)1368 	CmdResolveImage(const vk::Image *srcImage, vk::Image *dstImage, const VkImageResolve2 &region)
1369 	    : srcImage(srcImage)
1370 	    , dstImage(dstImage)
1371 	    , region(region)
1372 	{
1373 	}
1374 
execute(vk::CommandBuffer::ExecutionState & executionState)1375 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1376 	{
1377 		srcImage->resolveTo(dstImage, region);
1378 	}
1379 
description()1380 	std::string description() override { return "vkCmdBlitImage()"; }
1381 
1382 private:
1383 	const vk::Image *const srcImage;
1384 	vk::Image *const dstImage;
1385 	const VkImageResolve2 region;
1386 };
1387 
1388 class CmdPipelineBarrier : public vk::CommandBuffer::Command
1389 {
1390 public:
execute(vk::CommandBuffer::ExecutionState & executionState)1391 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1392 	{
1393 		// This is a very simple implementation that simply calls sw::Renderer::synchronize(),
1394 		// since the driver is free to move the source stage towards the bottom of the pipe
1395 		// and the target stage towards the top, so a full pipeline sync is spec compliant.
1396 		executionState.renderer->synchronize();
1397 
1398 		// Right now all buffers are read-only in drawcalls but a similar mechanism will be required once we support SSBOs.
1399 
1400 		// Also note that this would be a good moment to update cube map borders or decompress compressed textures, if necessary.
1401 	}
1402 
description()1403 	std::string description() override { return "vkCmdPipelineBarrier()"; }
1404 };
1405 
1406 class CmdSignalEvent : public vk::CommandBuffer::Command
1407 {
1408 public:
CmdSignalEvent(vk::Event * ev)1409 	CmdSignalEvent(vk::Event *ev)
1410 	    : ev(ev)
1411 	{
1412 	}
1413 
execute(vk::CommandBuffer::ExecutionState & executionState)1414 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1415 	{
1416 		executionState.renderer->synchronize();
1417 		ev->signal();
1418 	}
1419 
description()1420 	std::string description() override { return "vkCmdSignalEvent()"; }
1421 
1422 private:
1423 	vk::Event *const ev;
1424 };
1425 
1426 class CmdResetEvent : public vk::CommandBuffer::Command
1427 {
1428 public:
CmdResetEvent(vk::Event * ev,VkPipelineStageFlags2 stageMask)1429 	CmdResetEvent(vk::Event *ev, VkPipelineStageFlags2 stageMask)
1430 	    : ev(ev)
1431 	    , stageMask(stageMask)
1432 	{
1433 	}
1434 
execute(vk::CommandBuffer::ExecutionState & executionState)1435 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1436 	{
1437 		ev->reset();
1438 	}
1439 
description()1440 	std::string description() override { return "vkCmdResetEvent()"; }
1441 
1442 private:
1443 	vk::Event *const ev;
1444 	const VkPipelineStageFlags2 stageMask;  // FIXME(b/117835459): We currently ignore the flags and reset the event at the last stage
1445 };
1446 
1447 class CmdWaitEvent : public vk::CommandBuffer::Command
1448 {
1449 public:
CmdWaitEvent(vk::Event * ev)1450 	CmdWaitEvent(vk::Event *ev)
1451 	    : ev(ev)
1452 	{
1453 	}
1454 
execute(vk::CommandBuffer::ExecutionState & executionState)1455 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1456 	{
1457 		executionState.renderer->synchronize();
1458 		ev->wait();
1459 	}
1460 
description()1461 	std::string description() override { return "vkCmdWaitEvent()"; }
1462 
1463 private:
1464 	vk::Event *const ev;
1465 };
1466 
1467 class CmdBindDescriptorSets : public vk::CommandBuffer::Command
1468 {
1469 public:
CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t firstDynamicOffset,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)1470 	CmdBindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
1471 	                      uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
1472 	                      uint32_t firstDynamicOffset, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
1473 	    : pipelineBindPoint(pipelineBindPoint)
1474 	    , firstSet(firstSet)
1475 	    , descriptorSetCount(descriptorSetCount)
1476 	    , firstDynamicOffset(firstDynamicOffset)
1477 	    , dynamicOffsetCount(dynamicOffsetCount)
1478 	{
1479 		for(uint32_t i = 0; i < descriptorSetCount; i++)
1480 		{
1481 			// We need both a descriptor set object for updates and a descriptor set data pointer for routines
1482 			descriptorSetObjects[firstSet + i] = vk::Cast(pDescriptorSets[i]);
1483 			descriptorSets[firstSet + i] = vk::Cast(pDescriptorSets[i])->getDataAddress();
1484 		}
1485 
1486 		for(uint32_t i = 0; i < dynamicOffsetCount; i++)
1487 		{
1488 			dynamicOffsets[firstDynamicOffset + i] = pDynamicOffsets[i];
1489 		}
1490 	}
1491 
execute(vk::CommandBuffer::ExecutionState & executionState)1492 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1493 	{
1494 		ASSERT((size_t)pipelineBindPoint < executionState.pipelineState.size());
1495 		ASSERT(firstSet + descriptorSetCount <= vk::MAX_BOUND_DESCRIPTOR_SETS);
1496 		ASSERT(firstDynamicOffset + dynamicOffsetCount <= vk::MAX_DESCRIPTOR_SET_COMBINED_BUFFERS_DYNAMIC);
1497 
1498 		auto &pipelineState = executionState.pipelineState[pipelineBindPoint];
1499 
1500 		for(uint32_t i = firstSet; i < firstSet + descriptorSetCount; i++)
1501 		{
1502 			pipelineState.descriptorSetObjects[i] = descriptorSetObjects[i];
1503 			pipelineState.descriptorSets[i] = descriptorSets[i];
1504 		}
1505 
1506 		for(uint32_t i = firstDynamicOffset; i < firstDynamicOffset + dynamicOffsetCount; i++)
1507 		{
1508 			pipelineState.descriptorDynamicOffsets[i] = dynamicOffsets[i];
1509 		}
1510 	}
1511 
description()1512 	std::string description() override { return "vkCmdBindDescriptorSets()"; }
1513 
1514 private:
1515 	const VkPipelineBindPoint pipelineBindPoint;
1516 	const uint32_t firstSet;
1517 	const uint32_t descriptorSetCount;
1518 	const uint32_t firstDynamicOffset;
1519 	const uint32_t dynamicOffsetCount;
1520 
1521 	vk::DescriptorSet::Array descriptorSetObjects;
1522 	vk::DescriptorSet::Bindings descriptorSets;
1523 	vk::DescriptorSet::DynamicOffsets dynamicOffsets;
1524 };
1525 
1526 class CmdSetPushConstants : public vk::CommandBuffer::Command
1527 {
1528 public:
CmdSetPushConstants(uint32_t offset,uint32_t size,const void * pValues)1529 	CmdSetPushConstants(uint32_t offset, uint32_t size, const void *pValues)
1530 	    : offset(offset)
1531 	    , size(size)
1532 	{
1533 		ASSERT(offset < vk::MAX_PUSH_CONSTANT_SIZE);
1534 		ASSERT(offset + size <= vk::MAX_PUSH_CONSTANT_SIZE);
1535 
1536 		memcpy(data, pValues, size);
1537 	}
1538 
execute(vk::CommandBuffer::ExecutionState & executionState)1539 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1540 	{
1541 		memcpy(&executionState.pushConstants.data[offset], data, size);
1542 	}
1543 
description()1544 	std::string description() override { return "vkCmdSetPushConstants()"; }
1545 
1546 private:
1547 	const uint32_t offset;
1548 	const uint32_t size;
1549 	unsigned char data[vk::MAX_PUSH_CONSTANT_SIZE];
1550 };
1551 
1552 class CmdBeginQuery : public vk::CommandBuffer::Command
1553 {
1554 public:
CmdBeginQuery(vk::QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1555 	CmdBeginQuery(vk::QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1556 	    : queryPool(queryPool)
1557 	    , query(query)
1558 	    , flags(flags)
1559 	{
1560 	}
1561 
execute(vk::CommandBuffer::ExecutionState & executionState)1562 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1563 	{
1564 		// "If queries are used while executing a render pass instance that has multiview enabled, the query uses
1565 		//  N consecutive query indices in the query pool (starting at `query`)"
1566 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1567 		{
1568 			queryPool->begin(query + i, flags);
1569 		}
1570 
1571 		// The renderer accumulates the result into a single query.
1572 		ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1573 		executionState.renderer->addQuery(queryPool->getQuery(query));
1574 	}
1575 
description()1576 	std::string description() override { return "vkCmdBeginQuery()"; }
1577 
1578 private:
1579 	vk::QueryPool *const queryPool;
1580 	const uint32_t query;
1581 	const VkQueryControlFlags flags;
1582 };
1583 
1584 class CmdEndQuery : public vk::CommandBuffer::Command
1585 {
1586 public:
CmdEndQuery(vk::QueryPool * queryPool,uint32_t query)1587 	CmdEndQuery(vk::QueryPool *queryPool, uint32_t query)
1588 	    : queryPool(queryPool)
1589 	    , query(query)
1590 	{
1591 	}
1592 
execute(vk::CommandBuffer::ExecutionState & executionState)1593 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1594 	{
1595 		// The renderer accumulates the result into a single query.
1596 		ASSERT(queryPool->getType() == VK_QUERY_TYPE_OCCLUSION);
1597 		executionState.renderer->removeQuery(queryPool->getQuery(query));
1598 
1599 		// "implementations may write the total result to the first query and write zero to the other queries."
1600 		for(uint32_t i = 1; i < executionState.viewCount(); i++)
1601 		{
1602 			queryPool->getQuery(query + i)->set(0);
1603 		}
1604 
1605 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1606 		{
1607 			queryPool->end(query + i);
1608 		}
1609 	}
1610 
description()1611 	std::string description() override { return "vkCmdEndQuery()"; }
1612 
1613 private:
1614 	vk::QueryPool *const queryPool;
1615 	const uint32_t query;
1616 };
1617 
1618 class CmdResetQueryPool : public vk::CommandBuffer::Command
1619 {
1620 public:
CmdResetQueryPool(vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1621 	CmdResetQueryPool(vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1622 	    : queryPool(queryPool)
1623 	    , firstQuery(firstQuery)
1624 	    , queryCount(queryCount)
1625 	{
1626 	}
1627 
execute(vk::CommandBuffer::ExecutionState & executionState)1628 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1629 	{
1630 		queryPool->reset(firstQuery, queryCount);
1631 	}
1632 
description()1633 	std::string description() override { return "vkCmdResetQueryPool()"; }
1634 
1635 private:
1636 	vk::QueryPool *const queryPool;
1637 	const uint32_t firstQuery;
1638 	const uint32_t queryCount;
1639 };
1640 
1641 class CmdWriteTimeStamp : public vk::CommandBuffer::Command
1642 {
1643 public:
CmdWriteTimeStamp(vk::QueryPool * queryPool,uint32_t query,VkPipelineStageFlagBits2 stage)1644 	CmdWriteTimeStamp(vk::QueryPool *queryPool, uint32_t query, VkPipelineStageFlagBits2 stage)
1645 	    : queryPool(queryPool)
1646 	    , query(query)
1647 	    , stage(stage)
1648 	{
1649 	}
1650 
execute(vk::CommandBuffer::ExecutionState & executionState)1651 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1652 	{
1653 		if(stage & ~(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT))
1654 		{
1655 			// The `top of pipe` and `draw indirect` stages are handled in command buffer processing so a timestamp write
1656 			// done in those stages can just be done here without any additional synchronization.
1657 			// Everything else is deferred to the Renderer; we will treat those stages all as if they were
1658 			// `bottom of pipe`.
1659 			//
1660 			// FIXME(chrisforbes): once Marl is integrated, do this in a task so we don't have to stall here.
1661 			executionState.renderer->synchronize();
1662 		}
1663 
1664 		// "the timestamp uses N consecutive query indices in the query pool (starting at `query`) where
1665 		//  N is the number of bits set in the view mask of the subpass the command is executed in."
1666 		for(uint32_t i = 0; i < executionState.viewCount(); i++)
1667 		{
1668 			queryPool->writeTimestamp(query + i);
1669 		}
1670 	}
1671 
description()1672 	std::string description() override { return "vkCmdWriteTimeStamp()"; }
1673 
1674 private:
1675 	vk::QueryPool *const queryPool;
1676 	const uint32_t query;
1677 	const VkPipelineStageFlagBits2 stage;
1678 };
1679 
1680 class CmdCopyQueryPoolResults : public vk::CommandBuffer::Command
1681 {
1682 public:
CmdCopyQueryPoolResults(const vk::QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,vk::Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1683 	CmdCopyQueryPoolResults(const vk::QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1684 	                        vk::Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1685 	    : queryPool(queryPool)
1686 	    , firstQuery(firstQuery)
1687 	    , queryCount(queryCount)
1688 	    , dstBuffer(dstBuffer)
1689 	    , dstOffset(dstOffset)
1690 	    , stride(stride)
1691 	    , flags(flags)
1692 	{
1693 	}
1694 
execute(vk::CommandBuffer::ExecutionState & executionState)1695 	void execute(vk::CommandBuffer::ExecutionState &executionState) override
1696 	{
1697 		queryPool->getResults(firstQuery, queryCount, dstBuffer->getSize() - dstOffset,
1698 		                      dstBuffer->getOffsetPointer(dstOffset), stride, flags);
1699 	}
1700 
description()1701 	std::string description() override { return "vkCmdCopyQueryPoolResults()"; }
1702 
1703 private:
1704 	const vk::QueryPool *const queryPool;
1705 	const uint32_t firstQuery;
1706 	const uint32_t queryCount;
1707 	vk::Buffer *const dstBuffer;
1708 	const VkDeviceSize dstOffset;
1709 	const VkDeviceSize stride;
1710 	const VkQueryResultFlags flags;
1711 };
1712 
1713 }  // anonymous namespace
1714 
1715 namespace vk {
1716 
DynamicRendering(const VkRenderingInfo * pRenderingInfo)1717 DynamicRendering::DynamicRendering(const VkRenderingInfo *pRenderingInfo)
1718     : renderArea(pRenderingInfo->renderArea)
1719     , layerCount(pRenderingInfo->layerCount)
1720     , viewMask(pRenderingInfo->viewMask)
1721     , colorAttachmentCount(pRenderingInfo->colorAttachmentCount)
1722     , flags(pRenderingInfo->flags)
1723 {
1724 	if(colorAttachmentCount > 0)
1725 	{
1726 		for(uint32_t i = 0; i < colorAttachmentCount; ++i)
1727 		{
1728 			colorAttachments[i] = pRenderingInfo->pColorAttachments[i];
1729 		}
1730 	}
1731 
1732 	if(pRenderingInfo->pDepthAttachment)
1733 	{
1734 		depthAttachment = *pRenderingInfo->pDepthAttachment;
1735 	}
1736 
1737 	if(pRenderingInfo->pStencilAttachment)
1738 	{
1739 		stencilAttachment = *pRenderingInfo->pStencilAttachment;
1740 	}
1741 }
1742 
getAttachments(Attachments * attachments) const1743 void DynamicRendering::getAttachments(Attachments *attachments) const
1744 {
1745 	for(uint32_t i = 0; i < sw::MAX_COLOR_BUFFERS; ++i)
1746 	{
1747 		attachments->colorBuffer[i] =
1748 		    (i < colorAttachmentCount) ? vk::Cast(colorAttachments[i].imageView) : nullptr;
1749 	}
1750 	attachments->depthBuffer = vk::Cast(depthAttachment.imageView);
1751 	attachments->stencilBuffer = vk::Cast(stencilAttachment.imageView);
1752 }
1753 
CommandBuffer(Device * device,VkCommandBufferLevel pLevel)1754 CommandBuffer::CommandBuffer(Device *device, VkCommandBufferLevel pLevel)
1755     : device(device)
1756     , level(pLevel)
1757 {
1758 }
1759 
destroy(const VkAllocationCallbacks * pAllocator)1760 void CommandBuffer::destroy(const VkAllocationCallbacks *pAllocator)
1761 {
1762 }
1763 
resetState()1764 void CommandBuffer::resetState()
1765 {
1766 	// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
1767 	commands.clear();
1768 
1769 	state = INITIAL;
1770 }
1771 
begin(VkCommandBufferUsageFlags flags,const VkCommandBufferInheritanceInfo * pInheritanceInfo)1772 VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo *pInheritanceInfo)
1773 {
1774 	ASSERT((state != RECORDING) && (state != PENDING));
1775 
1776 	// Nothing interesting to do based on flags. We don't have any optimizations
1777 	// to apply for ONE_TIME_SUBMIT or (lack of) SIMULTANEOUS_USE. RENDER_PASS_CONTINUE
1778 	// must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
1779 	(void)flags;
1780 
1781 	// pInheritanceInfo merely contains optimization hints, so we currently ignore it
1782 
1783 	// "pInheritanceInfo is a pointer to a VkCommandBufferInheritanceInfo structure, used if commandBuffer is a
1784 	//  secondary command buffer. If this is a primary command buffer, then this value is ignored."
1785 	if(level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
1786 	{
1787 		if(pInheritanceInfo->queryFlags != 0)
1788 		{
1789 			// "If the inherited queries feature is not enabled, queryFlags must be 0"
1790 			UNSUPPORTED("VkPhysicalDeviceFeatures::inheritedQueries");
1791 		}
1792 	}
1793 
1794 	if(state != INITIAL)
1795 	{
1796 		// Implicit reset
1797 		resetState();
1798 	}
1799 
1800 	state = RECORDING;
1801 
1802 	return VK_SUCCESS;
1803 }
1804 
end()1805 VkResult CommandBuffer::end()
1806 {
1807 	ASSERT(state == RECORDING);
1808 
1809 	state = EXECUTABLE;
1810 
1811 	return VK_SUCCESS;
1812 }
1813 
reset(VkCommandPoolResetFlags flags)1814 VkResult CommandBuffer::reset(VkCommandPoolResetFlags flags)
1815 {
1816 	ASSERT(state != PENDING);
1817 
1818 	resetState();
1819 
1820 	return VK_SUCCESS;
1821 }
1822 
1823 template<typename T, typename... Args>
addCommand(Args &&...args)1824 void CommandBuffer::addCommand(Args &&...args)
1825 {
1826 	// FIXME (b/119409619): use an allocator here so we can control all memory allocations
1827 	commands.push_back(std::make_unique<T>(std::forward<Args>(args)...));
1828 }
1829 
beginRenderPass(RenderPass * renderPass,Framebuffer * framebuffer,VkRect2D renderArea,uint32_t clearValueCount,const VkClearValue * clearValues,VkSubpassContents contents,const VkRenderPassAttachmentBeginInfo * attachmentInfo)1830 void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
1831                                     uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents,
1832                                     const VkRenderPassAttachmentBeginInfo *attachmentInfo)
1833 {
1834 	ASSERT(state == RECORDING);
1835 
1836 	addCommand<::CmdBeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues, attachmentInfo);
1837 }
1838 
nextSubpass(VkSubpassContents contents)1839 void CommandBuffer::nextSubpass(VkSubpassContents contents)
1840 {
1841 	ASSERT(state == RECORDING);
1842 
1843 	addCommand<::CmdNextSubpass>();
1844 }
1845 
endRenderPass()1846 void CommandBuffer::endRenderPass()
1847 {
1848 	addCommand<::CmdEndRenderPass>();
1849 }
1850 
executeCommands(uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)1851 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
1852 {
1853 	ASSERT(state == RECORDING);
1854 
1855 	for(uint32_t i = 0; i < commandBufferCount; ++i)
1856 	{
1857 		addCommand<::CmdExecuteCommands>(vk::Cast(pCommandBuffers[i]));
1858 	}
1859 }
1860 
beginRendering(const VkRenderingInfo * pRenderingInfo)1861 void CommandBuffer::beginRendering(const VkRenderingInfo *pRenderingInfo)
1862 {
1863 	ASSERT(state == RECORDING);
1864 
1865 	addCommand<::CmdBeginRendering>(pRenderingInfo);
1866 }
1867 
endRendering()1868 void CommandBuffer::endRendering()
1869 {
1870 	ASSERT(state == RECORDING);
1871 
1872 	addCommand<::CmdEndRendering>();
1873 }
1874 
setDeviceMask(uint32_t deviceMask)1875 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
1876 {
1877 	// SwiftShader only has one device, so we ignore the device mask
1878 }
1879 
dispatchBase(uint32_t baseGroupX,uint32_t baseGroupY,uint32_t baseGroupZ,uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)1880 void CommandBuffer::dispatchBase(uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ,
1881                                  uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
1882 {
1883 	addCommand<::CmdDispatch>(baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
1884 }
1885 
pipelineBarrier(const VkDependencyInfo & pDependencyInfo)1886 void CommandBuffer::pipelineBarrier(const VkDependencyInfo &pDependencyInfo)
1887 {
1888 	addCommand<::CmdPipelineBarrier>();
1889 }
1890 
bindPipeline(VkPipelineBindPoint pipelineBindPoint,Pipeline * pipeline)1891 void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, Pipeline *pipeline)
1892 {
1893 	switch(pipelineBindPoint)
1894 	{
1895 	case VK_PIPELINE_BIND_POINT_COMPUTE:
1896 	case VK_PIPELINE_BIND_POINT_GRAPHICS:
1897 		addCommand<::CmdPipelineBind>(pipelineBindPoint, pipeline);
1898 		break;
1899 	default:
1900 		UNSUPPORTED("VkPipelineBindPoint %d", int(pipelineBindPoint));
1901 	}
1902 }
1903 
bindVertexBuffers(uint32_t firstBinding,uint32_t bindingCount,const VkBuffer * pBuffers,const VkDeviceSize * pOffsets,const VkDeviceSize * pSizes,const VkDeviceSize * pStrides)1904 void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
1905                                       const VkBuffer *pBuffers, const VkDeviceSize *pOffsets,
1906                                       const VkDeviceSize *pSizes, const VkDeviceSize *pStrides)
1907 {
1908 	for(uint32_t i = 0; i < bindingCount; ++i)
1909 	{
1910 		addCommand<::CmdVertexBufferBind>(i + firstBinding, vk::Cast(pBuffers[i]), pOffsets[i],
1911 		                                  pSizes ? pSizes[i] : 0,
1912 		                                  pStrides ? pStrides[i] : 0);
1913 	}
1914 }
1915 
beginQuery(QueryPool * queryPool,uint32_t query,VkQueryControlFlags flags)1916 void CommandBuffer::beginQuery(QueryPool *queryPool, uint32_t query, VkQueryControlFlags flags)
1917 {
1918 	addCommand<::CmdBeginQuery>(queryPool, query, flags);
1919 }
1920 
endQuery(QueryPool * queryPool,uint32_t query)1921 void CommandBuffer::endQuery(QueryPool *queryPool, uint32_t query)
1922 {
1923 	addCommand<::CmdEndQuery>(queryPool, query);
1924 }
1925 
resetQueryPool(QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount)1926 void CommandBuffer::resetQueryPool(QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount)
1927 {
1928 	addCommand<::CmdResetQueryPool>(queryPool, firstQuery, queryCount);
1929 }
1930 
writeTimestamp(VkPipelineStageFlags2 pipelineStage,QueryPool * queryPool,uint32_t query)1931 void CommandBuffer::writeTimestamp(VkPipelineStageFlags2 pipelineStage, QueryPool *queryPool, uint32_t query)
1932 {
1933 	addCommand<::CmdWriteTimeStamp>(queryPool, query, pipelineStage);
1934 }
1935 
copyQueryPoolResults(const QueryPool * queryPool,uint32_t firstQuery,uint32_t queryCount,Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1936 void CommandBuffer::copyQueryPoolResults(const QueryPool *queryPool, uint32_t firstQuery, uint32_t queryCount,
1937                                          Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags)
1938 {
1939 	addCommand<::CmdCopyQueryPoolResults>(queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
1940 }
1941 
pushConstants(PipelineLayout * layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues)1942 void CommandBuffer::pushConstants(PipelineLayout *layout, VkShaderStageFlags stageFlags,
1943                                   uint32_t offset, uint32_t size, const void *pValues)
1944 {
1945 	addCommand<::CmdSetPushConstants>(offset, size, pValues);
1946 }
1947 
setViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)1948 void CommandBuffer::setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports)
1949 {
1950 	if(firstViewport != 0 || viewportCount > 1)
1951 	{
1952 		UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1953 	}
1954 
1955 	for(uint32_t i = 0; i < viewportCount; i++)
1956 	{
1957 		addCommand<::CmdSetViewport>(pViewports[i], i + firstViewport);
1958 	}
1959 }
1960 
setScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)1961 void CommandBuffer::setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors)
1962 {
1963 	if(firstScissor != 0 || scissorCount > 1)
1964 	{
1965 		UNSUPPORTED("VkPhysicalDeviceFeatures::multiViewport");
1966 	}
1967 
1968 	for(uint32_t i = 0; i < scissorCount; i++)
1969 	{
1970 		addCommand<::CmdSetScissor>(pScissors[i], i + firstScissor);
1971 	}
1972 }
1973 
setLineWidth(float lineWidth)1974 void CommandBuffer::setLineWidth(float lineWidth)
1975 {
1976 	addCommand<::CmdSetLineWidth>(lineWidth);
1977 }
1978 
setDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)1979 void CommandBuffer::setDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor)
1980 {
1981 	addCommand<::CmdSetDepthBias>(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1982 }
1983 
setBlendConstants(const float blendConstants[4])1984 void CommandBuffer::setBlendConstants(const float blendConstants[4])
1985 {
1986 	addCommand<::CmdSetBlendConstants>(blendConstants);
1987 }
1988 
setDepthBounds(float minDepthBounds,float maxDepthBounds)1989 void CommandBuffer::setDepthBounds(float minDepthBounds, float maxDepthBounds)
1990 {
1991 	addCommand<::CmdSetDepthBounds>(minDepthBounds, maxDepthBounds);
1992 }
1993 
setStencilCompareMask(VkStencilFaceFlags faceMask,uint32_t compareMask)1994 void CommandBuffer::setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t compareMask)
1995 {
1996 	// faceMask must not be 0
1997 	ASSERT(faceMask != 0);
1998 
1999 	addCommand<::CmdSetStencilCompareMask>(faceMask, compareMask);
2000 }
2001 
setStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)2002 void CommandBuffer::setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask)
2003 {
2004 	// faceMask must not be 0
2005 	ASSERT(faceMask != 0);
2006 
2007 	addCommand<::CmdSetStencilWriteMask>(faceMask, writeMask);
2008 }
2009 
setStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)2010 void CommandBuffer::setStencilReference(VkStencilFaceFlags faceMask, uint32_t reference)
2011 {
2012 	// faceMask must not be 0
2013 	ASSERT(faceMask != 0);
2014 
2015 	addCommand<::CmdSetStencilReference>(faceMask, reference);
2016 }
2017 
setCullMode(VkCullModeFlags cullMode)2018 void CommandBuffer::setCullMode(VkCullModeFlags cullMode)
2019 {
2020 	addCommand<::CmdSetCullMode>(cullMode);
2021 }
2022 
setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)2023 void CommandBuffer::setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable)
2024 {
2025 	addCommand<::CmdSetDepthBoundsTestEnable>(depthBoundsTestEnable);
2026 }
2027 
setDepthCompareOp(VkCompareOp depthCompareOp)2028 void CommandBuffer::setDepthCompareOp(VkCompareOp depthCompareOp)
2029 {
2030 	addCommand<::CmdSetDepthCompareOp>(depthCompareOp);
2031 }
2032 
setDepthTestEnable(VkBool32 depthTestEnable)2033 void CommandBuffer::setDepthTestEnable(VkBool32 depthTestEnable)
2034 {
2035 	addCommand<::CmdSetDepthTestEnable>(depthTestEnable);
2036 }
2037 
setDepthWriteEnable(VkBool32 depthWriteEnable)2038 void CommandBuffer::setDepthWriteEnable(VkBool32 depthWriteEnable)
2039 {
2040 	addCommand<::CmdSetDepthWriteEnable>(depthWriteEnable);
2041 }
2042 
setFrontFace(VkFrontFace frontFace)2043 void CommandBuffer::setFrontFace(VkFrontFace frontFace)
2044 {
2045 	addCommand<::CmdSetFrontFace>(frontFace);
2046 }
2047 
setPrimitiveTopology(VkPrimitiveTopology primitiveTopology)2048 void CommandBuffer::setPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
2049 {
2050 	addCommand<::CmdSetPrimitiveTopology>(primitiveTopology);
2051 }
2052 
setScissorWithCount(uint32_t scissorCount,const VkRect2D * pScissors)2053 void CommandBuffer::setScissorWithCount(uint32_t scissorCount, const VkRect2D *pScissors)
2054 {
2055 	addCommand<::CmdSetScissorWithCount>(scissorCount, pScissors);
2056 }
2057 
setStencilOp(VkStencilFaceFlags faceMask,VkStencilOp failOp,VkStencilOp passOp,VkStencilOp depthFailOp,VkCompareOp compareOp)2058 void CommandBuffer::setStencilOp(VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp)
2059 {
2060 	addCommand<::CmdSetStencilOp>(faceMask, failOp, passOp, depthFailOp, compareOp);
2061 }
2062 
setStencilTestEnable(VkBool32 stencilTestEnable)2063 void CommandBuffer::setStencilTestEnable(VkBool32 stencilTestEnable)
2064 {
2065 	addCommand<::CmdSetStencilTestEnable>(stencilTestEnable);
2066 }
2067 
setViewportWithCount(uint32_t viewportCount,const VkViewport * pViewports)2068 void CommandBuffer::setViewportWithCount(uint32_t viewportCount, const VkViewport *pViewports)
2069 {
2070 	addCommand<::CmdSetViewportWithCount>(viewportCount, pViewports);
2071 }
2072 
setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)2073 void CommandBuffer::setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable)
2074 {
2075 	addCommand<::CmdSetRasterizerDiscardEnable>(rasterizerDiscardEnable);
2076 }
2077 
setDepthBiasEnable(VkBool32 depthBiasEnable)2078 void CommandBuffer::setDepthBiasEnable(VkBool32 depthBiasEnable)
2079 {
2080 	addCommand<::CmdSetDepthBiasEnable>(depthBiasEnable);
2081 }
2082 
setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)2083 void CommandBuffer::setPrimitiveRestartEnable(VkBool32 primitiveRestartEnable)
2084 {
2085 	addCommand<::CmdSetPrimitiveRestartEnable>(primitiveRestartEnable);
2086 }
2087 
bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,const PipelineLayout * pipelineLayout,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets)2088 void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, const PipelineLayout *pipelineLayout,
2089                                        uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
2090                                        uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets)
2091 {
2092 	ASSERT(state == RECORDING);
2093 
2094 	auto firstDynamicOffset = (dynamicOffsetCount != 0) ? pipelineLayout->getDynamicOffsetIndex(firstSet, 0) : 0;
2095 
2096 	addCommand<::CmdBindDescriptorSets>(
2097 	    pipelineBindPoint, firstSet, descriptorSetCount, pDescriptorSets,
2098 	    firstDynamicOffset, dynamicOffsetCount, pDynamicOffsets);
2099 }
2100 
bindIndexBuffer(Buffer * buffer,VkDeviceSize offset,VkIndexType indexType)2101 void CommandBuffer::bindIndexBuffer(Buffer *buffer, VkDeviceSize offset, VkIndexType indexType)
2102 {
2103 	addCommand<::CmdIndexBufferBind>(buffer, offset, indexType);
2104 }
2105 
dispatch(uint32_t groupCountX,uint32_t groupCountY,uint32_t groupCountZ)2106 void CommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
2107 {
2108 	addCommand<::CmdDispatch>(0, 0, 0, groupCountX, groupCountY, groupCountZ);
2109 }
2110 
dispatchIndirect(Buffer * buffer,VkDeviceSize offset)2111 void CommandBuffer::dispatchIndirect(Buffer *buffer, VkDeviceSize offset)
2112 {
2113 	addCommand<::CmdDispatchIndirect>(buffer, offset);
2114 }
2115 
copyBuffer(const VkCopyBufferInfo2 & copyBufferInfo)2116 void CommandBuffer::copyBuffer(const VkCopyBufferInfo2 &copyBufferInfo)
2117 {
2118 	ASSERT(state == RECORDING);
2119 
2120 	for(uint32_t i = 0; i < copyBufferInfo.regionCount; i++)
2121 	{
2122 		addCommand<::CmdCopyBuffer>(
2123 		    vk::Cast(copyBufferInfo.srcBuffer),
2124 		    vk::Cast(copyBufferInfo.dstBuffer),
2125 		    copyBufferInfo.pRegions[i]);
2126 	}
2127 }
2128 
copyImage(const VkCopyImageInfo2 & copyImageInfo)2129 void CommandBuffer::copyImage(const VkCopyImageInfo2 &copyImageInfo)
2130 {
2131 	ASSERT(state == RECORDING);
2132 	ASSERT(copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2133 	       copyImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2134 	ASSERT(copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2135 	       copyImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2136 
2137 	for(uint32_t i = 0; i < copyImageInfo.regionCount; i++)
2138 	{
2139 		addCommand<::CmdCopyImage>(
2140 		    vk::Cast(copyImageInfo.srcImage),
2141 		    vk::Cast(copyImageInfo.dstImage),
2142 		    copyImageInfo.pRegions[i]);
2143 	}
2144 }
2145 
blitImage(const VkBlitImageInfo2 & blitImageInfo)2146 void CommandBuffer::blitImage(const VkBlitImageInfo2 &blitImageInfo)
2147 {
2148 	ASSERT(state == RECORDING);
2149 	ASSERT(blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2150 	       blitImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2151 	ASSERT(blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2152 	       blitImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2153 
2154 	for(uint32_t i = 0; i < blitImageInfo.regionCount; i++)
2155 	{
2156 		addCommand<::CmdBlitImage>(
2157 		    vk::Cast(blitImageInfo.srcImage),
2158 		    vk::Cast(blitImageInfo.dstImage),
2159 		    blitImageInfo.pRegions[i],
2160 		    blitImageInfo.filter);
2161 	}
2162 }
2163 
copyBufferToImage(const VkCopyBufferToImageInfo2 & copyBufferToImageInfo)2164 void CommandBuffer::copyBufferToImage(const VkCopyBufferToImageInfo2 &copyBufferToImageInfo)
2165 {
2166 	ASSERT(state == RECORDING);
2167 
2168 	for(uint32_t i = 0; i < copyBufferToImageInfo.regionCount; i++)
2169 	{
2170 		addCommand<::CmdCopyBufferToImage>(
2171 		    vk::Cast(copyBufferToImageInfo.srcBuffer),
2172 		    vk::Cast(copyBufferToImageInfo.dstImage),
2173 		    copyBufferToImageInfo.pRegions[i]);
2174 	}
2175 }
2176 
copyImageToBuffer(const VkCopyImageToBufferInfo2 & copyImageToBufferInfo)2177 void CommandBuffer::copyImageToBuffer(const VkCopyImageToBufferInfo2 &copyImageToBufferInfo)
2178 {
2179 	ASSERT(state == RECORDING);
2180 	ASSERT(copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2181 	       copyImageToBufferInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2182 
2183 	for(uint32_t i = 0; i < copyImageToBufferInfo.regionCount; i++)
2184 	{
2185 		addCommand<::CmdCopyImageToBuffer>(
2186 		    vk::Cast(copyImageToBufferInfo.srcImage),
2187 		    vk::Cast(copyImageToBufferInfo.dstBuffer),
2188 		    copyImageToBufferInfo.pRegions[i]);
2189 	}
2190 }
2191 
updateBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)2192 void CommandBuffer::updateBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData)
2193 {
2194 	ASSERT(state == RECORDING);
2195 
2196 	addCommand<::CmdUpdateBuffer>(dstBuffer, dstOffset, dataSize, reinterpret_cast<const uint8_t *>(pData));
2197 }
2198 
fillBuffer(Buffer * dstBuffer,VkDeviceSize dstOffset,VkDeviceSize size,uint32_t data)2199 void CommandBuffer::fillBuffer(Buffer *dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data)
2200 {
2201 	ASSERT(state == RECORDING);
2202 
2203 	addCommand<::CmdFillBuffer>(dstBuffer, dstOffset, size, data);
2204 }
2205 
clearColorImage(Image * image,VkImageLayout imageLayout,const VkClearColorValue * pColor,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)2206 void CommandBuffer::clearColorImage(Image *image, VkImageLayout imageLayout, const VkClearColorValue *pColor,
2207                                     uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
2208 {
2209 	ASSERT(state == RECORDING);
2210 
2211 	for(uint32_t i = 0; i < rangeCount; i++)
2212 	{
2213 		addCommand<::CmdClearColorImage>(image, *pColor, pRanges[i]);
2214 	}
2215 }
2216 
clearDepthStencilImage(Image * image,VkImageLayout imageLayout,const VkClearDepthStencilValue * pDepthStencil,uint32_t rangeCount,const VkImageSubresourceRange * pRanges)2217 void CommandBuffer::clearDepthStencilImage(Image *image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pDepthStencil,
2218                                            uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
2219 {
2220 	ASSERT(state == RECORDING);
2221 
2222 	for(uint32_t i = 0; i < rangeCount; i++)
2223 	{
2224 		addCommand<::CmdClearDepthStencilImage>(image, *pDepthStencil, pRanges[i]);
2225 	}
2226 }
2227 
clearAttachments(uint32_t attachmentCount,const VkClearAttachment * pAttachments,uint32_t rectCount,const VkClearRect * pRects)2228 void CommandBuffer::clearAttachments(uint32_t attachmentCount, const VkClearAttachment *pAttachments,
2229                                      uint32_t rectCount, const VkClearRect *pRects)
2230 {
2231 	ASSERT(state == RECORDING);
2232 
2233 	for(uint32_t i = 0; i < attachmentCount; i++)
2234 	{
2235 		for(uint32_t j = 0; j < rectCount; j++)
2236 		{
2237 			addCommand<::CmdClearAttachment>(pAttachments[i], pRects[j]);
2238 		}
2239 	}
2240 }
2241 
resolveImage(const VkResolveImageInfo2 & resolveImageInfo)2242 void CommandBuffer::resolveImage(const VkResolveImageInfo2 &resolveImageInfo)
2243 {
2244 	ASSERT(state == RECORDING);
2245 	ASSERT(resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
2246 	       resolveImageInfo.srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2247 	ASSERT(resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
2248 	       resolveImageInfo.dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
2249 
2250 	for(uint32_t i = 0; i < resolveImageInfo.regionCount; i++)
2251 	{
2252 		addCommand<::CmdResolveImage>(
2253 		    vk::Cast(resolveImageInfo.srcImage),
2254 		    vk::Cast(resolveImageInfo.dstImage),
2255 		    resolveImageInfo.pRegions[i]);
2256 	}
2257 }
2258 
setEvent(Event * event,const VkDependencyInfo & pDependencyInfo)2259 void CommandBuffer::setEvent(Event *event, const VkDependencyInfo &pDependencyInfo)
2260 {
2261 	ASSERT(state == RECORDING);
2262 
2263 	// TODO(b/117835459): We currently ignore the flags and signal the event at the last stage
2264 
2265 	addCommand<::CmdSignalEvent>(event);
2266 }
2267 
resetEvent(Event * event,VkPipelineStageFlags2 stageMask)2268 void CommandBuffer::resetEvent(Event *event, VkPipelineStageFlags2 stageMask)
2269 {
2270 	ASSERT(state == RECORDING);
2271 
2272 	addCommand<::CmdResetEvent>(event, stageMask);
2273 }
2274 
waitEvents(uint32_t eventCount,const VkEvent * pEvents,const VkDependencyInfo & pDependencyInfo)2275 void CommandBuffer::waitEvents(uint32_t eventCount, const VkEvent *pEvents, const VkDependencyInfo &pDependencyInfo)
2276 {
2277 	ASSERT(state == RECORDING);
2278 
2279 	// TODO(b/117835459): Since we always do a full barrier, all memory barrier related arguments are ignored
2280 
2281 	// Note: srcStageMask and dstStageMask are currently ignored
2282 	for(uint32_t i = 0; i < eventCount; i++)
2283 	{
2284 		addCommand<::CmdWaitEvent>(vk::Cast(pEvents[i]));
2285 	}
2286 }
2287 
draw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)2288 void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
2289 {
2290 	addCommand<::CmdDraw>(vertexCount, instanceCount, firstVertex, firstInstance);
2291 }
2292 
drawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)2293 void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
2294 {
2295 	addCommand<::CmdDrawIndexed>(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
2296 }
2297 
drawIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)2298 void CommandBuffer::drawIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
2299 {
2300 	addCommand<::CmdDrawIndirect>(buffer, offset, drawCount, stride);
2301 }
2302 
drawIndexedIndirect(Buffer * buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)2303 void CommandBuffer::drawIndexedIndirect(Buffer *buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride)
2304 {
2305 	addCommand<::CmdDrawIndexedIndirect>(buffer, offset, drawCount, stride);
2306 }
2307 
beginDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)2308 void CommandBuffer::beginDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
2309 {
2310 	// Optional debug label region
2311 }
2312 
endDebugUtilsLabel()2313 void CommandBuffer::endDebugUtilsLabel()
2314 {
2315 	// Close debug label region opened with beginDebugUtilsLabel()
2316 }
2317 
insertDebugUtilsLabel(const VkDebugUtilsLabelEXT * pLabelInfo)2318 void CommandBuffer::insertDebugUtilsLabel(const VkDebugUtilsLabelEXT *pLabelInfo)
2319 {
2320 	// Optional single debug label
2321 }
2322 
submit(CommandBuffer::ExecutionState & executionState)2323 void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
2324 {
2325 	// Perform recorded work
2326 	state = PENDING;
2327 
2328 	for(auto &command : commands)
2329 	{
2330 		command->execute(executionState);
2331 	}
2332 
2333 	// After work is completed
2334 	state = EXECUTABLE;
2335 }
2336 
submitSecondary(CommandBuffer::ExecutionState & executionState) const2337 void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState &executionState) const
2338 {
2339 	for(auto &command : commands)
2340 	{
2341 		command->execute(executionState);
2342 	}
2343 }
2344 
bindAttachments(Attachments * attachments)2345 void CommandBuffer::ExecutionState::bindAttachments(Attachments *attachments)
2346 {
2347 	// Binds all the attachments for the current subpass
2348 	// Ideally this would be performed by BeginRenderPass and NextSubpass, but
2349 	// there is too much stomping of the renderer's state by setContext() in
2350 	// draws.
2351 
2352 	if(renderPass)
2353 	{
2354 		const auto &subpass = renderPass->getSubpass(subpassIndex);
2355 
2356 		for(auto i = 0u; i < subpass.colorAttachmentCount; i++)
2357 		{
2358 			auto attachmentReference = subpass.pColorAttachments[i];
2359 			if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
2360 			{
2361 				attachments->colorBuffer[i] = renderPassFramebuffer->getAttachment(attachmentReference.attachment);
2362 			}
2363 		}
2364 
2365 		auto attachmentReference = subpass.pDepthStencilAttachment;
2366 		if(attachmentReference && attachmentReference->attachment != VK_ATTACHMENT_UNUSED)
2367 		{
2368 			auto *attachment = renderPassFramebuffer->getAttachment(attachmentReference->attachment);
2369 			if(attachment->hasDepthAspect())
2370 			{
2371 				attachments->depthBuffer = attachment;
2372 			}
2373 			if(attachment->hasStencilAspect())
2374 			{
2375 				attachments->stencilBuffer = attachment;
2376 			}
2377 		}
2378 	}
2379 	else if(dynamicRendering)
2380 	{
2381 		dynamicRendering->getAttachments(attachments);
2382 	}
2383 }
2384 
getRenderArea() const2385 VkRect2D CommandBuffer::ExecutionState::getRenderArea() const
2386 {
2387 	VkRect2D renderArea = {};
2388 
2389 	if(renderPassFramebuffer)
2390 	{
2391 		renderArea.extent = renderPassFramebuffer->getExtent();
2392 	}
2393 	else if(dynamicRendering)
2394 	{
2395 		renderArea = dynamicRendering->getRenderArea();
2396 	}
2397 
2398 	return renderArea;
2399 }
2400 
2401 // The layer mask is the same as the view mask when multiview is enabled,
2402 // or 1 if multiview is disabled.
getLayerMask() const2403 uint32_t CommandBuffer::ExecutionState::getLayerMask() const
2404 {
2405 	uint32_t layerMask = 1;
2406 
2407 	if(renderPass)
2408 	{
2409 		layerMask = renderPass->getViewMask(subpassIndex);
2410 	}
2411 	else if(dynamicRendering)
2412 	{
2413 		layerMask = dynamicRendering->getViewMask();
2414 	}
2415 
2416 	return sw::max(layerMask, 1u);
2417 }
2418 
2419 // Returns the number of bits set in the view mask, or 1 if multiview is disabled.
viewCount() const2420 uint32_t CommandBuffer::ExecutionState::viewCount() const
2421 {
2422 	return static_cast<uint32_t>(std::bitset<32>(getLayerMask()).count());
2423 }
2424 
2425 }  // namespace vk
2426