Browse Source

vulkan: implement cull and winding

niki 3 years ago
parent
commit
38f15ae97d

+ 27 - 6
src/modules/graphics/vulkan/Graphics.cpp

@@ -205,6 +205,7 @@ namespace love {
 
 
 				Shader::current = Shader::standardShaders[graphics::Shader::StandardShader::STANDARD_DEFAULT];
 				Shader::current = Shader::standardShaders[graphics::Shader::StandardShader::STANDARD_DEFAULT];
 				currentPolygonMode = VK_POLYGON_MODE_FILL;
 				currentPolygonMode = VK_POLYGON_MODE_FILL;
+				restoreState(states.back());
 
 
 				return true;
 				return true;
 			}
 			}
@@ -265,6 +266,18 @@ namespace love {
 				cleanup();
 				cleanup();
 			}
 			}
 
 
+			void Graphics::setFrontFaceWinding(Winding winding) {
+				const auto& currentState = states.back();
+
+				if (currentState.winding == winding) {
+					return;
+				}
+
+				flushBatchedDraws();
+
+				states.back().winding = winding;
+			}
+
 			void Graphics::setColorMask(ColorChannelMask mask) {
 			void Graphics::setColorMask(ColorChannelMask mask) {
 				flushBatchedDraws();
 				flushBatchedDraws();
 
 
@@ -308,7 +321,7 @@ namespace love {
 			void Graphics::draw(const DrawCommand& cmd) {
 			void Graphics::draw(const DrawCommand& cmd) {
 				std::cout << "draw ";
 				std::cout << "draw ";
 
 
-				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType);
+				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
 
 
 				vkCmdDraw(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
 				vkCmdDraw(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
 			}
 			}
@@ -316,7 +329,7 @@ namespace love {
 			void Graphics::draw(const DrawIndexedCommand& cmd) {
 			void Graphics::draw(const DrawIndexedCommand& cmd) {
 				std::cout << "drawIndexed ";
 				std::cout << "drawIndexed ";
 
 
-				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType);
+				prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
 
 
 				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast<VkDeviceSize>(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType));
 				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);
 				vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), static_cast<uint32_t>(cmd.instanceCount), 0, 0, 0);
@@ -384,7 +397,7 @@ namespace love {
 				const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
 				const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
 				const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
 				const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
 
 
-				prepareDraw(attributes, buffers, texture, PRIMITIVE_TRIANGLES);
+				prepareDraw(attributes, buffers, texture, PRIMITIVE_TRIANGLES, CULL_BACK);
 
 
 				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
 				vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
 				
 				
@@ -1237,12 +1250,14 @@ namespace love {
 				configuration.vertexInputAttributeDescriptions = attributeDescriptions;
 				configuration.vertexInputAttributeDescriptions = attributeDescriptions;
 			}
 			}
 
 
-			void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType) {
+			void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType primitiveType, CullMode cullmode) {
 				GraphicsPipelineConfiguration configuration;
 				GraphicsPipelineConfiguration configuration;
 				configuration.shader = (Shader*)Shader::current;
 				configuration.shader = (Shader*)Shader::current;
 				configuration.primitiveType = primitiveType;
 				configuration.primitiveType = primitiveType;
 				configuration.polygonMode = currentPolygonMode;
 				configuration.polygonMode = currentPolygonMode;
 				configuration.blendState = states.back().blend;
 				configuration.blendState = states.back().blend;
+				configuration.winding = states.back().winding;
+				configuration.cullmode = cullmode;
 				std::vector<VkBuffer> bufferVector;
 				std::vector<VkBuffer> bufferVector;
 
 
 				std::vector<VkDeviceSize> offsets;
 				std::vector<VkDeviceSize> offsets;
@@ -1316,8 +1331,8 @@ namespace love {
 				rasterizer.rasterizerDiscardEnable = VK_FALSE;
 				rasterizer.rasterizerDiscardEnable = VK_FALSE;
 				rasterizer.polygonMode = configuration.polygonMode;
 				rasterizer.polygonMode = configuration.polygonMode;
 				rasterizer.lineWidth = 1.0f;
 				rasterizer.lineWidth = 1.0f;
-				rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
-				rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
+				rasterizer.cullMode = Vulkan::getCullMode(configuration.cullmode);
+				rasterizer.frontFace = Vulkan::getFrontFace(configuration.winding);
 				rasterizer.depthBiasEnable = VK_FALSE;
 				rasterizer.depthBiasEnable = VK_FALSE;
 				rasterizer.depthBiasConstantFactor = 0.0f;
 				rasterizer.depthBiasConstantFactor = 0.0f;
 				rasterizer.depthBiasClamp = 0.0f;
 				rasterizer.depthBiasClamp = 0.0f;
@@ -1498,6 +1513,12 @@ namespace love {
 			}
 			}
 
 
 			bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other) {
 			bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other) {
+				if (first.cullmode != other.cullmode) {
+					return false;
+				}
+				if (first.winding != other.winding) {
+					return false;
+				}
 				if (first.colorChannelMask != other.colorChannelMask) {
 				if (first.colorChannelMask != other.colorChannelMask) {
 					return false;
 					return false;
 				}
 				}

+ 4 - 2
src/modules/graphics/vulkan/Graphics.h

@@ -27,6 +27,8 @@ namespace love {
 				VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
 				VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
 				BlendState blendState;
 				BlendState blendState;
 				ColorChannelMask colorChannelMask;
 				ColorChannelMask colorChannelMask;
+				Winding winding;
+				CullMode cullmode;
 
 
 				friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other);
 				friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other);
 			};
 			};
