v3dv: implement dynamic stencil states
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
committed by
Marge Bot
parent
d84458b5de
commit
134afdfd32
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user