Basic commands required to draw a simple triangle test
This cl adds the code needed to record and submit the minimal
subset of commands required to run a simple triangle example.
The commands themselves are still unimplemented.
Bug b/116336664
Change-Id: Id0109980225a64a2bb3599a89a5495091926c635
Reviewed-on: https://swiftshader-review.googlesource.com/c/22168
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Corentin Wallez <cwallez@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index 220d232..45f9199 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -17,30 +17,169 @@
namespace vk
{
+class CommandBuffer::Command
+{
+public:
+ // FIXME (b/119421344): change the commandBuffer argument to a CommandBuffer state
+ virtual void play(CommandBuffer* commandBuffer) = 0;
+ virtual ~Command() {}
+};
+
+class BeginRenderPass : public CommandBuffer::Command
+{
+public:
+ BeginRenderPass(VkRenderPass pRenderPass, VkFramebuffer pFramebuffer, VkRect2D pRenderArea,
+ uint32_t pClearValueCount, const VkClearValue* pClearValues) :
+ renderPass(pRenderPass), framebuffer(pFramebuffer), renderArea(pRenderArea),
+ clearValueCount(pClearValueCount)
+ {
+ // FIXME (b/119409619): use an allocator here so we can control all memory allocations
+ clearValues = new VkClearValue[clearValueCount];
+ memcpy(clearValues, pClearValues, clearValueCount * sizeof(VkClearValue));
+ }
+
+ ~BeginRenderPass() override
+ {
+ delete clearValues;
+ }
+
+protected:
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+private:
+ VkRenderPass renderPass;
+ VkFramebuffer framebuffer;
+ VkRect2D renderArea;
+ uint32_t clearValueCount;
+ VkClearValue* clearValues;
+};
+
+class EndRenderPass : public CommandBuffer::Command
+{
+public:
+ EndRenderPass()
+ {
+ }
+
+protected:
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+private:
+};
+
+class PipelineBind : public CommandBuffer::Command
+{
+public:
+ PipelineBind(VkPipelineBindPoint pPipelineBindPoint, VkPipeline pPipeline) :
+ pipelineBindPoint(pPipelineBindPoint), pipeline(pPipeline)
+ {
+ }
+
+protected:
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+private:
+ VkPipelineBindPoint pipelineBindPoint;
+ VkPipeline pipeline;
+};
+
+struct VertexBufferBind : public CommandBuffer::Command
+{
+ VertexBufferBind(uint32_t pBinding, const VkBuffer pBuffer, const VkDeviceSize pOffset) :
+ binding(pBinding), buffer(pBuffer), offset(pOffset)
+ {
+ }
+
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+ uint32_t binding;
+ const VkBuffer buffer;
+ const VkDeviceSize offset;
+};
+
+struct Draw : public CommandBuffer::Command
+{
+ Draw(uint32_t pVertexCount) : vertexCount(pVertexCount)
+ {
+ }
+
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+ uint32_t vertexCount;
+};
+
+struct ImageToBufferCopy : public CommandBuffer::Command
+{
+ ImageToBufferCopy(VkImage pSrcImage, VkBuffer pDstBuffer, const VkBufferImageCopy& pRegion) :
+ srcImage(pSrcImage), dstBuffer(pDstBuffer), region(pRegion)
+ {
+ }
+
+ void play(CommandBuffer* commandBuffer)
+ {
+ UNIMPLEMENTED();
+ }
+
+private:
+ VkImage srcImage;
+ VkBuffer dstBuffer;
+ const VkBufferImageCopy region;
+};
+
CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) : level(pLevel)
{
+ // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
+ commands = new std::vector<std::unique_ptr<Command> >();
+
pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS] = VK_NULL_HANDLE;
pipelines[VK_PIPELINE_BIND_POINT_COMPUTE] = VK_NULL_HANDLE;
}
void CommandBuffer::destroy(const VkAllocationCallbacks* pAllocator)
{
+ deleteCommands();
+}
+
+void CommandBuffer::deleteCommands()
+{
+ // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
+ delete commands;
}
VkResult CommandBuffer::begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo* pInheritanceInfo)
{
+ ASSERT((state != RECORDING) && (state != PENDING));
+
+ if((flags != VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) || pInheritanceInfo)
+ {
+ UNIMPLEMENTED();
+ }
+
state = RECORDING;
- UNIMPLEMENTED();
-
return VK_SUCCESS;
}
VkResult CommandBuffer::end()
{
- state = EXECUTABLE;
+ ASSERT(state == RECORDING);
- UNIMPLEMENTED();
+ state = EXECUTABLE;
return VK_SUCCESS;
}
@@ -49,18 +188,24 @@
{
ASSERT(state != PENDING);
- UNIMPLEMENTED();
+ deleteCommands();
- // FIXME: put command buffer back to the initial state
state = INITIAL;
return VK_SUCCESS;
}
void CommandBuffer::beginRenderPass(VkRenderPass renderPass, VkFramebuffer framebuffer, VkRect2D renderArea,
- uint32_t clearValueCount, const VkClearValue* pClearValues, VkSubpassContents contents)
+ uint32_t clearValueCount, const VkClearValue* clearValues, VkSubpassContents contents)
{
- UNIMPLEMENTED();
+ ASSERT(state == RECORDING);
+
+ if(contents != VK_SUBPASS_CONTENTS_INLINE)
+ {
+ UNIMPLEMENTED();
+ }
+
+ commands->push_back(std::make_unique<BeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues));
}
void CommandBuffer::nextSubpass(VkSubpassContents contents)
@@ -70,7 +215,7 @@
void CommandBuffer::endRenderPass()
{
- UNIMPLEMENTED();
+ commands->push_back(std::make_unique<EndRenderPass>());
}
void CommandBuffer::executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers)
@@ -100,7 +245,12 @@
void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline)
{
- pipelines[pipelineBindPoint] = pipeline;
+ if(pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS)
+ {
+ UNIMPLEMENTED();
+ }
+
+ commands->push_back(std::make_unique<PipelineBind>(pipelineBindPoint, pipeline));
}
void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, uint32_t bindingCount,
@@ -108,8 +258,7 @@
{
for(uint32_t i = firstBinding; i < (firstBinding + bindingCount); ++i)
{
- vertexInputBindings[i].buffer = pBuffers[i];
- vertexInputBindings[i].offset = pOffsets[i];
+ commands->push_back(std::make_unique<VertexBufferBind>(i, pBuffers[i], pOffsets[i]));
}
}
@@ -276,7 +425,12 @@
void CommandBuffer::copyImageToBuffer(VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer,
uint32_t regionCount, const VkBufferImageCopy* pRegions)
{
- UNIMPLEMENTED();
+ ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+
+ for(uint32_t i = 0; i < regionCount; i++)
+ {
+ commands->push_back(std::make_unique<ImageToBufferCopy>(srcImage, dstBuffer, pRegions[i]));
+ }
}
void CommandBuffer::updateBuffer(VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
@@ -333,7 +487,12 @@
void CommandBuffer::draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance)
{
- UNIMPLEMENTED();
+ if(instanceCount > 1 || firstVertex != 0 || firstInstance != 0)
+ {
+ UNIMPLEMENTED();
+ }
+
+ commands->push_back(std::make_unique<Draw>(vertexCount));
}
void CommandBuffer::drawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
@@ -356,7 +515,10 @@
// Perform recorded work
state = PENDING;
- UNIMPLEMENTED();
+ for(auto& command : *commands)
+ {
+ command->play(this);
+ }
// After work is completed
state = EXECUTABLE;