Browse Source

vulkan: implement draw(DrawCommand)

Now love.graphics.point and love.graphics.line works
niki 3 years ago
parent
commit
0834408b90

+ 36 - 14
src/modules/graphics/vulkan/Graphics.cpp

@@ -112,8 +112,6 @@ namespace love {
 				renderPassInfo.clearValueCount = 1;
 				renderPassInfo.pClearValues = &clearColor;
 
-				const auto& commandBuffer = commandBuffers.at(imageIndex);
-
 				vkCmdBeginRenderPass(commandBuffers.at(imageIndex), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 				currentGraphicsPipeline = VK_NULL_HANDLE;
 			}
@@ -250,6 +248,8 @@ namespace love {
 
 				updatedBatchedDrawBuffers();
 
+				Shader::current = Shader::standardShaders[graphics::Shader::StandardShader::STANDARD_DEFAULT];
+
 				return true;
 			}
 
@@ -322,13 +322,21 @@ namespace love {
 				return info;
 			}
 
+			void Graphics::draw(const DrawCommand& cmd) {
+				std::cout << "draw ";
+
+				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType);
+
+				vkCmdDraw(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
+			}
+
 			void Graphics::draw(const DrawIndexedCommand& cmd) {
 				std::cout << "drawIndexed ";
 
-				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture);
+				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType);
 
