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;
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp index abcf241..814c603 100644 --- a/src/Vulkan/VkCommandBuffer.hpp +++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -17,6 +17,8 @@ #include "VkConfig.h" #include "VkObject.hpp" +#include <memory> +#include <vector> namespace vk { @@ -109,7 +111,10 @@ void submit(); + class Command; private: + void deleteCommands(); + enum State { INITIAL, RECORDING, EXECUTABLE, PENDING, INVALID }; State state = INITIAL; VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; @@ -121,6 +126,9 @@ VkDeviceSize offset; }; VertexInputBindings vertexInputBindings[MAX_VERTEX_INPUT_BINDINGS]; + + // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations + std::vector<std::unique_ptr<Command>>* commands; }; using DispatchableCommandBuffer = DispatchableObject<CommandBuffer, VkCommandBuffer>;
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp index 537849c..f0978cf 100644 --- a/src/Vulkan/VkQueue.cpp +++ b/src/Vulkan/VkQueue.cpp
@@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "VkCommandBuffer.hpp" #include "VkQueue.hpp" +#include "VkSemaphore.hpp" namespace vk { @@ -21,4 +23,31 @@ { } +void Queue::submit(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) +{ + if(fence != VK_NULL_HANDLE) + { + UNIMPLEMENTED(); + } + + for(uint32_t i = 0; i < submitCount; i++) + { + auto& submitInfo = pSubmits[i]; + for(uint32_t j = 0; j < submitInfo.waitSemaphoreCount; j++) + { + vk::Cast(submitInfo.pWaitSemaphores[j])->wait(submitInfo.pWaitDstStageMask[j]); + } + + for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++) + { + vk::Cast(submitInfo.pCommandBuffers[j])->submit(); + } + + for(uint32_t j = 0; j < submitInfo.signalSemaphoreCount; j++) + { + vk::Cast(submitInfo.pSignalSemaphores[j])->signal(); + } + } +} + } // namespace vk \ No newline at end of file
diff --git a/src/Vulkan/VkQueue.hpp b/src/Vulkan/VkQueue.hpp index 49e2604..739d7fd 100644 --- a/src/Vulkan/VkQueue.hpp +++ b/src/Vulkan/VkQueue.hpp
@@ -34,6 +34,8 @@ return reinterpret_cast<VkQueue>(this); } + void submit(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); + private: uint32_t familyIndex = 0; float priority = 0.0f;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index 249afe4..9d23ec8 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -427,8 +427,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) { - TRACE("()"); - UNIMPLEMENTED(); + TRACE("(VkQueue queue = 0x%X, uint32_t submitCount = %d, const VkSubmitInfo* pSubmits = 0x%X, VkFence fence = 0x%X)", + queue, submitCount, pSubmits, fence); + + vk::Cast(queue)->submit(submitCount, pSubmits, fence); + return VK_SUCCESS; }