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