- implement the depth and stencil states

This commit is contained in:
Magnus Norddahl 2019-03-03 22:25:38 +01:00
parent d516b2ff7b
commit 923fb5c127
6 changed files with 112 additions and 23 deletions

View file

@ -250,7 +250,7 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key)
// builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS); // builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK); // builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK); // builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
builder.setViewport(0.0f, 0.0f, (float)SCREENWIDTH, (float)SCREENHEIGHT); builder.setViewport(0.0f, 0.0f, (float)SCREENWIDTH, (float)SCREENHEIGHT);
builder.setScissor(0, 0, SCREENWIDTH, SCREENHEIGHT); builder.setScissor(0, 0, SCREENWIDTH, SCREENHEIGHT);
@ -263,8 +263,6 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key)
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
}; };
builder.setTopology(vktopology[key.DrawType]);
static const int blendstyles[] = { static const int blendstyles[] = {
VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO,
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE,
@ -291,8 +289,15 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key)
blendequation = VK_BLEND_OP_ADD; blendequation = VK_BLEND_OP_ADD;
} }
builder.setDepthEnable(key.DepthTest, key.DepthWrite); static const VkStencilOp op2vk[] = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP };
static const VkCompareOp depthfunc2vk[] = { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS };
builder.setTopology(vktopology[key.DrawType]);
builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
builder.setDepthFunc(depthfunc2vk[key.DepthFunc]);
builder.setCull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_FRONT_AND_BACK, key.CullMode == Cull_CW ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE);
builder.setColorWriteMask((VkColorComponentFlagBits)key.ColorMask);
builder.setStencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
builder.setBlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend); builder.setBlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend);
builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get()); builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get());

View file

@ -17,6 +17,11 @@ public:
int AlphaTest; int AlphaTest;
int DepthWrite; int DepthWrite;
int DepthTest; int DepthTest;
int DepthFunc;
int StencilTest;
int StencilPassOp;
int ColorMask;
int CullMode;
int VertexFormat; int VertexFormat;
int DrawType; int DrawType;

View file