@@ -99,7 +101,7 @@ namespace love {
 				void setScissor() override { std::cout << "setScissor2 "; }
 				void setScissor() override { std::cout << "setScissor2 "; }
 				void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { std::cout << "setStencilMode "; }
 				void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { std::cout << "setStencilMode "; }
 				void setDepthMode(CompareMode compare, bool write) override { std::cout << "setDepthMode "; }
 				void setDepthMode(CompareMode compare, bool write) override { std::cout << "setDepthMode "; }
-				void setFrontFaceWinding(Winding winding) override { std::cout << "setFrontFaceWinding "; }
+				void setFrontFaceWinding(Winding winding) override;
 				void setColorMask(ColorChannelMask mask) override;
 				void setColorMask(ColorChannelMask mask) override;
 				void setBlendState(const BlendState& blend) override;
 				void setBlendState(const BlendState& blend) override;
 				void setPointSize(float size) override;
 				void setPointSize(float size) override;
@@ -175,7 +177,7 @@ namespace love {
 				VkDescriptorSet* getDescriptorSet(int currentFrame);
 				VkDescriptorSet* getDescriptorSet(int currentFrame);
 				graphics::StreamBuffer* getUniformBuffer();
 				graphics::StreamBuffer* getUniformBuffer();
 				void createVulkanVertexFormat(VertexAttributes vertexAttributes, bool& useConstantVertexColor, GraphicsPipelineConfiguration& configuration);
 				void createVulkanVertexFormat(VertexAttributes vertexAttributes, bool& useConstantVertexColor, GraphicsPipelineConfiguration& configuration);
-				void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType);
+				void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType, CullMode);
 
 
 				VkInstance instance = VK_NULL_HANDLE;
 				VkInstance instance = VK_NULL_HANDLE;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;

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

@@ -374,6 +374,30 @@ namespace love {
 
 
 				return flags;
 				return flags;
 			}
 			}
+
+			VkFrontFace Vulkan::getFrontFace(Winding winding) {
+				switch (winding) {
+				case WINDING_CW:
+					return VK_FRONT_FACE_CLOCKWISE;
+				case WINDING_CCW:
+					return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+				default:
+					throw love::Exception("unknown winding");
+				}
+			}
+
+			VkCullModeFlags Vulkan::getCullMode(CullMode cullmode) {
+				switch (cullmode) {
+				case CULL_BACK:
+					return VK_CULL_MODE_BACK_BIT;
+				case CULL_FRONT:
+					return VK_CULL_MODE_FRONT_BIT;
+				case CULL_NONE:
+					return VK_CULL_MODE_NONE;
+				default:
+					throw love::Exception("unknown cull mode");
+				}
+			}
 		}
 		}
 	}
 	}
 }
 }

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

@@ -27,6 +27,8 @@ namespace love {
 				static VkBlendOp getBlendOp(BlendOperation);
 				static VkBlendOp getBlendOp(BlendOperation);
 				static VkBool32 getBool(bool);
 				static VkBool32 getBool(bool);
 				static VkColorComponentFlags getColorMask(ColorChannelMask);
 				static VkColorComponentFlags getColorMask(ColorChannelMask);
+				static VkFrontFace getFrontFace(Winding);
+				static VkCullModeFlags getCullMode(CullMode);
 			};
 			};
 		}
 		}
 	}
 	}