vkCmdDraw implementation Piped all the information from the vertex buffers and the pipeline to the renderer to perform a draw. In order for the renderer and the context to have proper lifetimes, they both reside in the Queue object for now. Bug b/118619338 Change-Id: Ifa03acd13ceb065a856b50f2cffadd4ee6b9a163 Reviewed-on: https://swiftshader-review.googlesource.com/c/23111 Reviewed-by: Corentin Wallez <cwallez@google.com> Reviewed-by: Chris Forbes <chrisforbes@google.com> Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp index d2a50af..6be7df8 100644 --- a/src/Vulkan/VkCommandBuffer.cpp +++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -13,9 +13,12 @@ // limitations under the License. #include "VkCommandBuffer.hpp" +#include "VkBuffer.hpp" #include "VkFramebuffer.hpp" #include "VkImage.hpp" +#include "VkPipeline.hpp" #include "VkRenderpass.hpp" +#include "Device/Renderer.hpp" #include <cstring> @@ -123,7 +126,23 @@ void play(CommandBuffer::ExecutionState& executionState) { - UNIMPLEMENTED(); + GraphicsPipeline* pipeline = static_cast<GraphicsPipeline*>( + Cast(executionState.pipelines[VK_PIPELINE_BIND_POINT_GRAPHICS])); + + sw::Context context = pipeline->getContext(); + for(uint32_t i = 0; i < MAX_VERTEX_INPUT_BINDINGS; i++) + { + const auto& vertexInput = executionState.vertexInputBindings[i]; + Buffer* buffer = Cast(vertexInput.buffer); + context.input[i].buffer = buffer ? buffer->map(vertexInput.offset) : nullptr; + } + + executionState.renderer->setContext(context); + executionState.renderer->setScissor(pipeline->getScissor()); + executionState.renderer->setViewport(pipeline->getViewport()); + executionState.renderer->setBlendConstant(pipeline->getBlendConstants()); + + executionState.renderer->draw(context.drawType, 0, pipeline->computePrimitiveCount(vertexCount)); } uint32_t vertexCount;
diff --git a/src/Vulkan/VkCommandBuffer.hpp b/src/Vulkan/VkCommandBuffer.hpp index c90dd1d..3a256c4 100644 --- a/src/Vulkan/VkCommandBuffer.hpp +++ b/src/Vulkan/VkCommandBuffer.hpp
@@ -20,6 +20,11 @@ #include <memory> #include <vector> +namespace sw +{ + class Renderer; +} + namespace vk { @@ -112,6 +117,7 @@ // TODO(sugoi): Move ExecutionState out of CommandBuffer (possibly into Device) struct ExecutionState { + sw::Renderer* renderer = nullptr; VkRenderPass renderpass = VK_NULL_HANDLE; VkPipeline pipelines[VK_PIPELINE_BIND_POINT_RANGE_SIZE] = {};
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp index 59ff864..ec472f7 100644 --- a/src/Vulkan/VkPipeline.cpp +++ b/src/Vulkan/VkPipeline.cpp
@@ -383,6 +383,29 @@ fragmentRoutine = Cast(pCreateInfo->pStages[1].module)->compile(pAllocator); } +uint32_t GraphicsPipeline::computePrimitiveCount(uint32_t vertexCount) const +{ + switch(context.drawType) + { + case sw::DRAW_POINTLIST: + return vertexCount; + case sw::DRAW_LINELIST: + return vertexCount / 2; + case sw::DRAW_LINESTRIP: + return vertexCount - 1; + case sw::DRAW_TRIANGLELIST: + return vertexCount / 3; + case sw::DRAW_TRIANGLESTRIP: + return vertexCount - 2; + case sw::DRAW_TRIANGLEFAN: + return vertexCount - 2; + default: + UNIMPLEMENTED(); + } + + return 0; +} + const sw::Context& GraphicsPipeline::getContext() const { return context;
diff --git a/src/Vulkan/VkPipeline.hpp b/src/Vulkan/VkPipeline.hpp index 77a3d21..a38a105 100644 --- a/src/Vulkan/VkPipeline.hpp +++ b/src/Vulkan/VkPipeline.hpp
@@ -58,13 +58,14 @@ void compileShaders(const VkAllocationCallbacks* pAllocator, const VkGraphicsPipelineCreateInfo* pCreateInfo); + uint32_t computePrimitiveCount(uint32_t vertexCount) const; const sw::Context& getContext() const; const sw::Rect& getScissor() const; const VkViewport& getViewport() const; const sw::Color<float>& getBlendConstants() const; private: - rr::Routine* vertexRoutine; + rr::Routine* vertexRoutine; rr::Routine* fragmentRoutine; sw::Context context; sw::Rect scissor;
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp index b433815..57f8605 100644 --- a/src/Vulkan/VkQueue.cpp +++ b/src/Vulkan/VkQueue.cpp
@@ -16,11 +16,12 @@ #include "VkFence.hpp" #include "VkQueue.hpp" #include "VkSemaphore.hpp" +#include "Device/Renderer.hpp" namespace vk { -Queue::Queue(uint32_t pFamilyIndex, float pPriority) : familyIndex(pFamilyIndex), priority(pPriority) +Queue::Queue(uint32_t pFamilyIndex, float pPriority) : context(), renderer(&context, sw::OpenGL, true), familyIndex(pFamilyIndex), priority(pPriority) { } @@ -36,6 +37,7 @@ { CommandBuffer::ExecutionState executionState; + executionState.renderer = &renderer; for(uint32_t j = 0; j < submitInfo.commandBufferCount; j++) { vk::Cast(submitInfo.pCommandBuffers[j])->submit(executionState);
diff --git a/src/Vulkan/VkQueue.hpp b/src/Vulkan/VkQueue.hpp index 739d7fd..f57ebdf 100644 --- a/src/Vulkan/VkQueue.hpp +++ b/src/Vulkan/VkQueue.hpp
@@ -16,6 +16,7 @@ #define VK_QUEUE_HPP_ #include "VkObject.hpp" +#include "Device/Renderer.hpp" #include <vulkan/vk_icd.h> namespace vk @@ -37,6 +38,8 @@ void submit(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence); private: + sw::Context context; + sw::Renderer renderer; uint32_t familyIndex = 0; float priority = 0.0f; };