@ -32,10 +32,8 @@ void VkRenderState::ClearScreen()
void VkRenderState::Draw(int dt, int index, int count, bool apply) void VkRenderState::Draw(int dt, int index, int count, bool apply)
{ {
if (apply) if (apply || mNeedApply)
Apply(dt); Apply(dt);
else if (mDynamicSetChanged)
ApplyDynamicSet();
drawcalls.Clock(); drawcalls.Clock();
mCommandBuffer->draw(count, 1, index, 0); mCommandBuffer->draw(count, 1, index, 0);
@ -44,10 +42,8 @@ void VkRenderState::Draw(int dt, int index, int count, bool apply)
void VkRenderState::DrawIndexed(int dt, int index, int count, bool apply) void VkRenderState::DrawIndexed(int dt, int index, int count, bool apply)
{ {
if (apply) if (apply || mNeedApply)
Apply(dt); Apply(dt);
else if (mDynamicSetChanged)
ApplyDynamicSet();
drawcalls.Clock(); drawcalls.Clock();
mCommandBuffer->drawIndexed(count, 1, index, 0, 0); mCommandBuffer->drawIndexed(count, 1, index, 0, 0);
@ -58,16 +54,20 @@ bool VkRenderState::SetDepthClamp(bool on)
{ {
bool lastValue = mLastDepthClamp; bool lastValue = mLastDepthClamp;
mLastDepthClamp = on; mLastDepthClamp = on;
mNeedApply = true;
return lastValue; return lastValue;
} }
void VkRenderState::SetDepthMask(bool on) void VkRenderState::SetDepthMask(bool on)
{ {
mDepthWrite = on; mDepthWrite = on;
mNeedApply = true;
} }
void VkRenderState::SetDepthFunc(int func) void VkRenderState::SetDepthFunc(int func)
{ {
mDepthFunc = func;
mNeedApply = true;
} }
void VkRenderState::SetDepthRange(float min, float max) void VkRenderState::SetDepthRange(float min, float max)
@ -75,10 +75,14 @@ void VkRenderState::SetDepthRange(float min, float max)
mViewportDepthMin = min; mViewportDepthMin = min;
mViewportDepthMax = max; mViewportDepthMax = max;
mViewportChanged = true; mViewportChanged = true;
mNeedApply = true;
} }
void VkRenderState::SetColorMask(bool r, bool g, bool b, bool a) void VkRenderState::SetColorMask(bool r, bool g, bool b, bool a)
{ {
int rr = r, gg = g, bb = b, aa = a;
mColorMask = (aa < 3) | (bb << 2) | (gg << 1) | rr;
mNeedApply = true;
} }
void VkRenderState::EnableDrawBufferAttachments(bool on) void VkRenderState::EnableDrawBufferAttachments(bool on)
@ -87,10 +91,24 @@ void VkRenderState::EnableDrawBufferAttachments(bool on)
void VkRenderState::SetStencil(int offs, int op, int flags) void VkRenderState::SetStencil(int offs, int op, int flags)
{ {
mStencilRef = screen->stencilValue + offs;
mStencilRefChanged = true;
mStencilOp = op;
if (flags != -1)
{
bool cmon = !(flags & SF_ColorMaskOff);
SetColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
mDepthWrite = cmon;
}
mNeedApply = true;
} }
void VkRenderState::SetCulling(int mode) void VkRenderState::SetCulling(int mode)
{ {
mCullMode = mode;
mNeedApply = true;
} }
void VkRenderState::EnableClipDistance(int num, bool state) void VkRenderState::EnableClipDistance(int num, bool state)
@ -160,6 +178,8 @@ void VkRenderState::Clear(int targets)
void VkRenderState::EnableStencil(bool on) void VkRenderState::EnableStencil(bool on)
{ {
mStencilTest = on;
mNeedApply = true;
} }
void VkRenderState::SetScissor(int x, int y, int w, int h) void VkRenderState::SetScissor(int x, int y, int w, int h)
@ -169,6 +189,7 @@ void VkRenderState::SetScissor(int x, int y, int w, int h)
mScissorWidth = w; mScissorWidth = w;
mScissorHeight = h; mScissorHeight = h;
mScissorChanged = true; mScissorChanged = true;
mNeedApply = true;
} }
void VkRenderState::SetViewport(int x, int y, int w, int h) void VkRenderState::SetViewport(int x, int y, int w, int h)
@ -178,11 +199,13 @@ void VkRenderState::SetViewport(int x, int y, int w, int h)
mViewportWidth = w; mViewportWidth = w;
mViewportHeight = h; mViewportHeight = h;
mViewportChanged = true; mViewportChanged = true;
mNeedApply = true;
} }
void VkRenderState::EnableDepthTest(bool on) void VkRenderState::EnableDepthTest(bool on)
{ {
mDepthTest = on; mDepthTest = on;
mNeedApply = true;
} }
void VkRenderState::EnableMultisampling(bool on) void VkRenderState::EnableMultisampling(bool on)
@ -198,12 +221,14 @@ void VkRenderState::Apply(int dt)
ApplyRenderPass(dt); ApplyRenderPass(dt);
ApplyScissor(); ApplyScissor();
ApplyViewport(); ApplyViewport();
ApplyStencilRef();
ApplyStreamData(); ApplyStreamData();
ApplyMatrices(); ApplyMatrices();
ApplyPushConstants(); ApplyPushConstants();
ApplyVertexBuffers(); ApplyVertexBuffers();
ApplyDynamicSet(); ApplyDynamicSet();
ApplyMaterial(); ApplyMaterial();
mNeedApply = false;
} }
void VkRenderState::ApplyRenderPass(int dt) void VkRenderState::ApplyRenderPass(int dt)
@ -218,6 +243,11 @@ void VkRenderState::ApplyRenderPass(int dt)
passKey.RenderStyle = mRenderStyle; passKey.RenderStyle = mRenderStyle;
passKey.DepthTest = mDepthTest; passKey.DepthTest = mDepthTest;
passKey.DepthWrite = mDepthTest && mDepthWrite; passKey.DepthWrite = mDepthTest && mDepthWrite;
passKey.DepthFunc = mDepthFunc;
passKey.StencilTest = mStencilTest;
passKey.StencilPassOp = mStencilOp;
passKey.ColorMask = mColorMask;
passKey.CullMode = mCullMode;
if (mSpecialEffect > EFF_NONE) if (mSpecialEffect > EFF_NONE)
{ {
passKey.SpecialEffect = mSpecialEffect; passKey.SpecialEffect = mSpecialEffect;
@ -241,6 +271,7 @@ void VkRenderState::ApplyRenderPass(int dt)
changingRenderPass = true; changingRenderPass = true;
mScissorChanged = true; mScissorChanged = true;
mViewportChanged = true; mViewportChanged = true;
mStencilRefChanged = true;
} }
else if (changingRenderPass) else if (changingRenderPass)
{ {
@ -262,6 +293,15 @@ void VkRenderState::ApplyRenderPass(int dt)
} }
} }
void VkRenderState::ApplyStencilRef()
{
if (mStencilRefChanged)
{
mCommandBuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, mStencilRef);
mStencilRefChanged = false;
}
}
void VkRenderState::ApplyScissor() void VkRenderState::ApplyScissor()
{ {
if (mScissorChanged) if (mScissorChanged)
@ -530,7 +570,6 @@ void VkRenderState::ApplyDynamicSet()
mLastViewpointOffset = mViewpointOffset; mLastViewpointOffset = mViewpointOffset;
mLastLightBufferOffset = mLightBufferOffset; mLastLightBufferOffset = mLightBufferOffset;
} }
mDynamicSetChanged = false;
} }
void VkRenderState::Bind(int bindingpoint, uint32_t offset) void VkRenderState::Bind(int bindingpoint, uint32_t offset)
@ -538,13 +577,13 @@ void VkRenderState::Bind(int bindingpoint, uint32_t offset)
if (bindingpoint == VIEWPOINT_BINDINGPOINT) if (bindingpoint == VIEWPOINT_BINDINGPOINT)
{ {
mViewpointOffset = offset; mViewpointOffset = offset;
mNeedApply = true;
} }
else if (bindingpoint == LIGHTBUF_BINDINGPOINT) else if (bindingpoint == LIGHTBUF_BINDINGPOINT)
{ {
mLightBufferOffset = offset; mLightBufferOffset = offset;
mNeedApply = true;
} }
mDynamicSetChanged = true;
} }
void VkRenderState::EndRenderPass() void VkRenderState::EndRenderPass()
@ -555,7 +594,6 @@ void VkRenderState::EndRenderPass()
mCommandBuffer = nullptr; mCommandBuffer = nullptr;
mRenderPassKey = {}; mRenderPassKey = {};
// To do: move this elsewhere or rename this function to make it clear this can only happen at the end of a frame
mMatricesOffset = 0; mMatricesOffset = 0;
mStreamDataOffset = 0; mStreamDataOffset = 0;
mDataIndex = -1; mDataIndex = -1;

