vkCmdExecuteCommands implementation

Basic support for executing secondary command buffers, without
support for any inheritance features.

Bug b/118619338

Change-Id: Ie3453018a45a722ecfa4f1acd20c95442fbb3d9b
Tests: dEQP-VK.memory.pipeline_barrier.host_write_transfer_src.*
Tests: dEQP-VK.api.command_buffers.allocate_single_secondary
Tests: dEQP-VK.api.command_buffers.allocate_many_secondary
Tests: dEQP-VK.api.command_buffers.trim_command_pool_secondary
Tests: dEQP-VK.api.command_buffers.record_single_secondary
Tests: dEQP-VK.api.command_buffers.record_many_secondary
Tests: dEQP-VK.api.command_buffers.submit_twice_secondary
Tests: dEQP-VK.api.command_buffers.record_one_time_submit_secondary
Tests: dEQP-VK.api.command_buffers.secondary_execute
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27493
Tested-by: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index ff1dbd6..06e1c1b 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -109,6 +109,23 @@
 private:
 };
 
+class ExecuteCommands : public CommandBuffer::Command
+{
+public:
+	ExecuteCommands(const VkCommandBuffer& commandBuffer) : commandBuffer(commandBuffer)
+	{
+	}
+
+protected:
+	void play(CommandBuffer::ExecutionState& executionState) override
+	{
+		Cast(commandBuffer)->submitSecondary(executionState);
+	}
+
+private:
+	const VkCommandBuffer commandBuffer;
+};
+
 class PipelineBind : public CommandBuffer::Command
 {
 public:
@@ -660,10 +677,7 @@
 	// must also provide a non-null pInheritanceInfo, which we don't implement yet, but is caught below.
 	(void) flags;
 
-	if(pInheritanceInfo)
-	{
-		UNIMPLEMENTED("pInheritanceInfo");
-	}
+	// pInheritanceInfo merely contains optimization hints, so we currently ignore it
 
 	if(state != INITIAL)
 	{
@@ -727,7 +741,12 @@
 
 void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
 {
-	UNIMPLEMENTED("executeCommands");
+	ASSERT(state == RECORDING);
+
+	for(uint32_t i = 0; i < commandBufferCount; ++i)
+	{
+		addCommand<ExecuteCommands>(pCommandBuffers[i]);
+	}
 }
 
 void CommandBuffer::setDeviceMask(uint32_t deviceMask)
@@ -1102,4 +1121,12 @@
 	state = EXECUTABLE;
 }
 
+void CommandBuffer::submitSecondary(CommandBuffer::ExecutionState& executionState) const
+{
+	for(auto& command : *commands)
+	{
+		command->play(executionState);
+	}
+}
+
 } // namespace vk
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp
index 66f9de0..4fbbe35 100644
--- a/src/Vulkan/VkCommandBuffer.hpp
+++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -144,6 +144,7 @@
 	};
 
 	void submit(CommandBuffer::ExecutionState& executionState);
+	void submitSecondary(CommandBuffer::ExecutionState& executionState) const;
 
 	class Command;
 private: