v3dv: implement dynamic stencil states

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga
2020-02-04 17:43:49 +01:00
committed by Marge Bot
parent d84458b5de
commit 134afdfd32
3 changed files with 217 additions and 17 deletions
+130 -5
View File
@@ -33,6 +33,21 @@ const struct v3dv_dynamic_state default_dynamic_state = {
.scissor = {
.count = 0,
},
.stencil_compare_mask =
{
.front = ~0u,
.back = ~0u,
},
.stencil_write_mask =
{
.front = ~0u,
.back = ~0u,
},
.stencil_reference =
{
.front = 0u,
.back = 0u,
},
};
void
@@ -1412,6 +1427,30 @@ bind_dynamic_state(struct v3dv_cmd_buffer *cmd_buffer,
}
}
if (copy_mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) {
if (memcmp(&dest->stencil_compare_mask, &src->stencil_compare_mask,
sizeof(src->stencil_compare_mask))) {
dest->stencil_compare_mask = src->stencil_compare_mask;
dest_mask |= V3DV_DYNAMIC_STENCIL_COMPARE_MASK;
}
}
if (copy_mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK) {
if (memcmp(&dest->stencil_write_mask, &src->stencil_write_mask,
sizeof(src->stencil_write_mask))) {
dest->stencil_write_mask = src->stencil_write_mask;
dest_mask |= V3DV_DYNAMIC_STENCIL_WRITE_MASK;
}
}
if (copy_mask & V3DV_DYNAMIC_STENCIL_REFERENCE) {
if (memcmp(&dest->stencil_reference, &src->stencil_reference,
sizeof(src->stencil_reference))) {
dest->stencil_reference = src->stencil_reference;
dest_mask |= V3DV_DYNAMIC_STENCIL_REFERENCE;
}
}
cmd_buffer->state.dirty |= dest_mask;
}
@@ -1686,6 +1725,51 @@ emit_viewport(struct v3dv_cmd_buffer *cmd_buffer)
}
}
static void
emit_stencil(struct v3dv_cmd_buffer *cmd_buffer)
{
struct v3dv_job *job = cmd_buffer->state.job;
assert(job);
struct v3dv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct v3dv_dynamic_state *dynamic_state = &cmd_buffer->state.dynamic;
const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK |
V3DV_DYNAMIC_STENCIL_WRITE_MASK |
V3DV_DYNAMIC_STENCIL_REFERENCE;
for (uint32_t i = 0; i < 2; i++) {
if (pipeline->emit_stencil_cfg[i]) {
/* Our dynamic state bits signal whether a particular state is
* taken from the static pipeline definition (so it is not dynamic).
*/
if (!(dynamic_state->mask & dynamic_stencil_states)) {
/* At least one of the stencil states is dynamic */
cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
pipeline->stencil_cfg[i], config) {
if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK)) {
config.stencil_test_mask =
i == 0 ? dynamic_state->stencil_compare_mask.front :
dynamic_state->stencil_compare_mask.back;
}
if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK)) {
config.stencil_write_mask =
i == 0 ? dynamic_state->stencil_write_mask.front :
dynamic_state->stencil_write_mask.back;
}
if (!(dynamic_state->mask & V3DV_DYNAMIC_STENCIL_REFERENCE)) {
config.stencil_ref_value =
i == 0 ? dynamic_state->stencil_reference.front :
dynamic_state->stencil_reference.back;
}
}
} else {
cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]);
}
}
}
}
static void
cmd_buffer_emit_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer)
{
@@ -1821,11 +1905,7 @@ cmd_buffer_emit_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer)
config.early_z_updates_enable = job->ez_state != VC5_EZ_DISABLED;
}
if (pipeline->emit_stencil_cfg[0]) {
cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[0]);
if (pipeline->emit_stencil_cfg[1])
cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[1]);
}
emit_stencil(cmd_buffer);
/* FIXME: hardcoded values */
cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags);
@@ -1980,3 +2060,48 @@ v3dv_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_VERTEX_BUFFER;
}
void
v3dv_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t compareMask)
{
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
cmd_buffer->state.dynamic.stencil_compare_mask.front = compareMask & 0xff;
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
cmd_buffer->state.dynamic.stencil_compare_mask.back = compareMask & 0xff;
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK;
}
void
v3dv_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t writeMask)
{
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
cmd_buffer->state.dynamic.stencil_write_mask.front = writeMask & 0xff;
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
cmd_buffer->state.dynamic.stencil_write_mask.back = writeMask & 0xff;
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK;
}
void
v3dv_CmdSetStencilReference(VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t reference)
{
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
cmd_buffer->state.dynamic.stencil_reference.front = reference & 0xff;
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
cmd_buffer->state.dynamic.stencil_reference.back = reference & 0xff;
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE;
}
+61 -8
View File
@@ -870,6 +870,12 @@ v3dv_dynamic_state_mask(VkDynamicState state)
return V3DV_DYNAMIC_VIEWPORT;
case VK_DYNAMIC_STATE_SCISSOR:
return V3DV_DYNAMIC_SCISSOR;
case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
return V3DV_DYNAMIC_STENCIL_COMPARE_MASK;
case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
return V3DV_DYNAMIC_STENCIL_WRITE_MASK;
case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
return V3DV_DYNAMIC_STENCIL_REFERENCE;
default:
unreachable("Unhandled dynamic state");
}
@@ -936,6 +942,27 @@ pipeline_init_dynamic_state(struct v3dv_pipeline *pipeline,
}
}
if (needed_states & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) {
dynamic->stencil_compare_mask.front =
pCreateInfo->pDepthStencilState->front.compareMask;
dynamic->stencil_compare_mask.back =
pCreateInfo->pDepthStencilState->back.compareMask;
}
if (needed_states & V3DV_DYNAMIC_STENCIL_WRITE_MASK) {
dynamic->stencil_write_mask.front =
pCreateInfo->pDepthStencilState->front.writeMask;
dynamic->stencil_write_mask.back =
pCreateInfo->pDepthStencilState->back.writeMask;
}
if (needed_states & V3DV_DYNAMIC_STENCIL_REFERENCE) {
dynamic->stencil_reference.front =
pCreateInfo->pDepthStencilState->front.reference;
dynamic->stencil_reference.back =
pCreateInfo->pDepthStencilState->back.reference;
}
pipeline->dynamic_state.mask = states;
}
@@ -1022,7 +1049,8 @@ translate_stencil_op(enum pipe_stencil_op op)
}
static void
pack_single_stencil_cfg(uint8_t *stencil_cfg,
pack_single_stencil_cfg(struct v3dv_pipeline *pipeline,
uint8_t *stencil_cfg,
bool is_front,
bool is_back,
const VkStencilOpState *stencil_state)
@@ -1037,10 +1065,22 @@ pack_single_stencil_cfg(uint8_t *stencil_cfg,
*
* In our case, 's' is always 8, so we clamp to that to prevent our packing
* functions to assert in debug mode if they see larger values.
*
* If we have dynamic state we need to make sure we set the corresponding
* state bits to 0, since cl_emit_with_prepacked ORs the new value with
* the old.
*/
const uint8_t write_mask = stencil_state->writeMask & 0xff;
const uint8_t compare_mask = stencil_state->compareMask & 0xff;
const uint8_t reference = stencil_state->reference & 0xff;
const uint8_t write_mask =
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK ?
stencil_state->writeMask & 0xff : 0;
const uint8_t compare_mask =
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
stencil_state->compareMask & 0xff : 0;
const uint8_t reference =
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
stencil_state->reference & 0xff : 0;
v3dv_pack(stencil_cfg, STENCIL_CFG, config) {
config.front_config = is_front;
@@ -1064,18 +1104,31 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline,
if (!ds_info || !ds_info->stencilTestEnable)
return;
const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK |
V3DV_DYNAMIC_STENCIL_WRITE_MASK |
V3DV_DYNAMIC_STENCIL_REFERENCE;
/* If front != back or we have dynamic stencil state we can't emit a single
* packet for both faces.
*/
bool needs_front_and_back = false;
if (!(pipeline->dynamic_state.mask & dynamic_stencil_states) ||
memcmp(&ds_info->front, &ds_info->back, sizeof(ds_info->front)))
needs_front_and_back = true;
/* If the front and back configurations are the same we can emit both with
* a single packet.
*/
pipeline->emit_stencil_cfg[0] = true;
if (memcmp(&ds_info->front, &ds_info->back, sizeof(ds_info->front)) == 0) {
pack_single_stencil_cfg(pipeline->stencil_cfg[0],
if (!needs_front_and_back) {
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
true, true, &ds_info->front);
} else {
pipeline->emit_stencil_cfg[1] = true;
pack_single_stencil_cfg(pipeline->stencil_cfg[0],
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
true, false, &ds_info->front);
pack_single_stencil_cfg(pipeline->stencil_cfg[1],
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[1],
false, true, &ds_info->back);
}
}
+26 -4
View File
@@ -434,7 +434,10 @@ struct v3dv_scissor_state {
enum v3dv_dynamic_state_bits {
V3DV_DYNAMIC_VIEWPORT = 1 << 0,
V3DV_DYNAMIC_SCISSOR = 1 << 1,
V3DV_DYNAMIC_ALL = (1 << 2) - 1,
V3DV_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 2,
V3DV_DYNAMIC_STENCIL_WRITE_MASK = 1 << 3,
V3DV_DYNAMIC_STENCIL_REFERENCE = 1 << 4,
V3DV_DYNAMIC_ALL = (1 << 5) - 1,
};
/* To track which cmd buffer elements are "dirty" so would need an
@@ -444,9 +447,13 @@ enum v3dv_dynamic_state_bits {
enum v3dv_cmd_dirty_bits {
V3DV_CMD_DIRTY_DYNAMIC_VIEWPORT = 1 << 0,
V3DV_CMD_DIRTY_DYNAMIC_SCISSOR = 1 << 1,
V3DV_CMD_DIRTY_DYNAMIC_ALL = (1 << 2) - 1,
V3DV_CMD_DIRTY_PIPELINE = 1 << 2,
V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 3,
V3DV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 2,
V3DV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK = 1 << 3,
V3DV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE = 1 << 4,
V3DV_CMD_DIRTY_DYNAMIC_ALL = (1 << 5) - 1,
V3DV_CMD_DIRTY_PIPELINE = 1 << 5,
V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 6,
};
@@ -460,6 +467,21 @@ struct v3dv_dynamic_state {
struct v3dv_viewport_state viewport;
struct v3dv_scissor_state scissor;
struct {
uint32_t front;
uint32_t back;
} stencil_compare_mask;
struct {
uint32_t front;
uint32_t back;
} stencil_write_mask;
struct {
uint32_t front;
uint32_t back;
} stencil_reference;
};
extern const struct v3dv_dynamic_state default_dynamic_state;