View file

@ -47,6 +47,7 @@ public:
private: private:
void Apply(int dt); void Apply(int dt);
void ApplyRenderPass(int dt); void ApplyRenderPass(int dt);
void ApplyStencilRef();
void ApplyScissor(); void ApplyScissor();
void ApplyViewport(); void ApplyViewport();
void ApplyStreamData(); void ApplyStreamData();
@ -59,7 +60,7 @@ private:
bool mLastDepthClamp = true; bool mLastDepthClamp = true;
VulkanCommandBuffer *mCommandBuffer = nullptr; VulkanCommandBuffer *mCommandBuffer = nullptr;
VkRenderPassKey mRenderPassKey = {}; VkRenderPassKey mRenderPassKey = {};
bool mDynamicSetChanged = true; bool mNeedApply = true;
int mScissorX = 0, mScissorY = 0, mScissorWidth = -1, mScissorHeight = -1; int mScissorX = 0, mScissorY = 0, mScissorWidth = -1, mScissorHeight = -1;
int mViewportX = 0, mViewportY = 0, mViewportWidth = -1, mViewportHeight = -1; int mViewportX = 0, mViewportY = 0, mViewportWidth = -1, mViewportHeight = -1;
@ -69,6 +70,14 @@ private:
bool mDepthTest = false; bool mDepthTest = false;
bool mDepthWrite = false; bool mDepthWrite = false;
bool mStencilTest = false;
bool mStencilRefChanged = false;
int mStencilRef = 0;
int mStencilOp = 0;
int mDepthFunc = 0;
int mColorMask = 15;
int mCullMode = 0;
MatricesUBO mMatrices = {}; MatricesUBO mMatrices = {};
StreamData mStreamData = {}; StreamData mStreamData = {};

