diff --git a/include/boo/graphicsdev/D3D.hpp b/include/boo/graphicsdev/D3D.hpp index 3f46a41..804cc9e 100644 --- a/include/boo/graphicsdev/D3D.hpp +++ b/include/boo/graphicsdev/D3D.hpp @@ -31,7 +31,7 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling)=0; + bool depthTest, bool depthWrite, CullMode culling)=0; }; }; diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index 5902978..8a2ef8a 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -40,7 +40,7 @@ public: size_t texCount, const char** texNames, size_t uniformBlockCount, const char** uniformBlockNames, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling); + bool depthTest, bool depthWrite, CullMode culling); IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index e2c5f31..04d818a 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -170,6 +170,14 @@ enum class Primitive TriStrips }; +/** Used by platform shader pipeline constructors */ +enum class CullMode +{ + None, + Backface, + Frontface +}; + /** Used by platform shader pipeline constructors */ enum class BlendFactor { diff --git a/include/boo/graphicsdev/Metal.hpp b/include/boo/graphicsdev/Metal.hpp index ed763d9..837212b 100644 --- a/include/boo/graphicsdev/Metal.hpp +++ b/include/boo/graphicsdev/Metal.hpp @@ -40,7 +40,7 @@ public: IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, unsigned targetSamples, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling); + bool depthTest, bool depthWrite, CullMode culling); IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 3134c31..2e01fac 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -132,14 +132,14 @@ public: std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling); + bool depthTest, bool depthWrite, CullMode culling); IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr, - vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); + vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling); } IShaderDataBinding* diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index d8c9b9d..3365a03 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -501,14 +501,29 @@ class D3D11ShaderPipeline : public IShaderPipeline D3D11ShareableShader::Token&& pixel, const D3D11VertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), m_topology(PRIMITIVE_TABLE[int(prim)]) { m_vert.get().m_shader.As(&m_vShader); m_pixel.get().m_shader.As(&m_pShader); - CD3D11_RASTERIZER_DESC rasDesc(D3D11_FILL_SOLID, backfaceCulling ? D3D11_CULL_BACK : D3D11_CULL_NONE, true, + D3D11_CULL_MODE cullMode; + switch (culling) + { + case CullMode::None: + default: + cullMode = D3D11_CULL_NONE; + break; + case CullMode::Backface: + cullMode = D3D11_CULL_BACK; + break; + case CullMode::Frontface: + cullMode = D3D11_CULL_FRONT; + break; + } + + CD3D11_RASTERIZER_DESC rasDesc(D3D11_FILL_SOLID, cullMode, true, D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, true, true, false, false); ThrowIfFailed(ctx->m_dev->CreateRasterizerState(&rasDesc, &m_rasState)); @@ -1321,7 +1336,7 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { XXH64_state_t hashState; uint64_t srcHashes[2] = {}; @@ -1424,7 +1439,7 @@ public: D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(ctx, std::move(vertShader), std::move(fragShader), static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); + srcFac, dstFac, prim, depthTest, depthWrite, culling); d->m_SPs.emplace_back(retval); return retval; } diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 95795b6..0fa3481 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -654,10 +654,25 @@ class D3D12ShaderPipeline : public IShaderPipeline D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline, const D3D12VertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), m_topology(PRIMITIVE_TABLE[int(prim)]) { + D3D12_CULL_MODE cullMode; + switch (culling) + { + case CullMode::None: + default: + cullMode = D3D12_CULL_MODE_NONE; + break; + case CullMode::Backface: + cullMode = D3D12_CULL_MODE_BACK; + break; + case CullMode::Frontface: + cullMode = D3D12_CULL_MODE_FRONT; + break; + } + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; desc.pRootSignature = ctx->m_rs.Get(); const auto& vBlob = m_vert.get().m_shader; @@ -673,8 +688,7 @@ class D3D12ShaderPipeline : public IShaderPipeline } desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); desc.RasterizerState.FrontCounterClockwise = TRUE; - if (!backfaceCulling) - desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + desc.RasterizerState.CullMode = cullMode; desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; if (!depthTest) @@ -1753,7 +1767,7 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { XXH64_state_t hashState; uint64_t srcHashes[2] = {}; @@ -1839,7 +1853,7 @@ public: ID3DBlob* pipeline = pipelineBlob ? pipelineBlob->Get() : nullptr; D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, std::move(vertShader), std::move(fragShader), pipeline, static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); + srcFac, dstFac, prim, depthTest, depthWrite, culling); if (pipelineBlob && !*pipelineBlob) retval->m_state->GetCachedBlob(&*pipelineBlob); static_cast(m_deferredData)->m_SPs.emplace_back(retval); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 7d15b67..922f896 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -416,7 +416,7 @@ class GLShaderPipeline : public IShaderPipeline GLenum m_drawPrim = GL_TRIANGLES; bool m_depthTest = true; bool m_depthWrite = true; - bool m_backfaceCulling = true; + CullMode m_culling; std::vector m_uniLocs; GLShaderPipeline() = default; public: @@ -435,7 +435,7 @@ public: m_drawPrim = other.m_drawPrim; m_depthTest = other.m_depthTest; m_depthWrite = other.m_depthWrite; - m_backfaceCulling = other.m_backfaceCulling; + m_culling = other.m_culling; m_uniLocs = std::move(other.m_uniLocs); return *this; } @@ -460,8 +460,11 @@ public: glDepthMask(m_depthWrite); glDepthFunc(GL_LEQUAL); - if (m_backfaceCulling) + if (m_culling != CullMode::None) + { glEnable(GL_CULL_FACE); + glCullFace(m_culling == CullMode::Backface ? GL_BACK : GL_FRONT); + } else glDisable(GL_CULL_FACE); @@ -496,7 +499,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline size_t texCount, const char** texNames, size_t uniformBlockCount, const char** uniformBlockNames, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { GLDataFactoryImpl& factory = static_cast(m_parent); GLShaderPipeline shader; @@ -631,7 +634,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)]; shader.m_depthTest = depthTest; shader.m_depthWrite = depthWrite; - shader.m_backfaceCulling = backfaceCulling; + shader.m_culling = culling; shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)]; GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index d9714f0..0755d68 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -1154,7 +1154,7 @@ IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, c IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, unsigned targetSamples, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { MetalDataFactoryImpl& factory = static_cast(m_parent); MTLCompileOptions* compOpts = [MTLCompileOptions new]; diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index af6c493..2c14600 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -1841,10 +1841,25 @@ class VulkanShaderPipeline : public IShaderPipeline VkPipelineCache pipelineCache, const VulkanVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) : m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_frag(std::move(frag)) { + VkCullModeFlagBits cullMode; + switch (culling) + { + case CullMode::None: + default: + cullMode = VK_CULL_MODE_NONE; + break; + case CullMode::Backface: + cullMode = VK_CULL_MODE_BACK_BIT; + break; + case CullMode::Frontface: + cullMode = VK_CULL_MODE_FRONT_BIT; + break; + } + VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; VkPipelineDynamicStateCreateInfo dynamicState = {}; dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; @@ -1895,7 +1910,7 @@ class VulkanShaderPipeline : public IShaderPipeline rasterizationInfo.depthClampEnable = VK_FALSE; rasterizationInfo.rasterizerDiscardEnable = VK_FALSE; rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; - rasterizationInfo.cullMode = backfaceCulling ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_NONE; + rasterizationInfo.cullMode = cullMode; rasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizationInfo.depthBiasEnable = VK_FALSE; rasterizationInfo.lineWidth = 1.f; @@ -3066,7 +3081,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, bool backfaceCulling) + bool depthTest, bool depthWrite, CullMode culling) { VulkanDataFactoryImpl& factory = static_cast(m_parent); @@ -3195,7 +3210,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline VulkanShaderPipeline* retval = new VulkanShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader), pipelineCache, static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); + srcFac, dstFac, prim, depthTest, depthWrite, culling); if (pipelineBlob && pipelineBlob->empty()) { diff --git a/test/main.cpp b/test/main.cpp index b61b0f4..e8f0f8c 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -308,7 +308,7 @@ struct TestApplicationCallback : IApplicationCallback pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr, BlendFactor::One, BlendFactor::Zero, - Primitive::TriStrips, true, true, false); + Primitive::TriStrips, true, true, CullMode::None); } #if BOO_HAS_VULKAN else if (plat == IGraphicsDataFactory::Platform::Vulkan) @@ -340,7 +340,7 @@ struct TestApplicationCallback : IApplicationCallback "}\n"; pipeline = vkF.newShaderPipeline(VS, FS, vfmt, BlendFactor::One, BlendFactor::Zero, - Primitive::TriStrips, true, true, false); + Primitive::TriStrips, true, true, CullMode::None); } #endif #if _WIN32 @@ -371,7 +371,7 @@ struct TestApplicationCallback : IApplicationCallback pipeline = d3dF.newShaderPipeline(VS, PS, nullptr, nullptr, nullptr, vfmt, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, - true, true, false); + true, true, CullMode::None); } #elif BOO_HAS_METAL else if (plat == IGraphicsDataFactory::Platform::Metal)