Add front-face culling support

This commit is contained in:
Jack Andersen 2017-03-10 10:38:00 -10:00
parent 5c52877549
commit ca20aea834
11 changed files with 83 additions and 28 deletions

View File

@ -31,7 +31,7 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling)=0; bool depthTest, bool depthWrite, CullMode culling)=0;
}; };
}; };

View File

@ -40,7 +40,7 @@ public:
size_t texCount, const char** texNames, size_t texCount, const char** texNames,
size_t uniformBlockCount, const char** uniformBlockNames, size_t uniformBlockCount, const char** uniformBlockNames,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling); bool depthTest, bool depthWrite, CullMode culling);
IShaderDataBinding* IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,

View File

@ -170,6 +170,14 @@ enum class Primitive
TriStrips TriStrips
}; };
/** Used by platform shader pipeline constructors */
enum class CullMode
{
None,
Backface,
Frontface
};
/** Used by platform shader pipeline constructors */ /** Used by platform shader pipeline constructors */
enum class BlendFactor enum class BlendFactor
{ {

View File

@ -40,7 +40,7 @@ public:
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, IVertexFormat* vtxFmt, unsigned targetSamples,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling); bool depthTest, bool depthWrite, CullMode culling);
IShaderDataBinding* IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,

View File

@ -132,14 +132,14 @@ public:
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut, std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt, std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, 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, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, 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, return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr,
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling);
} }
IShaderDataBinding* IShaderDataBinding*

View File

@ -501,14 +501,29 @@ class D3D11ShaderPipeline : public IShaderPipeline
D3D11ShareableShader::Token&& pixel, D3D11ShareableShader::Token&& pixel,
const D3D11VertexFormat* vtxFmt, const D3D11VertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, 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_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
m_topology(PRIMITIVE_TABLE[int(prim)]) m_topology(PRIMITIVE_TABLE[int(prim)])
{ {
m_vert.get().m_shader.As<ID3D11VertexShader>(&m_vShader); m_vert.get().m_shader.As<ID3D11VertexShader>(&m_vShader);
m_pixel.get().m_shader.As<ID3D11PixelShader>(&m_pShader); m_pixel.get().m_shader.As<ID3D11PixelShader>(&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, D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
true, true, false, false); true, true, false, false);
ThrowIfFailed(ctx->m_dev->CreateRasterizerState(&rasDesc, &m_rasState)); ThrowIfFailed(ctx->m_dev->CreateRasterizerState(&rasDesc, &m_rasState));
@ -1321,7 +1336,7 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, CullMode culling)
{ {
XXH64_state_t hashState; XXH64_state_t hashState;
uint64_t srcHashes[2] = {}; uint64_t srcHashes[2] = {};
@ -1424,7 +1439,7 @@ public:
D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(ctx, D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(ctx,
std::move(vertShader), std::move(fragShader), std::move(vertShader), std::move(fragShader),
static_cast<const D3D11VertexFormat*>(vtxFmt), static_cast<const D3D11VertexFormat*>(vtxFmt),
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); srcFac, dstFac, prim, depthTest, depthWrite, culling);
d->m_SPs.emplace_back(retval); d->m_SPs.emplace_back(retval);
return retval; return retval;
} }

View File

@ -654,10 +654,25 @@ class D3D12ShaderPipeline : public IShaderPipeline
D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline, D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline,
const D3D12VertexFormat* vtxFmt, const D3D12VertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, 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_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
m_topology(PRIMITIVE_TABLE[int(prim)]) 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 = {}; D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
desc.pRootSignature = ctx->m_rs.Get(); desc.pRootSignature = ctx->m_rs.Get();
const auto& vBlob = m_vert.get().m_shader; 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 = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
desc.RasterizerState.FrontCounterClockwise = TRUE; desc.RasterizerState.FrontCounterClockwise = TRUE;
if (!backfaceCulling) desc.RasterizerState.CullMode = cullMode;
desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;
if (!depthTest) if (!depthTest)
@ -1753,7 +1767,7 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, CullMode culling)
{ {
XXH64_state_t hashState; XXH64_state_t hashState;
uint64_t srcHashes[2] = {}; uint64_t srcHashes[2] = {};
@ -1839,7 +1853,7 @@ public:
ID3DBlob* pipeline = pipelineBlob ? pipelineBlob->Get() : nullptr; ID3DBlob* pipeline = pipelineBlob ? pipelineBlob->Get() : nullptr;
D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, std::move(vertShader), std::move(fragShader), D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, std::move(vertShader), std::move(fragShader),
pipeline, static_cast<const D3D12VertexFormat*>(vtxFmt), pipeline, static_cast<const D3D12VertexFormat*>(vtxFmt),
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); srcFac, dstFac, prim, depthTest, depthWrite, culling);
if (pipelineBlob && !*pipelineBlob) if (pipelineBlob && !*pipelineBlob)
retval->m_state->GetCachedBlob(&*pipelineBlob); retval->m_state->GetCachedBlob(&*pipelineBlob);
static_cast<D3D12Data*>(m_deferredData)->m_SPs.emplace_back(retval); static_cast<D3D12Data*>(m_deferredData)->m_SPs.emplace_back(retval);

View File

