Draw: Preliminary stencil implementation. Two-sided only implemented for Vulkan.

This commit is contained in:
Henrik Rydgård 2016-12-26 23:11:31 +01:00
parent cbf4e5f38c
commit 10e4d4db14
4 changed files with 186 additions and 77 deletions

View File

@ -84,6 +84,17 @@ enum BlendFactor : int {
FIXED_COLOR,
};
enum class StencilOp {
KEEP = 0,
ZERO = 1,
REPLACE = 2,
INCREMENT_AND_CLAMP = 3,
DECREMENT_AND_CLAMP = 4,
INVERT = 5,
INCREMENT_AND_WRAP = 6,
DECREMENT_AND_WRAP = 7,
};
enum class TextureFilter : int {
NEAREST,
LINEAR,
@ -205,6 +216,57 @@ enum class DataFormat : uint8_t {
D32F_S8,
};
enum class ShaderStage {
VERTEX,
FRAGMENT,
GEOMETRY,
CONTROL, // HULL
EVALUATION, // DOMAIN
COMPUTE,
};
enum class CullMode : uint8_t {
NONE,
FRONT,
BACK,
FRONT_AND_BACK, // Not supported on D3D9
};
enum class Facing {
CCW,
CW,
};
enum BorderColor {
DONT_CARE,
TRANSPARENT_BLACK,
OPAQUE_BLACK,
OPAQUE_WHITE,
};
enum {
COLOR_MASK_R = 1,
COLOR_MASK_G = 2,
COLOR_MASK_B = 4,
COLOR_MASK_A = 8,
};
enum class TextureAddressMode {
REPEAT,
REPEAT_MIRROR,
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
};
enum class ShaderLanguage {
GLSL_ES_200,
GLSL_ES_300,
GLSL_410,
GLSL_VULKAN,
HLSL_D3D9,
HLSL_D3D11,
};
enum ImageFileType {
PNG,
JPEG,
@ -299,24 +361,6 @@ struct InputLayoutDesc {
class InputLayout : public RefCountedObject { };
enum class ShaderStage {
VERTEX,
FRAGMENT,
GEOMETRY,
CONTROL, // HULL
EVALUATION, // DOMAIN
COMPUTE,
};
enum class ShaderLanguage {
GLSL_ES_200,
GLSL_ES_300,
GLSL_410,
GLSL_VULKAN,
HLSL_D3D9,
HLSL_D3D11,
};
enum class UniformType : int8_t {
FLOAT, FLOAT2, FLOAT3, FLOAT4,
MATRIX4X4,
@ -350,11 +394,23 @@ public:
class RasterState : public RefCountedObject {};
struct StencilSide {
StencilOp failOp;
StencilOp passOp;
StencilOp depthFailOp;
Comparison compareOp;
uint8_t compareMask;
uint8_t writeMask;
uint8_t reference;
};
struct DepthStencilStateDesc {
bool depthTestEnabled;
bool depthWriteEnabled;
Comparison depthCompare;
// Ignore stencil for now, will need soon.
bool stencilEnabled;
StencilSide front;
StencilSide back;
};
struct BlendStateDesc {
@ -370,27 +426,6 @@ struct BlendStateDesc {
LogicOp logicOp;
};
enum {
COLOR_MASK_R = 1,
COLOR_MASK_G = 2,
COLOR_MASK_B = 4,
COLOR_MASK_A = 8,
};
enum BorderColor {
DONT_CARE,
TRANSPARENT_BLACK,
OPAQUE_BLACK,
OPAQUE_WHITE,
};
enum class TextureAddressMode {
REPEAT,
REPEAT_MIRROR,
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
};
struct SamplerStateDesc {
TextureFilter magFilter;
TextureFilter minFilter;
@ -405,18 +440,6 @@ struct SamplerStateDesc {
BorderColor borderColor;
};
enum class CullMode : uint8_t {
NONE,
FRONT,
BACK,
FRONT_AND_BACK, // Not supported on D3D9
};
enum class Facing {
CCW,
CW,
};
struct RasterStateDesc {
CullMode cull;
Facing facing;

View File

@ -83,6 +83,17 @@ static const D3DPRIMITIVETYPE primToD3D9[] = {
D3DPT_POINTLIST,
};
static const D3DSTENCILOP stencilOpToD3D9[] = {
D3DSTENCILOP_KEEP,
D3DSTENCILOP_ZERO,
D3DSTENCILOP_REPLACE,
D3DSTENCILOP_INCRSAT,
D3DSTENCILOP_DECRSAT,
D3DSTENCILOP_INVERT,
D3DSTENCILOP_INCR,
D3DSTENCILOP_DECR,
};
static const int primCountDivisor[] = {
1,
2,
@ -101,11 +112,30 @@ public:
BOOL depthTestEnabled;
BOOL depthWriteEnabled;
D3DCMPFUNC depthCompare;
BOOL stencilEnabled;
D3DSTENCILOP stencilFail;
D3DSTENCILOP stencilZFail;
D3DSTENCILOP stencilPass;
D3DCMPFUNC stencilCompareOp;
uint8_t stencilReference;
uint8_t stencilCompareMask;
uint8_t stencilWriteMask;
void Apply(LPDIRECT3DDEVICE9 device) {
device->SetRenderState(D3DRS_ZENABLE, depthTestEnabled);
device->SetRenderState(D3DRS_ZWRITEENABLE, depthWriteEnabled);
device->SetRenderState(D3DRS_ZFUNC, depthCompare);
if (depthTestEnabled) {
device->SetRenderState(D3DRS_ZWRITEENABLE, depthWriteEnabled);
device->SetRenderState(D3DRS_ZFUNC, depthCompare);
}
device->SetRenderState(D3DRS_STENCILENABLE, stencilEnabled);
if (stencilEnabled) {
device->SetRenderState(D3DRS_STENCILFAIL, stencilFail);
device->SetRenderState(D3DRS_STENCILZFAIL, stencilZFail);
device->SetRenderState(D3DRS_STENCILPASS, stencilPass);
device->SetRenderState(D3DRS_STENCILFUNC, stencilCompareOp);
device->SetRenderState(D3DRS_STENCILMASK, stencilCompareMask);
device->SetRenderState(D3DRS_STENCILREF, stencilReference);
device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWriteMask);
}
}
};
@ -591,6 +621,14 @@ DepthStencilState *D3D9Context::CreateDepthStencilState(const DepthStencilStateD
ds->depthTestEnabled = desc.depthTestEnabled;
ds->depthWriteEnabled = desc.depthWriteEnabled;
ds->depthCompare = compareToD3D9[(int)desc.depthCompare];
ds->stencilEnabled = desc.stencilEnabled;
ds->stencilCompareOp = compareToD3D9[(int)desc.front.compareOp];
ds->stencilPass = stencilOpToD3D9[(int)desc.front.passOp];
ds->stencilFail = stencilOpToD3D9[(int)desc.front.failOp];
ds->stencilZFail = stencilOpToD3D9[(int)desc.front.depthFailOp];
ds->stencilWriteMask = desc.front.writeMask;
ds->stencilReference = desc.front.reference;
ds->stencilCompareMask = desc.front.compareMask;
return ds;
}

View File

@ -83,6 +83,17 @@ static const unsigned short logicOpToGL[] = {
};
#endif
static const GLuint stencilOpToGL[8] = {
GL_KEEP,
GL_ZERO,
GL_REPLACE,
GL_INCR,
GL_DECR,
GL_INVERT,
GL_INCR_WRAP,
GL_DECR_WRAP,
};
static const unsigned short primToGL[] = {
GL_POINTS,
GL_LINES,
@ -166,7 +177,15 @@ public:
bool depthTestEnabled;
bool depthWriteEnabled;
GLuint depthComp;
// bool stencilTestEnabled; TODO
// TODO: Two-sided
GLboolean stencilEnabled;
GLuint stencilFail;
GLuint stencilZFail;
GLuint stencilPass;
GLuint stencilCompareOp;
uint8_t stencilReference;
uint8_t stencilCompareMask;
uint8_t stencilWriteMask;
void Apply() {
if (depthTestEnabled) {
@ -176,6 +195,14 @@ public:
} else {
glDisable(GL_DEPTH_TEST);
}
if (stencilEnabled) {
glEnable(GL_STENCIL_TEST);
glStencilOpSeparate(GL_FRONT_AND_BACK, stencilFail, stencilZFail, stencilPass);
glStencilFuncSeparate(GL_FRONT_AND_BACK, stencilCompareOp, stencilReference, stencilCompareMask);
glStencilMaskSeparate(GL_FRONT_AND_BACK, stencilWriteMask);
} else {
glDisable(GL_STENCIL_TEST);
}
glDisable(GL_STENCIL_TEST);
}
};
@ -737,6 +764,14 @@ DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStat
ds->depthTestEnabled = desc.depthTestEnabled;
ds->depthWriteEnabled = desc.depthWriteEnabled;
ds->depthComp = compToGL[(int)desc.depthCompare];
ds->stencilEnabled = desc.stencilEnabled;
ds->stencilCompareOp = compToGL[(int)desc.front.compareOp];
ds->stencilPass = stencilOpToGL[(int)desc.front.passOp];
ds->stencilFail = stencilOpToGL[(int)desc.front.failOp];
ds->stencilZFail = stencilOpToGL[(int)desc.front.depthFailOp];
ds->stencilWriteMask = desc.front.writeMask;
ds->stencilReference = desc.front.reference;
ds->stencilCompareMask = desc.front.compareMask;
return ds;
}

View File

@ -112,6 +112,18 @@ static const VkPrimitiveTopology primToVK[] = {
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
};
static const VkStencilOp stencilOpToVK[8] = {
VK_STENCIL_OP_KEEP,
VK_STENCIL_OP_ZERO,
VK_STENCIL_OP_REPLACE,
VK_STENCIL_OP_INCREMENT_AND_CLAMP,
VK_STENCIL_OP_DECREMENT_AND_CLAMP,
VK_STENCIL_OP_INVERT,
VK_STENCIL_OP_INCREMENT_AND_WRAP,
VK_STENCIL_OP_DECREMENT_AND_WRAP,
};
static inline void Uint8x4ToFloat4(uint32_t u, float f[4]) {
f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f);
f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f);
@ -121,25 +133,13 @@ static inline void Uint8x4ToFloat4(uint32_t u, float f[4]) {
class VKBlendState : public BlendState {
public:
VkPipelineColorBlendStateCreateInfo info{};
VkPipelineColorBlendStateCreateInfo info{ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
std::vector<VkPipelineColorBlendAttachmentState> attachments;
};
class VKDepthStencilState : public DepthStencilState {
public:
bool depthTestEnabled;
bool depthWriteEnabled;
VkCompareOp depthComp;
void ToVulkan(VkPipelineDepthStencilStateCreateInfo *info) const {
memset(info, 0, sizeof(*info));
info->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
info->depthCompareOp = depthComp;
info->depthTestEnable = depthTestEnabled;
info->depthWriteEnable = depthWriteEnabled;
info->stencilTestEnable = false;
info->depthBoundsTestEnable = false;
}
VkPipelineDepthStencilStateCreateInfo info{ VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
};
class VKRasterState : public RasterState {
@ -819,9 +819,6 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
stage.flags = 0;
}
VkPipelineDepthStencilStateCreateInfo depthStencil;
depth->ToVulkan(&depthStencil);
VkPipelineInputAssemblyStateCreateInfo inputAssembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
inputAssembly.topology = primToVK[(int)desc.prim];
inputAssembly.primitiveRestartEnable = false;
@ -852,7 +849,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
info.stageCount = (uint32_t)stages.size();
info.pStages = stages.data();
info.pColorBlendState = &blend->info;
info.pDepthStencilState = &depthStencil;
info.pDepthStencilState = &depth->info;
info.pDynamicState = &dynamicInfo;
info.pInputAssemblyState = &inputAssembly;
info.pTessellationState = nullptr;
@ -957,11 +954,27 @@ void VKTexture::Finalize(int zim_flags) {
// TODO
}
inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {
dest.compareMask = src.compareMask;
dest.reference = src.reference;
dest.writeMask = src.writeMask;
dest.compareOp = compToVK[(int)src.compareOp];
dest.failOp = stencilOpToVK[(int)src.failOp];
dest.passOp = stencilOpToVK[(int)src.passOp];
dest.depthFailOp = stencilOpToVK[(int)src.depthFailOp];
}
DepthStencilState *VKContext::CreateDepthStencilState(const DepthStencilStateDesc &desc) {
VKDepthStencilState *ds = new VKDepthStencilState();
ds->depthTestEnabled = desc.depthTestEnabled;
ds->depthWriteEnabled = desc.depthWriteEnabled;
ds->depthComp = compToVK[(int)desc.depthCompare];
ds->info.depthCompareOp = compToVK[(int)desc.depthCompare];
ds->info.depthTestEnable = desc.depthTestEnabled;
ds->info.depthWriteEnable = desc.depthWriteEnabled;
ds->info.stencilTestEnable = false;
ds->info.depthBoundsTestEnable = false;
if (ds->info.stencilTestEnable) {
CopySide(ds->info.front, desc.front);
CopySide(ds->info.back, desc.back);
}
return ds;
}