-				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), 0, getVulkanIndexBufferType(cmd.indexType));
-				vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), 1, 0, 0, 0);
+				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast<VkDeviceSize>(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType));
+				vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), static_cast<uint32_t>(cmd.instanceCount), 0, 0, 0);
 			}
 
 			void Graphics::setColor(Colorf c) {
@@ -366,13 +374,19 @@ namespace love {
 				return true;
 			}
 
+			Renderer Graphics::getRenderer() const {
+				std::cout << "getRenderer ";
+
+				return RENDERER_VULKAN;
+			}
+
 			void Graphics::drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) {
 				std::cout << "drawQuads ";
 
 				const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
 				const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
 
-				prepareDraw(attributes, buffers, texture);
+				prepareDraw(attributes, buffers, texture, PRIMITIVE_TRIANGLES);
 
 				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
 				
@@ -1176,15 +1190,18 @@ namespace love {
 				configuration.vertexInputAttributeDescriptions = attributeDescriptions;
 			}
 
-			void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) {
+			void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType) {
+				GraphicsPipelineConfiguration configuration;
+				configuration.shader = (Shader*)Shader::current;
+				configuration.primitiveType = primitiveType;
 				std::vector<VkBuffer> bufferVector;
+
 				std::vector<VkDeviceSize> offsets;
 
 				bool useConstantColorBuffer;
-				GraphicsPipelineConfiguration configuration;
 				createVulkanVertexFormat(attributes, useConstantColorBuffer, configuration);
 
-				for (uint32_t i = 0; i < 2; i++) {
+				for (uint32_t i = 0; i < VertexAttributes::MAX; i++) {
 					if (buffers.useBits & (1u << i)) {
 						bufferVector.push_back((VkBuffer)buffers.info[i].buffer->getHandle());
 						offsets.push_back((VkDeviceSize)buffers.info[i].offset);
@@ -1206,16 +1223,15 @@ namespace love {
 				ensureGraphicsPipelineConfiguration(configuration);
 
 				vkCmdBindDescriptorSets(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, getDescriptorSet(currentFrame), 0, nullptr);
-				vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, bufferVector.size(), bufferVector.data(), offsets.data());
+				vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, static_cast<uint32_t>(bufferVector.size()), bufferVector.data(), offsets.data());
 			}
 
 			VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration configuration) {
-				auto shader = reinterpret_cast<love::graphics::vulkan::Shader*>(love::graphics::vulkan::Shader::standardShaders[Shader::STANDARD_DEFAULT]);
+				auto shader = configuration.shader;
 				auto shaderStages = shader->getShaderStages();
 
 				VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
 				vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
-
 				vertexInputInfo.vertexBindingDescriptionCount = configuration.vertexInputBindingDescriptions.size();
 				vertexInputInfo.pVertexBindingDescriptions = configuration.vertexInputBindingDescriptions.data();
 				vertexInputInfo.vertexAttributeDescriptionCount = configuration.vertexInputAttributeDescriptions.size();
@@ -1223,7 +1239,7 @@ namespace love {
 
 				VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
 				inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
-				inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+				inputAssembly.topology = Vulkan::getPrimitiveTypeTopology(configuration.primitiveType);
 				inputAssembly.primitiveRestartEnable = VK_FALSE;
 				
 				VkViewport viewport{};
@@ -1250,7 +1266,7 @@ namespace love {
 				rasterizer.depthClampEnable = VK_FALSE;
 				rasterizer.rasterizerDiscardEnable = VK_FALSE;
 				rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
-				rasterizer.lineWidth = 1.0f;
+				rasterizer.lineWidth = 2.0f;
 				rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
 				rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
 				rasterizer.depthBiasEnable = VK_FALSE;
@@ -1433,6 +1449,12 @@ namespace love {
 			}
 
 			bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other) {
+				if (first.primitiveType != other.primitiveType) {
+					return false;
+				}
+				if (first.shader != other.shader) {
+					return false;
+				}
 				if (first.vertexInputAttributeDescriptions.size() != other.vertexInputAttributeDescriptions.size()) {
 					return false;
 				}

+ 5 - 3
src/modules/graphics/vulkan/Graphics.h

@@ -22,6 +22,8 @@ namespace love {
 			struct GraphicsPipelineConfiguration {
 				std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
 				std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
+				Shader* shader = nullptr;
+				PrimitiveType primitiveType = PRIMITIVE_MAX_ENUM;
 
 				friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other);
 			};
@@ -103,10 +105,10 @@ namespace love {
 				void setWireframe(bool enable) override { std::cout << "setWireframe "; }
 				PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
 				bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
-				Renderer getRenderer() const override { std::cout << "getRenderer "; return RENDERER_VULKAN; }
+				Renderer getRenderer() const override;
 				bool usesGLSLES() const override { std::cout << "usesGLSES "; return false; }
 				RendererInfo getRendererInfo() const override;
-				void draw(const DrawCommand& cmd) override { std::cout << "draw "; }
+				void draw(const DrawCommand& cmd) override;
 				void draw(const DrawIndexedCommand& cmd) override;
 				void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) override;
 
@@ -172,7 +174,7 @@ namespace love {
 				VkDescriptorSet* getDescriptorSet(int currentFrame);
 				graphics::StreamBuffer* getUniformBuffer();
 				void createVulkanVertexFormat(VertexAttributes vertexAttributes, bool& useConstantVertexColor, GraphicsPipelineConfiguration& configuration);
-				void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture);
+				void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType);
 
 				VkInstance instance = VK_NULL_HANDLE;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;

+ 4 - 1
src/modules/graphics/vulkan/Shader.h

@@ -6,6 +6,7 @@
 #include <vulkan/vulkan.h>
 
 #include <map>
+#include <iostream>
 
 
 namespace love {
@@ -20,7 +21,9 @@ namespace love {
 					return shaderStages;
 				}
 
-				void attach() override {}
+				void attach() override {
+					Shader::current = this;
+				}
 
 				ptrdiff_t getHandle() const { return 0; }
 

+ 15 - 0
src/modules/graphics/vulkan/Vulkan.cpp

@@ -286,6 +286,21 @@ namespace love {
 
 				return ss.str();
 			}
+
+			VkPrimitiveTopology Vulkan::getPrimitiveTypeTopology(graphics::PrimitiveType primitiveType) {
+				switch (primitiveType) {
+				case PRIMITIVE_POINTS:
+					return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+				case PRIMITIVE_TRIANGLES:
+					return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+				case PRIMITIVE_TRIANGLE_FAN:
+					return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
+				case PRIMITIVE_TRIANGLE_STRIP:
+					return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+				default:
+					throw love::Exception("unknown primitive type");
+				}
+			}
 		}
 	}
 }

+ 1 - 0
src/modules/graphics/vulkan/Vulkan.h

@@ -22,6 +22,7 @@ namespace love {
 				static TextureFormat getTextureFormat(PixelFormat);
 				static std::string getVendorName(uint32_t vendorId);
 				static std::string getVulkanApiVersion(uint32_t apiVersion);
+				static VkPrimitiveTopology getPrimitiveTypeTopology(graphics::PrimitiveType);
 			};
 		}
 	}