From 38f15ae97da5e49fe862837fc40457a5b0e74691 Mon Sep 17 00:00:00 2001 From: niki Date: Wed, 13 Jul 2022 17:27:11 +0200 Subject: [PATCH] vulkan: implement cull and winding --- src/modules/graphics/vulkan/Graphics.cpp | 33 +++++++++++++++++++----- src/modules/graphics/vulkan/Graphics.h | 6 +++-- src/modules/graphics/vulkan/Vulkan.cpp | 24 +++++++++++++++++ src/modules/graphics/vulkan/Vulkan.h | 2 ++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 2fdea0373..f1c8fe248 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -205,6 +205,7 @@ namespace love { Shader::current = Shader::standardShaders[graphics::Shader::StandardShader::STANDARD_DEFAULT]; currentPolygonMode = VK_POLYGON_MODE_FILL; + restoreState(states.back()); return true; } @@ -265,6 +266,18 @@ namespace love { 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) { flushBatchedDraws(); @@ -308,7 +321,7 @@ namespace love { void Graphics::draw(const DrawCommand& cmd) { 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(cmd.vertexCount), static_cast(cmd.instanceCount), static_cast(cmd.vertexStart), 0); } @@ -316,7 +329,7 @@ namespace love { void Graphics::draw(const DrawIndexedCommand& cmd) { 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(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType)); vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast(cmd.indexCount), static_cast(cmd.instanceCount), 0, 0, 0); @@ -384,7 +397,7 @@ namespace love { const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX; 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)); @@ -1237,12 +1250,14 @@ namespace love { 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; configuration.shader = (Shader*)Shader::current; configuration.primitiveType = primitiveType; configuration.polygonMode = currentPolygonMode; configuration.blendState = states.back().blend; + configuration.winding = states.back().winding; + configuration.cullmode = cullmode; std::vector bufferVector; std::vector offsets; @@ -1316,8 +1331,8 @@ namespace love { rasterizer.rasterizerDiscardEnable = VK_FALSE; rasterizer.polygonMode = configuration.polygonMode; 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.depthBiasConstantFactor = 0.0f; rasterizer.depthBiasClamp = 0.0f; @@ -1498,6 +1513,12 @@ namespace love { } 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) { return false; } diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index b30a045a2..5408f8647 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -27,6 +27,8 @@ namespace love { VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL; BlendState blendState; ColorChannelMask colorChannelMask; + Winding winding; + CullMode cullmode; friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other); }; @@ -99,7 +101,7 @@ namespace love { 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 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 setBlendState(const BlendState& blend) override; void setPointSize(float size) override; @@ -175,7 +177,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, PrimitiveType); + void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType, CullMode); VkInstance instance = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index 3e15a0a07..7dd097409 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -374,6 +374,30 @@ namespace love { 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"); + } + } } } } diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index bfa455aa5..9f62b2dd2 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -27,6 +27,8 @@ namespace love { static VkBlendOp getBlendOp(BlendOperation); static VkBool32 getBool(bool); static VkColorComponentFlags getColorMask(ColorChannelMask); + static VkFrontFace getFrontFace(Winding); + static VkCullModeFlags getCullMode(CullMode); }; } }