Refactor DepthStencilState. TODO: add validation tests
- defaults to depth and stencil tests off - whether or not depth and stencil tests are enabled is inferred from the comparison functions and stencil operations - only one stencil reference. D3D12 does not support separate references - change SetDepthWriteMode to SetDepthWriteEnabled and use a bool instead of enum - Create PersistentPipelineState class for OpenGL backend with simple state tracking - Add validation so DepthStencilState properties are only set once - Update API usage in HelloDepthStencil - refactor tracking of the DepthStencilState in the Metal backend - validate that compute pipeline does not have a depth stencil state
This commit is contained in:
parent
f51be34864
commit
1063439d5d
|
@ -176,7 +176,6 @@ void init() {
|
|||
.SetAttribute(0, 0, nxt::VertexFormat::FloatR32G32B32, 0)
|
||||
.SetAttribute(1, 0, nxt::VertexFormat::FloatR32G32B32, 3 * sizeof(float))
|
||||
.SetInput(0, 6 * sizeof(float), nxt::InputStepMode::Vertex)
|
||||
.SetInput(1, 6 * sizeof(float), nxt::InputStepMode::Vertex)
|
||||
.GetResult();
|
||||
|
||||
nxt::BindGroupLayout bgl = device.CreateBindGroupLayoutBuilder()
|
||||
|
@ -243,8 +242,8 @@ void init() {
|
|||
CreateDefaultRenderPass(device, &renderpass, &framebuffer);
|
||||
|
||||
auto depthStencilState = device.CreateDepthStencilStateBuilder()
|
||||
.SetDepthEnabled(true)
|
||||
.SetStencilEnabled(false)
|
||||
.SetDepthCompareFunction(nxt::CompareFunction::Less)
|
||||
.SetDepthWriteEnabled(true)
|
||||
.GetResult();
|
||||
|
||||
pipeline = device.CreatePipelineBuilder()
|
||||
|
@ -257,12 +256,9 @@ void init() {
|
|||
.GetResult();
|
||||
|
||||
auto planeStencilState = device.CreateDepthStencilStateBuilder()
|
||||
.SetDepthEnabled(true)
|
||||
.SetDepthWrite(nxt::DepthWriteMode::Disabled)
|
||||
.SetStencilEnabled(true)
|
||||
.SetStencilCompareFunction(nxt::Face::Both, nxt::CompareFunction::Always)
|
||||
.SetStencilOperation(nxt::Face::Both, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace)
|
||||
.SetStencilMask(nxt::Face::Both, 0xff, 0xff)
|
||||
.SetDepthCompareFunction(nxt::CompareFunction::Less)
|
||||
.SetDepthWriteEnabled(false)
|
||||
.SetStencilFunction(nxt::Face::Both, nxt::CompareFunction::Always, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace)
|
||||
.GetResult();
|
||||
|
||||
planePipeline = device.CreatePipelineBuilder()
|
||||
|
@ -275,12 +271,9 @@ void init() {
|
|||
.GetResult();
|
||||
|
||||
auto reflectionStencilState = device.CreateDepthStencilStateBuilder()
|
||||
.SetDepthEnabled(true)
|
||||
.SetDepthWrite(nxt::DepthWriteMode::Enabled)
|
||||
.SetStencilEnabled(true)
|
||||
.SetStencilCompareFunction(nxt::Face::Both, nxt::CompareFunction::Equal)
|
||||
.SetStencilOperation(nxt::Face::Both, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace)
|
||||
.SetStencilMask(nxt::Face::Both, 0xff, 0x00)
|
||||
.SetDepthCompareFunction(nxt::CompareFunction::Less)
|
||||
.SetDepthWriteEnabled(true)
|
||||
.SetStencilFunction(nxt::Face::Both, nxt::CompareFunction::Equal, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace)
|
||||
.GetResult();
|
||||
|
||||
reflectionPipeline = device.CreatePipelineBuilder()
|
||||
|
@ -320,13 +313,12 @@ void frame() {
|
|||
.SetIndexBuffer(indexBuffer, 0, nxt::IndexFormat::Uint32)
|
||||
.DrawElements(36, 1, 0, 0)
|
||||
|
||||
.SetStencilReference(0x1)
|
||||
.SetPipeline(planePipeline)
|
||||
.SetStencilReference(0x1, 0x1)
|
||||
.SetVertexBuffers(0, 1, &planeBuffer, vertexBufferOffsets)
|
||||
.DrawElements(6, 1, 0, 0)
|
||||
|
||||
.SetPipeline(reflectionPipeline)
|
||||
.SetStencilReference(0x1, 0x1)
|
||||
.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets)
|
||||
.SetBindGroup(0, bindGroup[1])
|
||||
.DrawElements(36, 1, 0, 0)
|
||||
|
|
48
next.json
48
next.json
|
@ -14,6 +14,9 @@
|
|||
"See the License for the specific language governing permissions and",
|
||||
"limitations under the License."
|
||||
],
|
||||
"bool": {
|
||||
"category": "native"
|
||||
},
|
||||
"bind group": {
|
||||
"category": "object"
|
||||
},
|
||||
|
@ -282,8 +285,7 @@
|
|||
{
|
||||
"name": "set stencil reference",
|
||||
"args": [
|
||||
{"name": "back reference", "type": "uint32_t"},
|
||||
{"name": "front reference", "type": "uint32_t"}
|
||||
{"name": "reference", "type": "uint32_t"}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -448,12 +450,6 @@
|
|||
"name": "get result",
|
||||
"returns": "depth stencil state"
|
||||
},
|
||||
{
|
||||
"name": "set depth enabled",
|
||||
"args": [
|
||||
{"name": "depth enabled", "type": "bool"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set depth compare function",
|
||||
"args": [
|
||||
|
@ -461,56 +457,37 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "set depth write",
|
||||
"name": "set depth write enabled",
|
||||
"args" : [
|
||||
{"name": "depth write mode", "type": "depth write mode"}
|
||||
{"name": "enabled", "type": "bool"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set stencil enabled",
|
||||
"args": [
|
||||
{"name": "stencil enabled", "type": "bool"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set stencil operation",
|
||||
"name": "set stencil function",
|
||||
"args": [
|
||||
{"name": "face", "type": "face"},
|
||||
{"name": "stencil compare function", "type": "compare function"},
|
||||
{"name": "stencil failure operation", "type": "stencil operation"},
|
||||
{"name": "depth failure operation", "type": "stencil operation"},
|
||||
{"name": "stencil pass operation", "type": "stencil operation"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set stencil compare function",
|
||||
"args": [
|
||||
{"name": "face", "type": "face"},
|
||||
{"name": "stencil compare function", "type": "compare function"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "set stencil mask",
|
||||
"args": [
|
||||
{"name": "face", "type": "face"},
|
||||
{"name": "read mask", "type": "uint32_t"},
|
||||
{"name": "write mask", "type": "uint32_t"}
|
||||
{"name": "mask", "type": "uint32_t"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"depth write mode": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
{"value": 0, "name": "disabled"},
|
||||
{"value": 1, "name": "enabled"}
|
||||
]
|
||||
},
|
||||
"device error callback": {
|
||||
"category": "natively defined"
|
||||
},
|
||||
"face": {
|
||||
"category": "bitmask",
|
||||
"values": [
|
||||
{"value": 0, "name": "none"},
|
||||
{"value": 1, "name": "back"},
|
||||
{"value": 2, "name": "front"},
|
||||
{"value": 3, "name": "both"}
|
||||
|
@ -638,7 +615,7 @@
|
|||
{
|
||||
"name": "set depth stencil state",
|
||||
"args": [
|
||||
{"name": "input", "type": "depth stencil state"}
|
||||
{"name": "depth stencil state", "type": "depth stencil state"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -912,8 +889,5 @@
|
|||
},
|
||||
"uint32_t": {
|
||||
"category": "native"
|
||||
},
|
||||
"bool": {
|
||||
"category": "native"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ list(APPEND BACKEND_SOURCES
|
|||
${OPENGL_DIR}/CommandBufferGL.h
|
||||
${OPENGL_DIR}/OpenGLBackend.cpp
|
||||
${OPENGL_DIR}/OpenGLBackend.h
|
||||
${OPENGL_DIR}/PersistentPipelineStateGL.cpp
|
||||
${OPENGL_DIR}/PersistentPipelineStateGL.h
|
||||
${OPENGL_DIR}/PipelineGL.cpp
|
||||
${OPENGL_DIR}/PipelineGL.h
|
||||
${OPENGL_DIR}/PipelineLayoutGL.cpp
|
||||
|
|
|
@ -573,6 +573,14 @@ namespace backend {
|
|||
case Command::SetStencilReference:
|
||||
{
|
||||
SetStencilReferenceCmd* cmd = iterator.NextCommand<SetStencilReferenceCmd>();
|
||||
if (lastPipeline->IsCompute()) {
|
||||
HandleError("Can't set stencil reference in a compute pipeline");
|
||||
return false;
|
||||
}
|
||||
if (currentRenderPass == nullptr) {
|
||||
HandleError("Can't set stencil reference without an active render pass");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -766,11 +774,10 @@ namespace backend {
|
|||
memcpy(values, data, count * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::SetStencilReference(uint32_t backReference, uint32_t frontReference) {
|
||||
void CommandBufferBuilder::SetStencilReference(uint32_t reference) {
|
||||
SetStencilReferenceCmd* cmd = allocator.Allocate<SetStencilReferenceCmd>(Command::SetStencilReference);
|
||||
new(cmd) SetStencilReferenceCmd;
|
||||
cmd->backReference = backReference;
|
||||
cmd->frontReference = frontReference;
|
||||
cmd->reference = reference;
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) {
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace backend {
|
|||
void EndRenderPass();
|
||||
void SetPushConstants(nxt::ShaderStageBit stage, uint32_t offset, uint32_t count, const void* data);
|
||||
void SetPipeline(PipelineBase* pipeline);
|
||||
void SetStencilReference(uint32_t backReference, uint32_t frontReference);
|
||||
void SetStencilReference(uint32_t reference);
|
||||
void SetBindGroup(uint32_t groupIndex, BindGroupBase* group);
|
||||
void SetIndexBuffer(BufferBase* buffer, uint32_t offset, nxt::IndexFormat format);
|
||||
|
||||
|
|
|
@ -96,8 +96,7 @@ namespace backend {
|
|||
};
|
||||
|
||||
struct SetStencilReferenceCmd {
|
||||
uint32_t backReference;
|
||||
uint32_t frontReference;
|
||||
uint32_t reference;
|
||||
};
|
||||
|
||||
struct SetBindGroupCmd {
|
||||
|
|
|
@ -21,34 +21,43 @@ namespace backend {
|
|||
// DepthStencilStateBase
|
||||
|
||||
DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder)
|
||||
: depthEnabled(builder->depthEnabled), stencilEnabled(builder->stencilEnabled),
|
||||
depthInfo(builder->depthInfo), backStencilInfo(builder->backStencilInfo),
|
||||
frontStencilInfo(builder->frontStencilInfo) {
|
||||
: depthInfo(builder->depthInfo), stencilInfo(builder->stencilInfo) {
|
||||
}
|
||||
|
||||
bool DepthStencilStateBase::DepthIsEnabled() const {
|
||||
return depthEnabled;
|
||||
bool DepthStencilStateBase::DepthTestEnabled() const {
|
||||
return depthInfo.compareFunction != nxt::CompareFunction::Always;
|
||||
}
|
||||
|
||||
bool DepthStencilStateBase::StencilIsEnabled() const {
|
||||
return stencilEnabled;
|
||||
bool DepthStencilStateBase::StencilTestEnabled() const {
|
||||
return (stencilInfo.back.compareFunction != nxt::CompareFunction::Always ||
|
||||
stencilInfo.back.stencilFail != nxt::StencilOperation::Keep ||
|
||||
stencilInfo.back.depthFail != nxt::StencilOperation::Keep ||
|
||||
stencilInfo.back.depthStencilPass != nxt::StencilOperation::Keep ||
|
||||
stencilInfo.front.compareFunction != nxt::CompareFunction::Always ||
|
||||
stencilInfo.front.stencilFail != nxt::StencilOperation::Keep ||
|
||||
stencilInfo.front.depthFail != nxt::StencilOperation::Keep ||
|
||||
stencilInfo.front.depthStencilPass != nxt::StencilOperation::Keep);
|
||||
}
|
||||
|
||||
const DepthStencilStateBase::DepthInfo& DepthStencilStateBase::GetDepth() const {
|
||||
return depthInfo;
|
||||
}
|
||||
|
||||
const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetBackStencil() const {
|
||||
return backStencilInfo;
|
||||
const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetStencil() const {
|
||||
return stencilInfo;
|
||||
}
|
||||
|
||||
const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetFrontStencil() const {
|
||||
return frontStencilInfo;
|
||||
}
|
||||
|
||||
|
||||
// DepthStencilStateBuilder
|
||||
|
||||
enum DepthStencilStateSetProperties {
|
||||
DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION = 0x1,
|
||||
DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED = 0x2,
|
||||
DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION = 0x4,
|
||||
DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_MASK = 0x8,
|
||||
DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION = 0x10,
|
||||
DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_MASK = 0x20,
|
||||
};
|
||||
|
||||
DepthStencilStateBuilder::DepthStencilStateBuilder(DeviceBase* device) : Builder(device) {
|
||||
}
|
||||
|
||||
|
@ -56,53 +65,88 @@ namespace backend {
|
|||
return device->CreateDepthStencilState(this);
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetDepthEnabled(bool depthEnabled) {
|
||||
this->depthEnabled = depthEnabled;
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction) {
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION) != 0) {
|
||||
HandleError("Depth compare property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION;
|
||||
|
||||
depthInfo.compareFunction = depthCompareFunction;
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetDepthWrite(nxt::DepthWriteMode depthWriteMode) {
|
||||
depthInfo.depthWriteMode = depthWriteMode;
|
||||
void DepthStencilStateBuilder::SetDepthWriteEnabled(bool enabled) {
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED) != 0) {
|
||||
HandleError("Depth write enabled property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED;
|
||||
|
||||
depthInfo.depthWriteEnabled = enabled;
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetStencilEnabled(bool stencilEnabled) {
|
||||
this->stencilEnabled = stencilEnabled;
|
||||
}
|
||||
void DepthStencilStateBuilder::SetStencilFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction,
|
||||
nxt::StencilOperation stencilFail, nxt::StencilOperation depthFail, nxt::StencilOperation depthStencilPass) {\
|
||||
if (face == nxt::Face::None) {
|
||||
HandleError("Can't set stencil function of None face");
|
||||
return;
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetStencilOperation(nxt::Face face, nxt::StencilOperation stencilFail,
|
||||
nxt::StencilOperation depthFail, nxt::StencilOperation stencilPass) {
|
||||
if (face & nxt::Face::Back) {
|
||||
backStencilInfo.stencilFail = stencilFail;
|
||||
backStencilInfo.depthFail = stencilFail;
|
||||
backStencilInfo.stencilPass = stencilPass;
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION) != 0) {
|
||||
HandleError("Stencil back function property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION;
|
||||
|
||||
stencilInfo.back.compareFunction = stencilCompareFunction;
|
||||
stencilInfo.back.stencilFail = stencilFail;
|
||||
stencilInfo.back.depthFail = depthFail;
|
||||
stencilInfo.back.depthStencilPass = depthStencilPass;
|
||||
}
|
||||
if (face & nxt::Face::Front) {
|
||||
frontStencilInfo.stencilFail = stencilFail;
|
||||
frontStencilInfo.depthFail = stencilFail;
|
||||
frontStencilInfo.stencilPass = stencilPass;
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION) != 0) {
|
||||
HandleError("Stencil front function property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION;
|
||||
|
||||
stencilInfo.front.compareFunction = stencilCompareFunction;
|
||||
stencilInfo.front.stencilFail = stencilFail;
|
||||
stencilInfo.front.depthFail = depthFail;
|
||||
stencilInfo.front.depthStencilPass = depthStencilPass;
|
||||
}
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetStencilCompareFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction) {
|
||||
if (face & nxt::Face::Back) {
|
||||
backStencilInfo.compareFunction = stencilCompareFunction;
|
||||
void DepthStencilStateBuilder::SetStencilMask(nxt::Face face, uint32_t mask) {
|
||||
if (face == nxt::Face::None) {
|
||||
HandleError("Can't set stencil mask of None face");
|
||||
return;
|
||||
}
|
||||
if (face & nxt::Face::Front) {
|
||||
frontStencilInfo.compareFunction = stencilCompareFunction;
|
||||
}
|
||||
}
|
||||
|
||||
void DepthStencilStateBuilder::SetStencilMask(nxt::Face face, uint32_t readMask, uint32_t writeMask) {
|
||||
if (face & nxt::Face::Back) {
|
||||
backStencilInfo.readMask = readMask;
|
||||
backStencilInfo.writeMask = writeMask;
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_MASK) != 0) {
|
||||
HandleError("Stencil back mask property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_MASK;
|
||||
|
||||
stencilInfo.back.mask = mask;
|
||||
}
|
||||
if (face & nxt::Face::Front) {
|
||||
frontStencilInfo.readMask = readMask;
|
||||
frontStencilInfo.writeMask = writeMask;
|
||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_MASK) != 0) {
|
||||
HandleError("Stencil front mask property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_MASK;
|
||||
|
||||
stencilInfo.front.mask = mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,31 +29,32 @@ namespace backend {
|
|||
DepthStencilStateBase(DepthStencilStateBuilder* builder);
|
||||
|
||||
struct DepthInfo {
|
||||
nxt::CompareFunction compareFunction = nxt::CompareFunction::Less;
|
||||
nxt::DepthWriteMode depthWriteMode = nxt::DepthWriteMode::Enabled;
|
||||
nxt::CompareFunction compareFunction = nxt::CompareFunction::Always;
|
||||
bool depthWriteEnabled = false;
|
||||
};
|
||||
|
||||
struct StencilInfo {
|
||||
struct StencilFaceInfo {
|
||||
nxt::CompareFunction compareFunction = nxt::CompareFunction::Always;
|
||||
nxt::StencilOperation stencilFail = nxt::StencilOperation::Keep;
|
||||
nxt::StencilOperation depthFail = nxt::StencilOperation::Keep;
|
||||
nxt::StencilOperation stencilPass = nxt::StencilOperation::Keep;
|
||||
uint32_t readMask = 0xff;
|
||||
uint32_t writeMask = 0xff;
|
||||
nxt::StencilOperation depthStencilPass = nxt::StencilOperation::Keep;
|
||||
uint32_t mask = 0xff;
|
||||
};
|
||||
|
||||
bool DepthIsEnabled() const;
|
||||
bool StencilIsEnabled() const;
|
||||
struct StencilInfo {
|
||||
bool stencilTestEnabled;
|
||||
StencilFaceInfo back;
|
||||
StencilFaceInfo front;
|
||||
};
|
||||
|
||||
bool DepthTestEnabled() const;
|
||||
bool StencilTestEnabled() const;
|
||||
const DepthInfo& GetDepth() const;
|
||||
const StencilInfo& GetBackStencil() const;
|
||||
const StencilInfo& GetFrontStencil() const;
|
||||
const StencilInfo& GetStencil() const;
|
||||
|
||||
private:
|
||||
bool depthEnabled = false;
|
||||
bool stencilEnabled = false;
|
||||
DepthInfo depthInfo;
|
||||
StencilInfo backStencilInfo;
|
||||
StencilInfo frontStencilInfo;
|
||||
StencilInfo stencilInfo;
|
||||
};
|
||||
|
||||
class DepthStencilStateBuilder : public Builder<DepthStencilStateBase> {
|
||||
|
@ -61,25 +62,21 @@ namespace backend {
|
|||
DepthStencilStateBuilder(DeviceBase* device);
|
||||
|
||||
// NXT API
|
||||
void SetDepthEnabled(bool depthEnabled);
|
||||
void SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction);
|
||||
void SetDepthWrite(nxt::DepthWriteMode depthWriteMode);
|
||||
void SetStencilEnabled(bool stencilEnabled);
|
||||
void SetStencilOperation(nxt::Face face, nxt::StencilOperation stencilFail,
|
||||
nxt::StencilOperation depthFail, nxt::StencilOperation stencilPass);
|
||||
void SetStencilCompareFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction);
|
||||
void SetStencilMask(nxt::Face face, uint32_t readMask, uint32_t writeMask);
|
||||
void SetDepthWriteEnabled(bool enabled);
|
||||
void SetStencilFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction,
|
||||
nxt::StencilOperation stencilFail, nxt::StencilOperation depthFail, nxt::StencilOperation depthStencilPass);
|
||||
void SetStencilMask(nxt::Face face, uint32_t mask);
|
||||
|
||||
private:
|
||||
friend class DepthStencilStateBase;
|
||||
|
||||
DepthStencilStateBase* GetResultImpl() override;
|
||||
|
||||
bool depthEnabled;
|
||||
bool stencilEnabled;
|
||||
int propertiesSet = 0;
|
||||
|
||||
DepthStencilStateBase::DepthInfo depthInfo;
|
||||
DepthStencilStateBase::StencilInfo backStencilInfo;
|
||||
DepthStencilStateBase::StencilInfo frontStencilInfo;
|
||||
DepthStencilStateBase::StencilInfo stencilInfo;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace backend {
|
|||
return;
|
||||
}
|
||||
|
||||
if (IsCompute() && depthStencilState) {
|
||||
builder->HandleError("Compute pipeline cannot have depth stencil state");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsCompute() && !renderPass) {
|
||||
builder->HandleError("Pipeline render pass not set");
|
||||
return;
|
||||
|
@ -123,13 +128,17 @@ namespace backend {
|
|||
if (!inputState) {
|
||||
inputState = device->CreateInputStateBuilder()->GetResult();
|
||||
}
|
||||
if (!depthStencilState) {
|
||||
if (!depthStencilState && !IsCompute()) {
|
||||
depthStencilState = device->CreateDepthStencilStateBuilder()->GetResult();
|
||||
}
|
||||
|
||||
return device->CreatePipeline(this);
|
||||
}
|
||||
|
||||
bool PipelineBuilder::IsCompute() const {
|
||||
return stageMask == nxt::ShaderStageBit::Compute;
|
||||
}
|
||||
|
||||
void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) {
|
||||
this->layout = layout;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ namespace backend {
|
|||
|
||||
PipelineBase* GetResultImpl() override;
|
||||
|
||||
bool IsCompute() const;
|
||||
|
||||
Ref<PipelineLayoutBase> layout;
|
||||
Ref<RenderPassBase> renderPass;
|
||||
uint32_t subpass;
|
||||
|
|
|
@ -189,11 +189,12 @@ namespace metal {
|
|||
DepthStencilState(Device* device, DepthStencilStateBuilder* builder);
|
||||
~DepthStencilState();
|
||||
|
||||
MTLDepthStencilDescriptor* GetMTLDepthStencilDescriptor();
|
||||
id<MTLDepthStencilState> GetMTLDepthStencilState();
|
||||
|
||||
private:
|
||||
Device* device;
|
||||
MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = nil;
|
||||
|
||||
id<MTLDepthStencilState> mtlDepthStencilState = nil;
|
||||
};
|
||||
|
||||
class InputState : public InputStateBase {
|
||||
|
@ -230,8 +231,6 @@ namespace metal {
|
|||
Device* device;
|
||||
|
||||
id<MTLRenderPipelineState> mtlRenderPipelineState = nil;
|
||||
id<MTLDepthStencilState> mtlDepthStencilState = nil;
|
||||
|
||||
id<MTLComputePipelineState> mtlComputePipelineState = nil;
|
||||
MTLSize localWorkgroupSize;
|
||||
};
|
||||
|
|
|
@ -456,6 +456,8 @@ namespace metal {
|
|||
lastPipeline->Encode(encoders.compute);
|
||||
} else {
|
||||
ASSERT(encoders.render);
|
||||
DepthStencilState* depthStencilState = ToBackend(lastPipeline->GetDepthStencilState());
|
||||
[encoders.render setDepthStencilState:depthStencilState->GetMTLDepthStencilState()];
|
||||
lastPipeline->Encode(encoders.render);
|
||||
}
|
||||
}
|
||||
|
@ -478,9 +480,7 @@ namespace metal {
|
|||
|
||||
ASSERT(encoders.render);
|
||||
|
||||
[encoders.render
|
||||
setStencilFrontReferenceValue:cmd->frontReference
|
||||
backReferenceValue:cmd->backReference];
|
||||
[encoders.render setStencilReferenceValue:cmd->reference];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -665,7 +665,7 @@ namespace metal {
|
|||
|
||||
// DepthStencilState
|
||||
|
||||
static MTLCompareFunction DepthStencilCompareFunction(nxt::CompareFunction compareFunction) {
|
||||
static MTLCompareFunction MetalDepthStencilCompareFunction(nxt::CompareFunction compareFunction) {
|
||||
switch (compareFunction) {
|
||||
case nxt::CompareFunction::Never:
|
||||
return MTLCompareFunctionNever;
|
||||
|
@ -683,12 +683,10 @@ namespace metal {
|
|||
return MTLCompareFunctionEqual;
|
||||
case nxt::CompareFunction::Always:
|
||||
return MTLCompareFunctionAlways;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
static MTLStencilOperation StencilOperation(nxt::StencilOperation stencilOperation) {
|
||||
static MTLStencilOperation MetalStencilOperation(nxt::StencilOperation stencilOperation) {
|
||||
switch (stencilOperation) {
|
||||
case nxt::StencilOperation::Keep:
|
||||
return MTLStencilOperationKeep;
|
||||
|
@ -706,51 +704,38 @@ namespace metal {
|
|||
return MTLStencilOperationIncrementWrap;
|
||||
case nxt::StencilOperation::DecrementWrap:
|
||||
return MTLStencilOperationDecrementWrap;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
|
||||
: DepthStencilStateBase(builder), device(device) {
|
||||
mtlDepthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
||||
MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
||||
|
||||
if (DepthIsEnabled()) {
|
||||
if (DepthTestEnabled()) {
|
||||
auto& depth = GetDepth();
|
||||
mtlDepthStencilDescriptor.depthCompareFunction = DepthStencilCompareFunction(depth.compareFunction);
|
||||
switch (depth.depthWriteMode) {
|
||||
case nxt::DepthWriteMode::Disabled:
|
||||
mtlDepthStencilDescriptor.depthWriteEnabled = false;
|
||||
break;
|
||||
case nxt::DepthWriteMode::Enabled:
|
||||
mtlDepthStencilDescriptor.depthWriteEnabled = true;
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
mtlDepthStencilDescriptor.depthCompareFunction = MetalDepthStencilCompareFunction(depth.compareFunction);
|
||||
mtlDepthStencilDescriptor.depthWriteEnabled = depth.depthWriteEnabled;
|
||||
}
|
||||
|
||||
if (StencilIsEnabled()) {
|
||||
auto& stencil = GetStencil();
|
||||
|
||||
if (StencilTestEnabled()) {
|
||||
MTLStencilDescriptor* backFaceStencil = [MTLStencilDescriptor new];
|
||||
MTLStencilDescriptor* frontFaceStencil = [MTLStencilDescriptor new];
|
||||
|
||||
auto& back = GetBackStencil();
|
||||
auto& front = GetFrontStencil();
|
||||
backFaceStencil.stencilCompareFunction = MetalDepthStencilCompareFunction(stencil.back.compareFunction);
|
||||
backFaceStencil.stencilFailureOperation = MetalStencilOperation(stencil.back.stencilFail);
|
||||
backFaceStencil.depthFailureOperation = MetalStencilOperation(stencil.back.depthFail);
|
||||
backFaceStencil.depthStencilPassOperation = MetalStencilOperation(stencil.back.depthStencilPass);
|
||||
backFaceStencil.readMask = stencil.back.mask;
|
||||
backFaceStencil.writeMask = stencil.back.mask;
|
||||
|
||||
backFaceStencil.stencilCompareFunction = DepthStencilCompareFunction(back.compareFunction);
|
||||
backFaceStencil.stencilFailureOperation = StencilOperation(back.stencilFail);
|
||||
backFaceStencil.depthFailureOperation = StencilOperation(back.depthFail);
|
||||
backFaceStencil.depthStencilPassOperation = StencilOperation(back.stencilPass);
|
||||
backFaceStencil.readMask = back.readMask;
|
||||
backFaceStencil.writeMask = back.writeMask;
|
||||
|
||||
frontFaceStencil.stencilCompareFunction = DepthStencilCompareFunction(front.compareFunction);
|
||||
frontFaceStencil.stencilFailureOperation = StencilOperation(front.stencilFail);
|
||||
frontFaceStencil.depthFailureOperation = StencilOperation(front.depthFail);
|
||||
frontFaceStencil.depthStencilPassOperation = StencilOperation(front.stencilPass);
|
||||
frontFaceStencil.readMask = front.readMask;
|
||||
frontFaceStencil.writeMask = front.writeMask;
|
||||
frontFaceStencil.stencilCompareFunction = MetalDepthStencilCompareFunction(stencil.front.compareFunction);
|
||||
frontFaceStencil.stencilFailureOperation = MetalStencilOperation(stencil.front.stencilFail);
|
||||
frontFaceStencil.depthFailureOperation = MetalStencilOperation(stencil.front.depthFail);
|
||||
frontFaceStencil.depthStencilPassOperation = MetalStencilOperation(stencil.front.depthStencilPass);
|
||||
frontFaceStencil.readMask = stencil.front.mask;
|
||||
frontFaceStencil.writeMask = stencil.front.mask;
|
||||
|
||||
mtlDepthStencilDescriptor.backFaceStencil = backFaceStencil;
|
||||
mtlDepthStencilDescriptor.frontFaceStencil = frontFaceStencil;
|
||||
|
@ -758,15 +743,17 @@ namespace metal {
|
|||
[frontFaceStencil release];
|
||||
}
|
||||
|
||||
mtlDepthStencilState = [device->GetMTLDevice() newDepthStencilStateWithDescriptor:mtlDepthStencilDescriptor];
|
||||
[mtlDepthStencilDescriptor release];
|
||||
}
|
||||
|
||||
DepthStencilState::~DepthStencilState() {
|
||||
[mtlDepthStencilDescriptor release];
|
||||
mtlDepthStencilDescriptor = nil;
|
||||
[mtlDepthStencilState release];
|
||||
mtlDepthStencilState = nil;
|
||||
}
|
||||
|
||||
MTLDepthStencilDescriptor* DepthStencilState::GetMTLDepthStencilDescriptor() {
|
||||
return mtlDepthStencilDescriptor;
|
||||
id<MTLDepthStencilState> DepthStencilState::GetMTLDepthStencilState() {
|
||||
return mtlDepthStencilState;
|
||||
}
|
||||
|
||||
// InputState
|
||||
|
@ -914,24 +901,17 @@ namespace metal {
|
|||
return;
|
||||
}
|
||||
|
||||
DepthStencilState* depthStencilState = ToBackend(GetDepthStencilState());
|
||||
MTLDepthStencilDescriptor* dsDesc = depthStencilState->GetMTLDepthStencilDescriptor();
|
||||
mtlDepthStencilState = [device->GetMTLDevice()
|
||||
newDepthStencilStateWithDescriptor:dsDesc];
|
||||
|
||||
[descriptor release];
|
||||
}
|
||||
}
|
||||
|
||||
Pipeline::~Pipeline() {
|
||||
[mtlRenderPipelineState release];
|
||||
[mtlDepthStencilState release];
|
||||
[mtlComputePipelineState release];
|
||||
}
|
||||
|
||||
void Pipeline::Encode(id<MTLRenderCommandEncoder> encoder) {
|
||||
ASSERT(!IsCompute());
|
||||
[encoder setDepthStencilState:mtlDepthStencilState];
|
||||
[encoder setRenderPipelineState:mtlRenderPipelineState];
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "common/Commands.h"
|
||||
#include "OpenGLBackend.h"
|
||||
#include "PersistentPipelineStateGL.h"
|
||||
#include "PipelineGL.h"
|
||||
#include "PipelineLayoutGL.h"
|
||||
#include "SamplerGL.h"
|
||||
|
@ -26,6 +27,8 @@
|
|||
namespace backend {
|
||||
namespace opengl {
|
||||
|
||||
PersistentPipelineState persistentPipelineState;
|
||||
|
||||
CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder)
|
||||
: CommandBufferBase(builder), device(device), commands(builder->AcquireCommands()) {
|
||||
}
|
||||
|
@ -144,7 +147,7 @@ namespace opengl {
|
|||
case Command::SetPipeline:
|
||||
{
|
||||
SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
|
||||
ToBackend(cmd->pipeline)->ApplyNow();
|
||||
ToBackend(cmd->pipeline)->ApplyNow(persistentPipelineState);
|
||||
lastPipeline = ToBackend(cmd->pipeline).Get();
|
||||
}
|
||||
break;
|
||||
|
@ -182,7 +185,8 @@ namespace opengl {
|
|||
{
|
||||
SetStencilReferenceCmd* cmd = commands.NextCommand<SetStencilReferenceCmd>();
|
||||
DepthStencilState* depthStencilState = ToBackend(lastPipeline->GetDepthStencilState());
|
||||
depthStencilState->ApplyStencilReferenceNow(cmd->backReference, cmd->frontReference);
|
||||
persistentPipelineState.UpdateStencilReference(cmd->reference);
|
||||
persistentPipelineState.ApplyStencilNow();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "OpenGLBackend.h"
|
||||
#include "CommandBufferGL.h"
|
||||
#include "PersistentPipelineStateGL.h"
|
||||
#include "PipelineGL.h"
|
||||
#include "PipelineLayoutGL.h"
|
||||
#include "SamplerGL.h"
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace opengl {
|
|||
*device = reinterpret_cast<nxtDevice>(new Device);
|
||||
}
|
||||
|
||||
static GLuint OpenGLCompareFunction(nxt::CompareFunction compareFunction) {
|
||||
GLuint OpenGLCompareFunction(nxt::CompareFunction compareFunction) {
|
||||
switch (compareFunction) {
|
||||
case nxt::CompareFunction::Never:
|
||||
return GL_NEVER;
|
||||
|
@ -68,7 +68,7 @@ namespace opengl {
|
|||
}
|
||||
}
|
||||
|
||||
static GLuint OpenGLStencilOperation(nxt::StencilOperation stencilOperation) {
|
||||
GLuint OpenGLStencilOperation(nxt::StencilOperation stencilOperation) {
|
||||
switch (stencilOperation) {
|
||||
case nxt::StencilOperation::Keep:
|
||||
return GL_KEEP;
|
||||
|
@ -188,69 +188,6 @@ namespace opengl {
|
|||
|
||||
DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder)
|
||||
: DepthStencilStateBase(builder), device(device) {
|
||||
|
||||
}
|
||||
|
||||
void DepthStencilState::ApplyNow() {
|
||||
if (DepthIsEnabled()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
auto& depth = GetDepth();
|
||||
glDepthFunc(OpenGLCompareFunction(depth.compareFunction));
|
||||
switch (depth.depthWriteMode) {
|
||||
case nxt::DepthWriteMode::Disabled:
|
||||
glDepthMask(GL_FALSE);
|
||||
break;
|
||||
case nxt::DepthWriteMode::Enabled:
|
||||
glDepthMask(GL_TRUE);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (StencilIsEnabled()) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
auto& back = GetBackStencil();
|
||||
auto& front = GetFrontStencil();
|
||||
|
||||
glStencilOpSeparate(GL_BACK,
|
||||
OpenGLStencilOperation(back.stencilFail),
|
||||
OpenGLStencilOperation(back.depthFail),
|
||||
OpenGLStencilOperation(back.stencilPass)
|
||||
);
|
||||
glStencilOpSeparate(GL_FRONT,
|
||||
OpenGLStencilOperation(front.stencilFail),
|
||||
OpenGLStencilOperation(front.depthFail),
|
||||
OpenGLStencilOperation(front.stencilPass)
|
||||
);
|
||||
|
||||
glStencilMaskSeparate(GL_BACK, back.writeMask);
|
||||
glStencilMaskSeparate(GL_FRONT, front.writeMask);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void DepthStencilState::ApplyStencilReferenceNow(uint32_t backReference, uint32_t frontReference) {
|
||||
if (StencilIsEnabled()) {
|
||||
auto& back = GetBackStencil();
|
||||
auto& front = GetFrontStencil();
|
||||
glStencilFuncSeparate(GL_BACK,
|
||||
OpenGLCompareFunction(back.compareFunction),
|
||||
backReference,
|
||||
back.readMask
|
||||
);
|
||||
glStencilFuncSeparate(GL_FRONT,
|
||||
OpenGLCompareFunction(front.compareFunction),
|
||||
frontReference,
|
||||
front.readMask
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// InputState
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace opengl {
|
|||
class CommandBuffer;
|
||||
class DepthStencilState;
|
||||
class InputState;
|
||||
class PersistentPipelineState;
|
||||
class Pipeline;
|
||||
class PipelineLayout;
|
||||
class Queue;
|
||||
|
@ -74,6 +75,9 @@ namespace opengl {
|
|||
return ToBackendBase<OpenGLBackendTraits>(common);
|
||||
}
|
||||
|
||||
GLuint OpenGLCompareFunction(nxt::CompareFunction compareFunction);
|
||||
GLuint OpenGLStencilOperation(nxt::StencilOperation stencilOperation);
|
||||
|
||||
// Definition of backend types
|
||||
class Device : public DeviceBase {
|
||||
public:
|
||||
|
@ -139,8 +143,6 @@ namespace opengl {
|
|||
class DepthStencilState : public DepthStencilStateBase {
|
||||
public:
|
||||
DepthStencilState(Device* device, DepthStencilStateBuilder* builder);
|
||||
void ApplyNow();
|
||||
void ApplyStencilReferenceNow(uint32_t backReference, uint32_t frontReference);
|
||||
|
||||
private:
|
||||
Device* device;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright 2017 The NXT Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "PersistentPipelineStateGL.h"
|
||||
|
||||
#include "OpenGLBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace opengl {
|
||||
|
||||
PersistentPipelineState::PersistentPipelineState() {
|
||||
dirtyFields.set(); // initialize all fields as dirty
|
||||
}
|
||||
|
||||
// when a field on PersistentPipelineState::State changes, mark its starting location as dirty
|
||||
#define SET_FIELD(field, destination, value) { \
|
||||
if (state.destination != value) { \
|
||||
dirtyFields.set(field); \
|
||||
state.destination = value; \
|
||||
} \
|
||||
}
|
||||
|
||||
void PersistentPipelineState::UpdateDepthStencilInfo(const DepthStencilStateBase* const depthStencilState) {
|
||||
auto& depth = depthStencilState->GetDepth();
|
||||
SET_FIELD(DEPTH_COMPARE_FUNCTION, depthInfo.compareFunction, depth.compareFunction)
|
||||
SET_FIELD(DEPTH_WRITE_ENABLED, depthInfo.depthWriteEnabled, depth.depthWriteEnabled)
|
||||
SET_FIELD(DEPTH_ENABLED, depthEnabled, depthStencilState->DepthTestEnabled())
|
||||
|
||||
auto& stencil = depthStencilState->GetStencil();
|
||||
SET_FIELD(STENCIL_ENABLED, stencilEnabled, depthStencilState->StencilTestEnabled())
|
||||
|
||||
SET_FIELD(STENCIL_BACK_COMPARE_FUNCTION, stencilInfo.back.compareFunction, stencil.back.compareFunction)
|
||||
SET_FIELD(STENCIL_BACK_STENCIL_FAIL, stencilInfo.back.stencilFail, stencil.back.stencilFail)
|
||||
SET_FIELD(STENCIL_BACK_DEPTH_FAIL, stencilInfo.back.depthFail, stencil.back.depthFail)
|
||||
SET_FIELD(STENCIL_BACK_DEPTH_STENCIL_PASS, stencilInfo.back.depthStencilPass, stencil.back.depthStencilPass)
|
||||
SET_FIELD(STENCIL_BACK_MASK, stencilInfo.back.mask, stencil.back.mask)
|
||||
|
||||
SET_FIELD(STENCIL_FRONT_COMPARE_FUNCTION, stencilInfo.front.compareFunction, stencil.front.compareFunction)
|
||||
SET_FIELD(STENCIL_FRONT_STENCIL_FAIL, stencilInfo.front.stencilFail, stencil.front.stencilFail)
|
||||
SET_FIELD(STENCIL_FRONT_DEPTH_FAIL, stencilInfo.front.depthFail, stencil.front.depthFail)
|
||||
SET_FIELD(STENCIL_FRONT_DEPTH_STENCIL_PASS, stencilInfo.front.depthStencilPass, stencil.front.depthStencilPass)
|
||||
SET_FIELD(STENCIL_FRONT_MASK, stencilInfo.front.mask, stencil.front.mask)
|
||||
}
|
||||
|
||||
void PersistentPipelineState::UpdateStencilReference(uint32_t stencilReference) {
|
||||
SET_FIELD(STENCIL_REFERENCE, stencilReference, stencilReference)
|
||||
}
|
||||
|
||||
#undef SET_FIELD
|
||||
|
||||
bool PersistentPipelineState::IsDirty(Field field) const {
|
||||
return dirtyFields.test(field);
|
||||
}
|
||||
|
||||
void PersistentPipelineState::CleanField(Field field) {
|
||||
dirtyFields.reset(field);
|
||||
}
|
||||
|
||||
void PersistentPipelineState::ApplyDepthNow() {
|
||||
if (IsDirty(DEPTH_ENABLED)) {
|
||||
if (state.depthEnabled) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
CleanField(DEPTH_ENABLED);
|
||||
}
|
||||
if (IsDirty(DEPTH_WRITE_ENABLED)) {
|
||||
if (state.depthInfo.depthWriteEnabled) {
|
||||
glDepthMask(GL_TRUE);
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
CleanField(DEPTH_WRITE_ENABLED);
|
||||
}
|
||||
if (IsDirty(DEPTH_COMPARE_FUNCTION)) {
|
||||
glDepthFunc(OpenGLCompareFunction(state.depthInfo.compareFunction));
|
||||
CleanField(DEPTH_COMPARE_FUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
void PersistentPipelineState::ApplyStencilNow() {
|
||||
if (IsDirty(STENCIL_ENABLED)) {
|
||||
if (state.stencilEnabled) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
} else {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
CleanField(STENCIL_ENABLED);
|
||||
}
|
||||
|
||||
if (IsDirty(STENCIL_BACK_STENCIL_FAIL) ||
|
||||
IsDirty(STENCIL_BACK_DEPTH_FAIL) ||
|
||||
IsDirty(STENCIL_BACK_DEPTH_STENCIL_PASS)) {
|
||||
|
||||
glStencilOpSeparate(GL_BACK,
|
||||
OpenGLStencilOperation(state.stencilInfo.back.stencilFail),
|
||||
OpenGLStencilOperation(state.stencilInfo.back.depthFail),
|
||||
OpenGLStencilOperation(state.stencilInfo.back.depthStencilPass)
|
||||
);
|
||||
|
||||
CleanField(STENCIL_BACK_STENCIL_FAIL);
|
||||
CleanField(STENCIL_BACK_DEPTH_FAIL);
|
||||
CleanField(STENCIL_BACK_DEPTH_STENCIL_PASS);
|
||||
}
|
||||
if (IsDirty(STENCIL_BACK_COMPARE_FUNCTION) ||
|
||||
IsDirty(STENCIL_REFERENCE) ||
|
||||
IsDirty(STENCIL_BACK_MASK)) {
|
||||
|
||||
glStencilFuncSeparate(GL_BACK,
|
||||
OpenGLCompareFunction(state.stencilInfo.back.compareFunction),
|
||||
state.stencilReference,
|
||||
state.stencilInfo.back.mask
|
||||
);
|
||||
if (IsDirty(STENCIL_BACK_MASK)) {
|
||||
glStencilMaskSeparate(GL_BACK, state.stencilInfo.back.mask);
|
||||
}
|
||||
|
||||
CleanField(STENCIL_BACK_COMPARE_FUNCTION);
|
||||
CleanField(STENCIL_BACK_MASK);
|
||||
}
|
||||
|
||||
if (IsDirty(STENCIL_FRONT_STENCIL_FAIL) ||
|
||||
IsDirty(STENCIL_FRONT_DEPTH_FAIL) ||
|
||||
IsDirty(STENCIL_FRONT_DEPTH_STENCIL_PASS)) {
|
||||
|
||||
glStencilOpSeparate(GL_FRONT,
|
||||
OpenGLStencilOperation(state.stencilInfo.front.stencilFail),
|
||||
OpenGLStencilOperation(state.stencilInfo.front.depthFail),
|
||||
OpenGLStencilOperation(state.stencilInfo.front.depthStencilPass)
|
||||
);
|
||||
|
||||
CleanField(STENCIL_FRONT_STENCIL_FAIL);
|
||||
CleanField(STENCIL_FRONT_DEPTH_FAIL);
|
||||
CleanField(STENCIL_FRONT_DEPTH_STENCIL_PASS);
|
||||
}
|
||||
if (IsDirty(STENCIL_FRONT_COMPARE_FUNCTION) ||
|
||||
IsDirty(STENCIL_REFERENCE) ||
|
||||
IsDirty(STENCIL_FRONT_MASK)) {
|
||||
|
||||
glStencilFuncSeparate(GL_FRONT,
|
||||
OpenGLCompareFunction(state.stencilInfo.front.compareFunction),
|
||||
state.stencilReference,
|
||||
state.stencilInfo.front.mask
|
||||
);
|
||||
if (IsDirty(STENCIL_FRONT_MASK)) {
|
||||
glStencilMaskSeparate(GL_FRONT, state.stencilInfo.front.mask);
|
||||
}
|
||||
|
||||
CleanField(STENCIL_FRONT_COMPARE_FUNCTION);
|
||||
CleanField(STENCIL_FRONT_MASK);
|
||||
}
|
||||
|
||||
CleanField(STENCIL_REFERENCE); // clean this last because its used for both the back and front functions
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2017 The NXT Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef BACKEND_OPENGL_PERSISTENTPIPELINESTATE_H_
|
||||
#define BACKEND_OPENGL_PERSISTENTPIPELINESTATE_H_
|
||||
|
||||
#include "common/DepthStencilState.h"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
namespace backend {
|
||||
namespace opengl {
|
||||
|
||||
class PersistentPipelineState {
|
||||
public:
|
||||
PersistentPipelineState();
|
||||
void UpdateDepthStencilInfo(const DepthStencilStateBase* const depthStencilState);
|
||||
void UpdateStencilReference(uint32_t stencilReference);
|
||||
|
||||
void ApplyDepthNow();
|
||||
void ApplyStencilNow();
|
||||
|
||||
enum Field {
|
||||
DEPTH_COMPARE_FUNCTION,
|
||||
DEPTH_WRITE_ENABLED,
|
||||
DEPTH_ENABLED,
|
||||
STENCIL_ENABLED,
|
||||
STENCIL_BACK_COMPARE_FUNCTION,
|
||||
STENCIL_BACK_STENCIL_FAIL,
|
||||
STENCIL_BACK_DEPTH_FAIL,
|
||||
STENCIL_BACK_DEPTH_STENCIL_PASS,
|
||||
STENCIL_BACK_MASK,
|
||||
STENCIL_FRONT_COMPARE_FUNCTION,
|
||||
STENCIL_FRONT_STENCIL_FAIL,
|
||||
STENCIL_FRONT_DEPTH_FAIL,
|
||||
STENCIL_FRONT_DEPTH_STENCIL_PASS,
|
||||
STENCIL_FRONT_MASK,
|
||||
STENCIL_REFERENCE,
|
||||
Count
|
||||
};
|
||||
|
||||
struct State {
|
||||
bool depthEnabled;
|
||||
bool stencilEnabled;
|
||||
DepthStencilStateBase::DepthInfo depthInfo;
|
||||
DepthStencilStateBase::StencilInfo stencilInfo;
|
||||
uint32_t stencilReference;
|
||||
};
|
||||
|
||||
private:
|
||||
State state;
|
||||
std::bitset<Field::Count> dirtyFields;
|
||||
|
||||
inline bool IsDirty(Field field) const;
|
||||
inline void CleanField(Field field);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BACKEND_OPENGL_PERSISTENTPIPELINESTATE_H_
|
|
@ -15,6 +15,7 @@
|
|||
#include "PipelineGL.h"
|
||||
|
||||
#include "OpenGLBackend.h"
|
||||
#include "PersistentPipelineStateGL.h"
|
||||
#include "PipelineLayoutGL.h"
|
||||
#include "ShaderModuleGL.h"
|
||||
|
||||
|
@ -202,13 +203,15 @@ namespace opengl {
|
|||
return program;
|
||||
}
|
||||
|
||||
void Pipeline::ApplyNow() {
|
||||
void Pipeline::ApplyNow(PersistentPipelineState &persistentPipelineState) {
|
||||
glUseProgram(program);
|
||||
|
||||
auto inputState = ToBackend(GetInputState());
|
||||
glBindVertexArray(inputState->GetVAO());
|
||||
auto depthStencilState = ToBackend(GetDepthStencilState());
|
||||
depthStencilState->ApplyNow();
|
||||
|
||||
persistentPipelineState.UpdateDepthStencilInfo(GetDepthStencilState());
|
||||
persistentPipelineState.ApplyDepthNow();
|
||||
persistentPipelineState.ApplyStencilNow();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace backend {
|
|||
namespace opengl {
|
||||
|
||||
class Device;
|
||||
class PersistentPipelineState;
|
||||
class ShaderModule;
|
||||
|
||||
class Pipeline : public PipelineBase {
|
||||
|
@ -39,7 +40,7 @@ namespace opengl {
|
|||
const std::vector<GLuint>& GetTextureUnitsForTexture(GLuint index) const;
|
||||
GLuint GetProgramHandle() const;
|
||||
|
||||
void ApplyNow();
|
||||
void ApplyNow(PersistentPipelineState &persistentPipelineState);
|
||||
|
||||
private:
|
||||
GLuint program;
|
||||
|
|
Loading…
Reference in New Issue