View file

@ -186,7 +186,10 @@ public:
void setScissor(int x, int y, int width, int height); void setScissor(int x, int y, int width, int height);
void setCull(VkCullModeFlags cullMode, VkFrontFace frontFace); void setCull(VkCullModeFlags cullMode, VkFrontFace frontFace);
void setDepthEnable(bool test, bool write); void setDepthStencilEnable(bool test, bool write, bool stencil);
void setDepthFunc(VkCompareOp func);
void setColorWriteMask(VkColorComponentFlags mask);
void setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference);
void setAdditiveBlendMode(); void setAdditiveBlendMode();
void setAlphaBlendMode(); void setAlphaBlendMode();
@ -764,12 +767,42 @@ inline void GraphicsPipelineBuilder::setCull(VkCullModeFlags cullMode, VkFrontFa
rasterizer.frontFace = frontFace; rasterizer.frontFace = frontFace;
} }
inline void GraphicsPipelineBuilder::setDepthEnable(bool test, bool write) inline void GraphicsPipelineBuilder::setDepthStencilEnable(bool test, bool write, bool stencil)
{ {
depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE; depthStencil.depthTestEnable = test ? VK_TRUE : VK_FALSE;
depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE; depthStencil.depthWriteEnable = write ? VK_TRUE : VK_FALSE;
depthStencil.stencilTestEnable = stencil ? VK_TRUE : VK_FALSE;
pipelineInfo.pDepthStencilState = (test || write) ? &depthStencil : nullptr; pipelineInfo.pDepthStencilState = (test || write || stencil) ? &depthStencil : nullptr;
}
inline void GraphicsPipelineBuilder::setStencil(VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp, uint32_t compareMask, uint32_t writeMask, uint32_t reference)
{
depthStencil.front.failOp = failOp;
depthStencil.front.passOp = passOp;
depthStencil.front.depthFailOp = depthFailOp;
depthStencil.front.compareOp = compareOp;
depthStencil.front.compareMask = compareMask;
depthStencil.front.writeMask = writeMask;
depthStencil.front.reference = reference;
depthStencil.back.failOp = failOp;
depthStencil.back.passOp = passOp;
depthStencil.back.depthFailOp = depthFailOp;
depthStencil.back.compareOp = compareOp;
depthStencil.back.compareMask = compareMask;
depthStencil.back.writeMask = writeMask;
depthStencil.back.reference = reference;
}
inline void GraphicsPipelineBuilder::setDepthFunc(VkCompareOp func)
{
depthStencil.depthCompareOp = func;
}
inline void GraphicsPipelineBuilder::setColorWriteMask(VkColorComponentFlags mask)
{
colorBlendAttachment.colorWriteMask = mask;
} }
inline void GraphicsPipelineBuilder::setAdditiveBlendMode() inline void GraphicsPipelineBuilder::setAdditiveBlendMode()

View file

@ -49,11 +49,10 @@ extern HWND Window;
EXTERN_CVAR(Bool, vid_vsync); EXTERN_CVAR(Bool, vid_vsync);
#ifdef NDEBUG CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
CVAR(Bool, vk_debug, false, 0); // this should be false, once the oversized model can be removed. {
#else Printf("This won't take effect until " GAMENAME " is restarted.\n");
CVAR(Bool, vk_debug, true, 0); }
#endif
VulkanDevice::VulkanDevice() VulkanDevice::VulkanDevice()
{ {