@ -416,7 +416,7 @@ class GLShaderPipeline : public IShaderPipeline
GLenum m_drawPrim = GL_TRIANGLES; GLenum m_drawPrim = GL_TRIANGLES;
bool m_depthTest = true; bool m_depthTest = true;
bool m_depthWrite = true; bool m_depthWrite = true;
bool m_backfaceCulling = true; CullMode m_culling;
std::vector<GLint> m_uniLocs; std::vector<GLint> m_uniLocs;
GLShaderPipeline() = default; GLShaderPipeline() = default;
public: public:
@ -435,7 +435,7 @@ public:
m_drawPrim = other.m_drawPrim; m_drawPrim = other.m_drawPrim;
m_depthTest = other.m_depthTest; m_depthTest = other.m_depthTest;
m_depthWrite = other.m_depthWrite; m_depthWrite = other.m_depthWrite;
m_backfaceCulling = other.m_backfaceCulling; m_culling = other.m_culling;
m_uniLocs = std::move(other.m_uniLocs); m_uniLocs = std::move(other.m_uniLocs);
return *this; return *this;
} }
@ -460,8 +460,11 @@ public:
glDepthMask(m_depthWrite); glDepthMask(m_depthWrite);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
if (m_backfaceCulling) if (m_culling != CullMode::None)
{
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(m_culling == CullMode::Backface ? GL_BACK : GL_FRONT);
}
else else
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
@ -496,7 +499,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline
size_t texCount, const char** texNames, size_t texCount, const char** texNames,
size_t uniformBlockCount, const char** uniformBlockNames, size_t uniformBlockCount, const char** uniformBlockNames,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, CullMode culling)
{ {
GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent); GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
GLShaderPipeline shader; GLShaderPipeline shader;
@ -631,7 +634,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline
shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)]; shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)];
shader.m_depthTest = depthTest; shader.m_depthTest = depthTest;
shader.m_depthWrite = depthWrite; shader.m_depthWrite = depthWrite;
shader.m_backfaceCulling = backfaceCulling; shader.m_culling = culling;
shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)]; shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)];
GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader));

View File

@ -1154,7 +1154,7 @@ IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, c
IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, IVertexFormat* vtxFmt, unsigned targetSamples,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, CullMode culling)
{ {
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MTLCompileOptions* compOpts = [MTLCompileOptions new]; MTLCompileOptions* compOpts = [MTLCompileOptions new];

View File

@ -1841,10 +1841,25 @@ class VulkanShaderPipeline : public IShaderPipeline
VkPipelineCache pipelineCache, VkPipelineCache pipelineCache,
const VulkanVertexFormat* vtxFmt, const VulkanVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, 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_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt),
m_vert(std::move(vert)), m_frag(std::move(frag)) 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] = {}; VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
VkPipelineDynamicStateCreateInfo dynamicState = {}; VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
@ -1895,7 +1910,7 @@ class VulkanShaderPipeline : public IShaderPipeline
rasterizationInfo.depthClampEnable = VK_FALSE; rasterizationInfo.depthClampEnable = VK_FALSE;
rasterizationInfo.rasterizerDiscardEnable = VK_FALSE; rasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; 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.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizationInfo.depthBiasEnable = VK_FALSE; rasterizationInfo.depthBiasEnable = VK_FALSE;
rasterizationInfo.lineWidth = 1.f; rasterizationInfo.lineWidth = 1.f;
@ -3066,7 +3081,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut, std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt, std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling) bool depthTest, bool depthWrite, CullMode culling)
{ {
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent); VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
@ -3195,7 +3210,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
VulkanShaderPipeline* retval = new VulkanShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader), VulkanShaderPipeline* retval = new VulkanShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader),
pipelineCache, static_cast<const VulkanVertexFormat*>(vtxFmt), pipelineCache, static_cast<const VulkanVertexFormat*>(vtxFmt),
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); srcFac, dstFac, prim, depthTest, depthWrite, culling);
if (pipelineBlob && pipelineBlob->empty()) if (pipelineBlob && pipelineBlob->empty())
{ {

View File

@ -308,7 +308,7 @@ struct TestApplicationCallback : IApplicationCallback
pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr, pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr,
BlendFactor::One, BlendFactor::Zero, BlendFactor::One, BlendFactor::Zero,
Primitive::TriStrips, true, true, false); Primitive::TriStrips, true, true, CullMode::None);
} }
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
else if (plat == IGraphicsDataFactory::Platform::Vulkan) else if (plat == IGraphicsDataFactory::Platform::Vulkan)
@ -340,7 +340,7 @@ struct TestApplicationCallback : IApplicationCallback
"}\n"; "}\n";
pipeline = vkF.newShaderPipeline(VS, FS, vfmt, BlendFactor::One, BlendFactor::Zero, pipeline = vkF.newShaderPipeline(VS, FS, vfmt, BlendFactor::One, BlendFactor::Zero,
Primitive::TriStrips, true, true, false); Primitive::TriStrips, true, true, CullMode::None);
} }
#endif #endif
#if _WIN32 #if _WIN32
@ -371,7 +371,7 @@ struct TestApplicationCallback : IApplicationCallback
pipeline = d3dF.newShaderPipeline(VS, PS, nullptr, nullptr, nullptr, vfmt, pipeline = d3dF.newShaderPipeline(VS, PS, nullptr, nullptr, nullptr, vfmt,
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, false); true, true, CullMode::None);
} }
#elif BOO_HAS_METAL #elif BOO_HAS_METAL
else if (plat == IGraphicsDataFactory::Platform::Metal) else if (plat == IGraphicsDataFactory::Platform::Metal)