v3dv: port dynamic state tracking to use Mesa Vulkan
Specifically to use the common vk_dynamic_graphics_state. The advantage of using the common struct is not only reducing the size of our custom one, but also using common helpers (like all those cmd buffer setters), and a lot of the logic that in the future will be used for other extensions. Some notes: * We still keep dirty flags, for things like PIPELINE, DESCRIPTOR_SETS, etc. Other driver do the same. FWIW, this is also an improvement, as before we were mixing those with the per-spec Vulkan dynamic info. * For the port viewport/scissor we still keep some data on a custom structure, as we cache the translate/scale info that is derived from scissor/viewport, but used in three different places. For that we also maintain a custom implementation of CmdSetViewport, that computes translate/scale, and call the common implementation. * We make the same for color_write_enables. The vulkan runtime saves it as a 8-bit bitset, with a bit per attachment. But when combining with color_write_mask you need a 32bit with 4 bits set per attachment. To avoid recompute it during emission, we also cache the color_write_enables, using the runtime just to track the dirty status. Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27609>
This commit is contained in:

committed by
Marge Bot

parent
858154b84e
commit
f2236065b7
@@ -31,7 +31,7 @@ float
|
||||
v3dv_get_aa_line_width(struct v3dv_pipeline *pipeline,
|
||||
struct v3dv_cmd_buffer *buffer)
|
||||
{
|
||||
float width = buffer->state.dynamic.line_width;
|
||||
float width = buffer->vk.dynamic_graphics_state.rs.line.width;
|
||||
|
||||
/* If line smoothing is enabled then we want to add some extra pixels to
|
||||
* the width in order to have some semi-transparent edges.
|
||||
@@ -833,6 +833,7 @@ v3dv_job_init(struct v3dv_job *job,
|
||||
*/
|
||||
cmd_buffer->state.dirty = ~0;
|
||||
cmd_buffer->state.dirty_descriptor_stages = ~0;
|
||||
vk_dynamic_graphics_state_dirty_all(&cmd_buffer->vk.dynamic_graphics_state);
|
||||
|
||||
/* Honor inheritance of occlusion queries in secondaries if requested */
|
||||
if (cmd_buffer->vk.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY &&
|
||||
@@ -1361,8 +1362,11 @@ cmd_buffer_ensure_render_pass_attachment_state(struct v3dv_cmd_buffer *cmd_buffe
|
||||
* to emit a new clip window to constraint it to the render area.
|
||||
*/
|
||||
static void
|
||||
constraint_clip_window_to_render_area(struct v3dv_cmd_buffer_state *state)
|
||||
constraint_clip_window_to_render_area(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
uint32_t min_render_x = state->render_area.offset.x;
|
||||
uint32_t min_render_y = state->render_area.offset.y;
|
||||
uint32_t max_render_x = min_render_x + state->render_area.extent.width - 1;
|
||||
@@ -1373,7 +1377,7 @@ constraint_clip_window_to_render_area(struct v3dv_cmd_buffer_state *state)
|
||||
uint32_t max_clip_y = min_clip_y + state->clip_window.extent.height - 1;
|
||||
if (min_render_x > min_clip_x || min_render_y > min_clip_y ||
|
||||
max_render_x < max_clip_x || max_render_y < max_clip_y) {
|
||||
state->dirty |= V3DV_CMD_DIRTY_SCISSOR;
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1396,7 +1400,7 @@ v3dv_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
|
||||
cmd_buffer_init_render_pass_attachment_state(cmd_buffer, pRenderPassBegin);
|
||||
|
||||
state->render_area = pRenderPassBegin->renderArea;
|
||||
constraint_clip_window_to_render_area(state);
|
||||
constraint_clip_window_to_render_area(cmd_buffer);
|
||||
|
||||
/* Setup for first subpass */
|
||||
v3dv_cmd_buffer_subpass_start(cmd_buffer, 0);
|
||||
@@ -2096,108 +2100,36 @@ v3dv_CmdExecuteCommands(VkCommandBuffer commandBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
/* This goes though the list of possible dynamic states in the pipeline and,
|
||||
* for those that are not configured as dynamic, copies relevant state into
|
||||
* the command buffer.
|
||||
static void
|
||||
cmd_buffer_copy_private_dynamic_state(struct v3dv_dynamic_state *dst,
|
||||
struct v3dv_dynamic_state *src,
|
||||
struct vk_dynamic_graphics_state *src_dyn)
|
||||
{
|
||||
if (BITSET_TEST(src_dyn->set, MESA_VK_DYNAMIC_VP_VIEWPORTS)) {
|
||||
typed_memcpy(dst->viewport.scale, src->viewport.scale,
|
||||
MAX_VIEWPORTS);
|
||||
typed_memcpy(dst->viewport.translate, src->viewport.translate,
|
||||
MAX_VIEWPORTS);
|
||||
}
|
||||
if (BITSET_TEST(src_dyn->set, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES))
|
||||
dst->color_write_enable = src->color_write_enable;
|
||||
}
|
||||
|
||||
/* This function copies relevant static state from the pipeline to the command
|
||||
* buffer state.
|
||||
*
|
||||
* Notice the Vulkan runtime uses the term 'dynamic' to refer to all state
|
||||
* that *could* be dynamic, even if it is not dynamic for a particular
|
||||
* pipeline, so the terminology used in the runtime may be a bit misleading.
|
||||
*/
|
||||
static void
|
||||
cmd_buffer_bind_pipeline_static_state(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
const struct v3dv_dynamic_state *src)
|
||||
struct v3dv_pipeline *pipeline)
|
||||
{
|
||||
struct v3dv_dynamic_state *dest = &cmd_buffer->state.dynamic;
|
||||
uint32_t dynamic_mask = src->mask;
|
||||
uint32_t dirty = 0;
|
||||
vk_cmd_set_dynamic_graphics_state(&cmd_buffer->vk, &pipeline->dynamic_graphics_state);
|
||||
cmd_buffer_copy_private_dynamic_state(&cmd_buffer->state.dynamic, &pipeline->dynamic,
|
||||
&pipeline->dynamic_graphics_state);
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_VIEWPORT)) {
|
||||
dest->viewport.count = src->viewport.count;
|
||||
if (memcmp(&dest->viewport.viewports, &src->viewport.viewports,
|
||||
src->viewport.count * sizeof(VkViewport))) {
|
||||
typed_memcpy(dest->viewport.viewports,
|
||||
src->viewport.viewports,
|
||||
src->viewport.count);
|
||||
typed_memcpy(dest->viewport.scale, src->viewport.scale,
|
||||
src->viewport.count);
|
||||
typed_memcpy(dest->viewport.translate, src->viewport.translate,
|
||||
src->viewport.count);
|
||||
dirty |= V3DV_CMD_DIRTY_VIEWPORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_SCISSOR)) {
|
||||
dest->scissor.count = src->scissor.count;
|
||||
if (memcmp(&dest->scissor.scissors, &src->scissor.scissors,
|
||||
src->scissor.count * sizeof(VkRect2D))) {
|
||||
typed_memcpy(dest->scissor.scissors,
|
||||
src->scissor.scissors, src->scissor.count);
|
||||
dirty |= V3DV_CMD_DIRTY_SCISSOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_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;
|
||||
dirty |= V3DV_CMD_DIRTY_STENCIL_COMPARE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_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;
|
||||
dirty |= V3DV_CMD_DIRTY_STENCIL_WRITE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_STENCIL_REFERENCE)) {
|
||||
if (memcmp(&dest->stencil_reference, &src->stencil_reference,
|
||||
sizeof(src->stencil_reference))) {
|
||||
dest->stencil_reference = src->stencil_reference;
|
||||
dirty |= V3DV_CMD_DIRTY_STENCIL_REFERENCE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_BLEND_CONSTANTS)) {
|
||||
if (memcmp(dest->blend_constants, src->blend_constants,
|
||||
sizeof(src->blend_constants))) {
|
||||
memcpy(dest->blend_constants, src->blend_constants,
|
||||
sizeof(src->blend_constants));
|
||||
dirty |= V3DV_CMD_DIRTY_BLEND_CONSTANTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_DEPTH_BIAS)) {
|
||||
if (memcmp(&dest->depth_bias, &src->depth_bias,
|
||||
sizeof(src->depth_bias))) {
|
||||
memcpy(&dest->depth_bias, &src->depth_bias, sizeof(src->depth_bias));
|
||||
dirty |= V3DV_CMD_DIRTY_DEPTH_BIAS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_DEPTH_BOUNDS)) {
|
||||
if (memcmp(&dest->depth_bounds, &src->depth_bounds,
|
||||
sizeof(src->depth_bounds))) {
|
||||
memcpy(&dest->depth_bounds, &src->depth_bounds, sizeof(src->depth_bounds));
|
||||
dirty |= V3DV_CMD_DIRTY_DEPTH_BOUNDS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_LINE_WIDTH)) {
|
||||
if (dest->line_width != src->line_width) {
|
||||
dest->line_width = src->line_width;
|
||||
dirty |= V3DV_CMD_DIRTY_LINE_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_mask & V3DV_DYNAMIC_COLOR_WRITE_ENABLE)) {
|
||||
if (dest->color_write_enable != src->color_write_enable) {
|
||||
dest->color_write_enable = src->color_write_enable;
|
||||
dirty |= V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_buffer->state.dynamic.mask = dynamic_mask;
|
||||
cmd_buffer->state.dirty |= dirty;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2210,13 +2142,12 @@ bind_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
* could have changed (through calls to vkCmdSetXXX) between bindings of
|
||||
* the same pipeline.
|
||||
*/
|
||||
cmd_buffer_bind_pipeline_static_state(cmd_buffer, &pipeline->dynamic_state);
|
||||
cmd_buffer_bind_pipeline_static_state(cmd_buffer, pipeline);
|
||||
|
||||
if (cmd_buffer->state.gfx.pipeline == pipeline)
|
||||
return;
|
||||
|
||||
cmd_buffer->state.gfx.pipeline = pipeline;
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_PIPELINE;
|
||||
}
|
||||
|
||||
@@ -2261,18 +2192,19 @@ v3dv_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
* and scale parameters.
|
||||
*/
|
||||
void
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state,
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
uint32_t vp_idx,
|
||||
float *translate_z, float *scale_z)
|
||||
{
|
||||
const struct v3dv_viewport_state *vp_state = &state->dynamic.viewport;
|
||||
const struct v3dv_viewport_state *vp_state = &cmd_buffer->state.dynamic.viewport;
|
||||
const struct vk_viewport_state *vk_vp_state = &cmd_buffer->vk.dynamic_graphics_state.vp;
|
||||
|
||||
float t = vp_state->translate[vp_idx][2];
|
||||
float s = vp_state->scale[vp_idx][2];
|
||||
|
||||
assert(state->gfx.pipeline);
|
||||
if (state->gfx.pipeline->negative_one_to_one) {
|
||||
t = (t + vp_state->viewports[vp_idx].maxDepth) * 0.5f;
|
||||
assert(cmd_buffer->state.gfx.pipeline);
|
||||
if (cmd_buffer->state.gfx.pipeline->negative_one_to_one) {
|
||||
t = (t + vk_vp_state->viewports[vp_idx].maxDepth) * 0.5f;
|
||||
s *= 0.5f;
|
||||
}
|
||||
|
||||
@@ -2283,6 +2215,38 @@ v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state,
|
||||
*scale_z = s;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t attachmentCount,
|
||||
const VkBool32 *pColorWriteEnables)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct v3dv_dynamic_state *v3dv_dyn = &cmd_buffer->state.dynamic;
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
uint32_t color_write_enable = 0;
|
||||
|
||||
/* Vulkan runtime computes color_write_enable as an 8-bit bitset, setting a
|
||||
* bit per attachment. But when emitting, it is combined with the
|
||||
* color_write_mask, that is stored as a 32-bit mask (one bit per channel,
|
||||
* per attachment). So we store the color_write_enable as a 32-bit mask
|
||||
* ourselves.
|
||||
*/
|
||||
for (uint32_t i = 0; i < attachmentCount; i++)
|
||||
color_write_enable |= pColorWriteEnables[i] ? (0xfu << (i * 4)) : 0;
|
||||
|
||||
if (v3dv_dyn->color_write_enable == color_write_enable)
|
||||
return;
|
||||
|
||||
v3dv_dyn->color_write_enable = color_write_enable;
|
||||
BITSET_SET(dyn->set, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES);
|
||||
BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES);
|
||||
}
|
||||
|
||||
/* We keep a custom CmdSetViewport because we want to cache the outcome of
|
||||
* viewport_compute_xform, and because we need to set the viewport count. This
|
||||
* is specially relevant to our case because we are pushing/popping the
|
||||
* dynamic state as part of the meta operations.
|
||||
*/
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetViewport(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstViewport,
|
||||
@@ -2290,64 +2254,47 @@ v3dv_CmdSetViewport(VkCommandBuffer commandBuffer,
|
||||
const VkViewport *pViewports)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
const uint32_t total_count = firstViewport + viewportCount;
|
||||
struct v3dv_dynamic_state *v3dv_dyn = &cmd_buffer->state.dynamic;
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
const uint32_t total_count = firstViewport + viewportCount;
|
||||
assert(firstViewport < MAX_VIEWPORTS);
|
||||
assert(total_count >= 1 && total_count <= MAX_VIEWPORTS);
|
||||
|
||||
if (state->dynamic.viewport.count < total_count)
|
||||
state->dynamic.viewport.count = total_count;
|
||||
|
||||
if (!memcmp(state->dynamic.viewport.viewports + firstViewport,
|
||||
pViewports, viewportCount * sizeof(*pViewports))) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(state->dynamic.viewport.viewports + firstViewport, pViewports,
|
||||
viewportCount * sizeof(*pViewports));
|
||||
vk_common_CmdSetViewportWithCount(commandBuffer,
|
||||
total_count,
|
||||
pViewports);
|
||||
|
||||
for (uint32_t i = firstViewport; i < total_count; i++) {
|
||||
v3dv_X(cmd_buffer->device, viewport_compute_xform)
|
||||
(&state->dynamic.viewport.viewports[i],
|
||||
state->dynamic.viewport.scale[i],
|
||||
state->dynamic.viewport.translate[i]);
|
||||
(&dyn->vp.viewports[i], v3dv_dyn->viewport.scale[i],
|
||||
v3dv_dyn->viewport.translate[i]);
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_VIEWPORT;
|
||||
}
|
||||
|
||||
/* We keep a custom CmdSetScissor because we need to set the scissor
|
||||
* count. This is specially relevant to our case because we are
|
||||
* pushing/popping the dynamic state as part of the meta operations.
|
||||
*/
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetScissor(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstScissor,
|
||||
uint32_t scissorCount,
|
||||
const VkRect2D *pScissors)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
|
||||
assert(firstScissor < MAX_SCISSORS);
|
||||
assert(firstScissor + scissorCount >= 1 &&
|
||||
firstScissor + scissorCount <= MAX_SCISSORS);
|
||||
|
||||
if (state->dynamic.scissor.count < firstScissor + scissorCount)
|
||||
state->dynamic.scissor.count = firstScissor + scissorCount;
|
||||
|
||||
if (!memcmp(state->dynamic.scissor.scissors + firstScissor,
|
||||
pScissors, scissorCount * sizeof(*pScissors))) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(state->dynamic.scissor.scissors + firstScissor, pScissors,
|
||||
scissorCount * sizeof(*pScissors));
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_SCISSOR;
|
||||
vk_common_CmdSetScissorWithCount(commandBuffer,
|
||||
firstScissor + scissorCount,
|
||||
pScissors);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_scissor(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
if (cmd_buffer->state.dynamic.viewport.count == 0)
|
||||
if (cmd_buffer->vk.dynamic_graphics_state.vp.viewport_count == 0)
|
||||
return;
|
||||
|
||||
struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
|
||||
@@ -2398,8 +2345,10 @@ emit_scissor(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
* FIXME: right now we only allow one scissor. Below would need to be
|
||||
* updated if we support more
|
||||
*/
|
||||
if (dynamic->scissor.count > 0) {
|
||||
VkRect2D *scissor = &dynamic->scissor.scissors[0];
|
||||
struct vk_dynamic_graphics_state *vk_dyn =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
if (vk_dyn->vp.scissor_count > 0) {
|
||||
VkRect2D *scissor = &vk_dyn->vp.scissors[0];
|
||||
minx = MAX2(minx, scissor->offset.x);
|
||||
miny = MAX2(miny, scissor->offset.y);
|
||||
maxx = MIN2(maxx, scissor->offset.x + scissor->extent.width);
|
||||
@@ -2422,12 +2371,11 @@ emit_scissor(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
v3dv_X(cmd_buffer->device, job_emit_clip_window)
|
||||
(cmd_buffer->state.job, &cmd_buffer->state.clip_window);
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_SCISSOR;
|
||||
BITSET_CLEAR(vk_dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS);
|
||||
}
|
||||
|
||||
static void
|
||||
update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
uint32_t dirty_uniform_state)
|
||||
static bool
|
||||
update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
/* We need to update uniform streams if any piece of state that is passed
|
||||
* to the shader as a uniform may have changed.
|
||||
@@ -2435,16 +2383,29 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
* If only descriptor sets are dirty then we can safely ignore updates
|
||||
* for shader stages that don't access descriptors.
|
||||
*/
|
||||
|
||||
struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
assert(pipeline);
|
||||
uint32_t dirty = cmd_buffer->state.dirty;
|
||||
struct vk_dynamic_graphics_state *dyn =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
const bool has_new_pipeline = dirty_uniform_state & V3DV_CMD_DIRTY_PIPELINE;
|
||||
const bool has_new_viewport = dirty_uniform_state & V3DV_CMD_DIRTY_VIEWPORT;
|
||||
const bool has_new_push_constants = dirty_uniform_state & V3DV_CMD_DIRTY_PUSH_CONSTANTS;
|
||||
const bool has_new_descriptors = dirty_uniform_state & V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
|
||||
const bool has_new_view_index = dirty_uniform_state & V3DV_CMD_DIRTY_VIEW_INDEX;
|
||||
const bool has_new_draw_id = dirty_uniform_state & V3DV_CMD_DIRTY_DRAW_ID;
|
||||
const bool dirty_uniform_state =
|
||||
(dirty & (V3DV_CMD_DIRTY_PIPELINE |
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS |
|
||||
V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
|
||||
V3DV_CMD_DIRTY_VIEW_INDEX |
|
||||
V3DV_CMD_DIRTY_DRAW_ID)) ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS);
|
||||
|
||||
if (!dirty_uniform_state)
|
||||
return false;
|
||||
|
||||
const bool has_new_pipeline = dirty & V3DV_CMD_DIRTY_PIPELINE;
|
||||
const bool has_new_viewport = BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS);
|
||||
const bool has_new_push_constants = dirty & V3DV_CMD_DIRTY_PUSH_CONSTANTS;
|
||||
const bool has_new_descriptors = dirty & V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
|
||||
const bool has_new_view_index = dirty & V3DV_CMD_DIRTY_VIEW_INDEX;
|
||||
const bool has_new_draw_id = dirty & V3DV_CMD_DIRTY_DRAW_ID;
|
||||
|
||||
/* VK_SHADER_STAGE_FRAGMENT_BIT */
|
||||
const bool has_new_descriptors_fs =
|
||||
@@ -2533,6 +2494,8 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEW_INDEX;
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_DRAW_ID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This stores command buffer state that we might be about to stomp for
|
||||
@@ -2589,6 +2552,8 @@ v3dv_cmd_buffer_meta_state_push(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
* account the graphics pipeline, and the graphics state
|
||||
*/
|
||||
state->meta.gfx.pipeline = state->gfx.pipeline;
|
||||
vk_dynamic_graphics_state_copy(&state->meta.dynamic_graphics_state,
|
||||
&cmd_buffer->vk.dynamic_graphics_state);
|
||||
memcpy(&state->meta.dynamic, &state->dynamic, sizeof(state->dynamic));
|
||||
|
||||
struct v3dv_descriptor_state *gfx_descriptor_state =
|
||||
@@ -2659,6 +2624,8 @@ v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
}
|
||||
|
||||
/* Restore dynamic state */
|
||||
vk_dynamic_graphics_state_copy(&cmd_buffer->vk.dynamic_graphics_state,
|
||||
&state->meta.dynamic_graphics_state);
|
||||
memcpy(&state->dynamic, &state->meta.dynamic, sizeof(state->dynamic));
|
||||
state->dirty = ~0;
|
||||
|
||||
@@ -3018,17 +2985,10 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
* that will require that we new uniform state for QUNIFORM_VIEWPORT_*.
|
||||
*/
|
||||
uint32_t *dirty = &cmd_buffer->state.dirty;
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
const uint32_t dirty_uniform_state =
|
||||
*dirty & (V3DV_CMD_DIRTY_PIPELINE |
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS |
|
||||
V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
|
||||
V3DV_CMD_DIRTY_VIEWPORT |
|
||||
V3DV_CMD_DIRTY_VIEW_INDEX |
|
||||
V3DV_CMD_DIRTY_DRAW_ID);
|
||||
|
||||
if (dirty_uniform_state)
|
||||
update_gfx_uniform_state(cmd_buffer, dirty_uniform_state);
|
||||
const bool dirty_uniform_state =
|
||||
update_gfx_uniform_state(cmd_buffer);
|
||||
|
||||
struct v3dv_device *device = cmd_buffer->device;
|
||||
|
||||
@@ -3040,44 +3000,51 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
v3dv_X(device, cmd_buffer_emit_varyings_state)(cmd_buffer);
|
||||
}
|
||||
|
||||
if (*dirty & (V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR)) {
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_SCISSORS) ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS)) {
|
||||
emit_scissor(cmd_buffer);
|
||||
}
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_VIEWPORT) {
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_VP_VIEWPORTS))
|
||||
v3dv_X(device, cmd_buffer_emit_viewport)(cmd_buffer);
|
||||
}
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_INDEX_BUFFER)
|
||||
v3dv_X(device, cmd_buffer_emit_index_buffer)(cmd_buffer);
|
||||
|
||||
const uint32_t dynamic_stencil_dirty_flags =
|
||||
V3DV_CMD_DIRTY_STENCIL_COMPARE_MASK |
|
||||
V3DV_CMD_DIRTY_STENCIL_WRITE_MASK |
|
||||
V3DV_CMD_DIRTY_STENCIL_REFERENCE;
|
||||
if (*dirty & (V3DV_CMD_DIRTY_PIPELINE | dynamic_stencil_dirty_flags))
|
||||
bool any_dynamic_stencil_dirty =
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE);
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_PIPELINE || any_dynamic_stencil_dirty)
|
||||
v3dv_X(device, cmd_buffer_emit_stencil)(cmd_buffer);
|
||||
|
||||
if (*dirty & (V3DV_CMD_DIRTY_PIPELINE | V3DV_CMD_DIRTY_DEPTH_BIAS))
|
||||
if (*dirty & V3DV_CMD_DIRTY_PIPELINE ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS)) {
|
||||
v3dv_X(device, cmd_buffer_emit_depth_bias)(cmd_buffer);
|
||||
}
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_DEPTH_BOUNDS)
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS))
|
||||
v3dv_X(device, cmd_buffer_emit_depth_bounds)(cmd_buffer);
|
||||
|
||||
if (*dirty & (V3DV_CMD_DIRTY_PIPELINE | V3DV_CMD_DIRTY_BLEND_CONSTANTS))
|
||||
if (*dirty & V3DV_CMD_DIRTY_PIPELINE ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {
|
||||
v3dv_X(device, cmd_buffer_emit_blend)(cmd_buffer);
|
||||
}
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_OCCLUSION_QUERY)
|
||||
v3dv_X(device, cmd_buffer_emit_occlusion_query)(cmd_buffer);
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_LINE_WIDTH)
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_WIDTH))
|
||||
v3dv_X(device, cmd_buffer_emit_line_width)(cmd_buffer);
|
||||
|
||||
if (*dirty & V3DV_CMD_DIRTY_PIPELINE)
|
||||
v3dv_X(device, cmd_buffer_emit_sample_state)(cmd_buffer);
|
||||
|
||||
if (*dirty & (V3DV_CMD_DIRTY_PIPELINE | V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE))
|
||||
if (*dirty & V3DV_CMD_DIRTY_PIPELINE ||
|
||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES)) {
|
||||
v3dv_X(device, cmd_buffer_emit_color_write_mask)(cmd_buffer);
|
||||
}
|
||||
|
||||
/* We disable double-buffer mode if indirect draws are used because in that
|
||||
* case we don't know the vertex count.
|
||||
@@ -3505,77 +3472,6 @@ v3dv_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
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_STENCIL_COMPARE_MASK;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
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_STENCIL_WRITE_MASK;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
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_STENCIL_REFERENCE;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetDepthBias(VkCommandBuffer commandBuffer,
|
||||
float depthBiasConstantFactor,
|
||||
float depthBiasClamp,
|
||||
float depthBiasSlopeFactor)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
|
||||
cmd_buffer->state.dynamic.depth_bias.constant_factor = depthBiasConstantFactor;
|
||||
cmd_buffer->state.dynamic.depth_bias.depth_bias_clamp = depthBiasClamp;
|
||||
cmd_buffer->state.dynamic.depth_bias.slope_factor = depthBiasSlopeFactor;
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DEPTH_BIAS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
|
||||
float minDepthBounds,
|
||||
float maxDepthBounds)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
|
||||
cmd_buffer->state.dynamic.depth_bounds.min = minDepthBounds;
|
||||
cmd_buffer->state.dynamic.depth_bounds.max = maxDepthBounds;
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DEPTH_BOUNDS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t lineStippleFactor,
|
||||
@@ -3584,16 +3480,6 @@ v3dv_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer,
|
||||
/* We do not support stippled line rasterization so we just ignore this. */
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetLineWidth(VkCommandBuffer commandBuffer,
|
||||
float lineWidth)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
|
||||
cmd_buffer->state.dynamic.line_width = lineWidth;
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_LINE_WIDTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks a descriptor set to see if are binding any descriptors that would
|
||||
* involve sampling from a linear image (the hardware only supports this for
|
||||
@@ -3983,44 +3869,6 @@ v3dv_CmdPushConstants(VkCommandBuffer commandBuffer,
|
||||
cmd_buffer->state.dirty_push_constants_stages |= stageFlags;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
|
||||
const float blendConstants[4])
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
|
||||
if (!memcmp(state->dynamic.blend_constants, blendConstants,
|
||||
sizeof(state->dynamic.blend_constants))) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(state->dynamic.blend_constants, blendConstants,
|
||||
sizeof(state->dynamic.blend_constants));
|
||||
|
||||
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_BLEND_CONSTANTS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
v3dv_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t attachmentCount,
|
||||
const VkBool32 *pColorWriteEnables)
|
||||
{
|
||||
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
|
||||
uint32_t color_write_enable = 0;
|
||||
|
||||
for (uint32_t i = 0; i < attachmentCount; i++)
|
||||
color_write_enable |= pColorWriteEnables[i] ? (0xfu << (i * 4)) : 0;
|
||||
|
||||
if (state->dynamic.color_write_enable == color_write_enable)
|
||||
return;
|
||||
|
||||
state->dynamic.color_write_enable = color_write_enable;
|
||||
|
||||
state->dirty |= V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE;
|
||||
}
|
||||
|
||||
void
|
||||
v3dv_cmd_buffer_ensure_array_state(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
uint32_t slot_size,
|
||||
@@ -4658,8 +4506,7 @@ v3dv_CmdBeginRenderingKHR(VkCommandBuffer commandBuffer,
|
||||
vk_free(&cmd_buffer->vk.pool->alloc, clear_values);
|
||||
|
||||
state->render_area = info->renderArea;
|
||||
constraint_clip_window_to_render_area(state);
|
||||
|
||||
constraint_clip_window_to_render_area(cmd_buffer);
|
||||
v3dv_cmd_buffer_subpass_start(cmd_buffer, 0);
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
#include "util/u_pack_color.h"
|
||||
#include "vk_common_entrypoints.h"
|
||||
|
||||
static void
|
||||
get_hw_clear_color(struct v3dv_device *device,
|
||||
@@ -1122,13 +1123,13 @@ emit_subpass_ds_clear_rects(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
pipeline->pipeline);
|
||||
|
||||
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||
v3dv_CmdSetStencilReference(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK,
|
||||
clear_ds->stencil);
|
||||
v3dv_CmdSetStencilWriteMask(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
v3dv_CmdSetStencilCompareMask(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
vk_common_CmdSetStencilReference(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK,
|
||||
clear_ds->stencil);
|
||||
vk_common_CmdSetStencilWriteMask(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
vk_common_CmdSetStencilCompareMask(cmd_buffer_handle,
|
||||
VK_STENCIL_FACE_FRONT_AND_BACK, 0xff);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < rect_count; i++) {
|
||||
|
@@ -2645,145 +2645,6 @@ compute_vpm_config(struct v3dv_pipeline *pipeline)
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
v3dv_dynamic_state_mask(VkDynamicState state)
|
||||
{
|
||||
switch(state) {
|
||||
case VK_DYNAMIC_STATE_VIEWPORT:
|
||||
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;
|
||||
case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
|
||||
return V3DV_DYNAMIC_BLEND_CONSTANTS;
|
||||
case VK_DYNAMIC_STATE_DEPTH_BIAS:
|
||||
return V3DV_DYNAMIC_DEPTH_BIAS;
|
||||
case VK_DYNAMIC_STATE_LINE_WIDTH:
|
||||
return V3DV_DYNAMIC_LINE_WIDTH;
|
||||
case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
|
||||
return V3DV_DYNAMIC_COLOR_WRITE_ENABLE;
|
||||
case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
|
||||
return V3DV_DYNAMIC_DEPTH_BOUNDS;
|
||||
|
||||
default:
|
||||
unreachable("Unhandled dynamic state");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pipeline_init_dynamic_state(
|
||||
struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineDynamicStateCreateInfo *pDynamicState,
|
||||
const VkPipelineViewportStateCreateInfo *pViewportState,
|
||||
const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState,
|
||||
const VkPipelineColorBlendStateCreateInfo *pColorBlendState,
|
||||
const VkPipelineRasterizationStateCreateInfo *pRasterizationState,
|
||||
const VkPipelineColorWriteCreateInfoEXT *pColorWriteState)
|
||||
{
|
||||
/* Initialize to default values */
|
||||
const struct v3d_device_info *devinfo = &pipeline->device->devinfo;
|
||||
struct v3dv_dynamic_state *dynamic = &pipeline->dynamic_state;
|
||||
memset(dynamic, 0, sizeof(*dynamic));
|
||||
dynamic->stencil_compare_mask.front = ~0;
|
||||
dynamic->stencil_compare_mask.back = ~0;
|
||||
dynamic->stencil_write_mask.front = ~0;
|
||||
dynamic->stencil_write_mask.back = ~0;
|
||||
dynamic->line_width = 1.0f;
|
||||
dynamic->color_write_enable =
|
||||
(1ull << (4 * V3D_MAX_RENDER_TARGETS(devinfo->ver))) - 1;
|
||||
dynamic->depth_bounds.max = 1.0f;
|
||||
|
||||
/* Create a mask of enabled dynamic states */
|
||||
uint32_t dynamic_states = 0;
|
||||
if (pDynamicState) {
|
||||
uint32_t count = pDynamicState->dynamicStateCount;
|
||||
for (uint32_t s = 0; s < count; s++) {
|
||||
dynamic_states |=
|
||||
v3dv_dynamic_state_mask(pDynamicState->pDynamicStates[s]);
|
||||
}
|
||||
}
|
||||
|
||||
/* For any pipeline states that are not dynamic, set the dynamic state
|
||||
* from the static pipeline state.
|
||||
*/
|
||||
if (pViewportState) {
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_VIEWPORT)) {
|
||||
dynamic->viewport.count = pViewportState->viewportCount;
|
||||
typed_memcpy(dynamic->viewport.viewports, pViewportState->pViewports,
|
||||
pViewportState->viewportCount);
|
||||
|
||||
for (uint32_t i = 0; i < dynamic->viewport.count; i++) {
|
||||
v3dv_X(pipeline->device, viewport_compute_xform)
|
||||
(&dynamic->viewport.viewports[i],
|
||||
dynamic->viewport.scale[i],
|
||||
dynamic->viewport.translate[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_SCISSOR)) {
|
||||
dynamic->scissor.count = pViewportState->scissorCount;
|
||||
typed_memcpy(dynamic->scissor.scissors, pViewportState->pScissors,
|
||||
pViewportState->scissorCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (pDepthStencilState) {
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_STENCIL_COMPARE_MASK)) {
|
||||
dynamic->stencil_compare_mask.front =
|
||||
pDepthStencilState->front.compareMask;
|
||||
dynamic->stencil_compare_mask.back =
|
||||
pDepthStencilState->back.compareMask;
|
||||
}
|
||||
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_STENCIL_WRITE_MASK)) {
|
||||
dynamic->stencil_write_mask.front = pDepthStencilState->front.writeMask;
|
||||
dynamic->stencil_write_mask.back = pDepthStencilState->back.writeMask;
|
||||
}
|
||||
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_STENCIL_REFERENCE)) {
|
||||
dynamic->stencil_reference.front = pDepthStencilState->front.reference;
|
||||
dynamic->stencil_reference.back = pDepthStencilState->back.reference;
|
||||
}
|
||||
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_DEPTH_BOUNDS)) {
|
||||
dynamic->depth_bounds.min = pDepthStencilState->minDepthBounds;
|
||||
dynamic->depth_bounds.max = pDepthStencilState->maxDepthBounds;
|
||||
}
|
||||
}
|
||||
|
||||
if (pColorBlendState && !(dynamic_states & V3DV_DYNAMIC_BLEND_CONSTANTS)) {
|
||||
memcpy(dynamic->blend_constants, pColorBlendState->blendConstants,
|
||||
sizeof(dynamic->blend_constants));
|
||||
}
|
||||
|
||||
if (pRasterizationState) {
|
||||
if (pRasterizationState->depthBiasEnable &&
|
||||
!(dynamic_states & V3DV_DYNAMIC_DEPTH_BIAS)) {
|
||||
dynamic->depth_bias.constant_factor =
|
||||
pRasterizationState->depthBiasConstantFactor;
|
||||
dynamic->depth_bias.depth_bias_clamp =
|
||||
pRasterizationState->depthBiasClamp;
|
||||
dynamic->depth_bias.slope_factor =
|
||||
pRasterizationState->depthBiasSlopeFactor;
|
||||
}
|
||||
if (!(dynamic_states & V3DV_DYNAMIC_LINE_WIDTH))
|
||||
dynamic->line_width = pRasterizationState->lineWidth;
|
||||
}
|
||||
|
||||
if (pColorWriteState && !(dynamic_states & V3DV_DYNAMIC_COLOR_WRITE_ENABLE)) {
|
||||
dynamic->color_write_enable = 0;
|
||||
for (uint32_t i = 0; i < pColorWriteState->attachmentCount; i++)
|
||||
dynamic->color_write_enable |= pColorWriteState->pColorWriteEnables[i] ? (0xfu << (i * 4)) : 0;
|
||||
}
|
||||
|
||||
pipeline->dynamic_state.mask = dynamic_states;
|
||||
}
|
||||
|
||||
static bool
|
||||
stencil_op_is_no_op(const VkStencilOpState *stencil)
|
||||
{
|
||||
@@ -2965,6 +2826,49 @@ pipeline_setup_rendering_info(struct v3dv_device *device,
|
||||
};
|
||||
}
|
||||
|
||||
static VkResult
|
||||
pipeline_init_dynamic_state(struct v3dv_device *device,
|
||||
struct v3dv_pipeline *pipeline,
|
||||
struct vk_graphics_pipeline_state *pipeline_state,
|
||||
const VkGraphicsPipelineCreateInfo *pCreateInfo,
|
||||
const VkPipelineColorWriteCreateInfoEXT *cw_info)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
struct vk_graphics_pipeline_all_state all;
|
||||
result = vk_graphics_pipeline_state_fill(&pipeline->device->vk, pipeline_state,
|
||||
pCreateInfo, &pipeline->rendering_info, 0,
|
||||
&all, NULL, 0, NULL);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
vk_dynamic_graphics_state_fill(&pipeline->dynamic_graphics_state, pipeline_state);
|
||||
|
||||
struct v3dv_dynamic_state *v3dv_dyn = &pipeline->dynamic;
|
||||
struct vk_dynamic_graphics_state *dyn = &pipeline->dynamic_graphics_state;
|
||||
|
||||
if (BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_VP_VIEWPORTS) ||
|
||||
BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_VP_SCISSORS)) {
|
||||
/* FIXME: right now we don't support multiViewport so viewporst[0] would
|
||||
* work now, but would need to change if we allow multiple viewports.
|
||||
*/
|
||||
v3dv_X(device, viewport_compute_xform)(&dyn->vp.viewports[0],
|
||||
v3dv_dyn->viewport.scale[0],
|
||||
v3dv_dyn->viewport.translate[0]);
|
||||
|
||||
}
|
||||
|
||||
v3dv_dyn->color_write_enable =
|
||||
(1ull << (4 * V3D_MAX_RENDER_TARGETS(device->devinfo.ver))) - 1;
|
||||
if (cw_info && BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES)) {
|
||||
v3dv_dyn->color_write_enable = 0;
|
||||
for (uint32_t i = 0; i < cw_info->attachmentCount; i++)
|
||||
v3dv_dyn->color_write_enable |=
|
||||
cw_info->pColorWriteEnables[i] ? (0xfu << (i * 4)) : 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
pipeline_init(struct v3dv_pipeline *pipeline,
|
||||
struct v3dv_device *device,
|
||||
@@ -3033,6 +2937,17 @@ pipeline_init(struct v3dv_pipeline *pipeline,
|
||||
PIPELINE_COLOR_WRITE_CREATE_INFO_EXT) :
|
||||
NULL;
|
||||
|
||||
struct vk_graphics_pipeline_state pipeline_state = { };
|
||||
result = pipeline_init_dynamic_state(device, pipeline, &pipeline_state,
|
||||
pCreateInfo, cw_info);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
/* Caller would already destroy the pipeline, and we didn't allocate any
|
||||
* extra info. We don't need to do anything else.
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
const VkPipelineViewportDepthClipControlCreateInfoEXT *depth_clip_control =
|
||||
vp_info ? vk_find_struct_const(vp_info->pNext,
|
||||
PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT) :
|
||||
@@ -3041,22 +2956,18 @@ pipeline_init(struct v3dv_pipeline *pipeline,
|
||||
if (depth_clip_control)
|
||||
pipeline->negative_one_to_one = depth_clip_control->negativeOneToOne;
|
||||
|
||||
pipeline_init_dynamic_state(pipeline,
|
||||
pCreateInfo->pDynamicState,
|
||||
vp_info, ds_info, cb_info, rs_info, cw_info);
|
||||
|
||||
/* V3D 4.2 doesn't support depth bounds testing so we don't advertise that
|
||||
* feature and it shouldn't be used by any pipeline.
|
||||
*/
|
||||
assert(device->devinfo.ver >= 71 ||
|
||||
!ds_info || !ds_info->depthBoundsTestEnable);
|
||||
pipeline->depth_bounds_test_enabled = ds_info && ds_info->depthBoundsTestEnable;
|
||||
|
||||
enable_depth_bias(pipeline, rs_info);
|
||||
|
||||
v3dv_X(device, pipeline_pack_state)(pipeline, cb_info, ds_info,
|
||||
rs_info, pv_info, ls_info,
|
||||
ms_info);
|
||||
ms_info,
|
||||
&pipeline_state);
|
||||
|
||||
pipeline_set_sample_mask(pipeline, ms_info);
|
||||
pipeline_set_sample_rate_shading(pipeline, ms_info);
|
||||
|
@@ -1040,102 +1040,49 @@ struct v3dv_cmd_buffer_attachment_state {
|
||||
bool use_tlb_resolve;
|
||||
};
|
||||
|
||||
/* Cached values derived from Vulkan viewport/count */
|
||||
struct v3dv_viewport_state {
|
||||
uint32_t count;
|
||||
VkViewport viewports[MAX_VIEWPORTS];
|
||||
float translate[MAX_VIEWPORTS][3];
|
||||
float scale[MAX_VIEWPORTS][3];
|
||||
};
|
||||
|
||||
struct v3dv_scissor_state {
|
||||
uint32_t count;
|
||||
VkRect2D scissors[MAX_SCISSORS];
|
||||
};
|
||||
|
||||
/* Mostly a v3dv mapping of VkDynamicState, used to track which data as
|
||||
* defined as dynamic
|
||||
*/
|
||||
enum v3dv_dynamic_state_bits {
|
||||
V3DV_DYNAMIC_VIEWPORT = 1 << 0,
|
||||
V3DV_DYNAMIC_SCISSOR = 1 << 1,
|
||||
V3DV_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 2,
|
||||
V3DV_DYNAMIC_STENCIL_WRITE_MASK = 1 << 3,
|
||||
V3DV_DYNAMIC_STENCIL_REFERENCE = 1 << 4,
|
||||
V3DV_DYNAMIC_BLEND_CONSTANTS = 1 << 5,
|
||||
V3DV_DYNAMIC_DEPTH_BIAS = 1 << 6,
|
||||
V3DV_DYNAMIC_LINE_WIDTH = 1 << 7,
|
||||
V3DV_DYNAMIC_COLOR_WRITE_ENABLE = 1 << 8,
|
||||
V3DV_DYNAMIC_DEPTH_BOUNDS = 1 << 9,
|
||||
V3DV_DYNAMIC_ALL = (1 << 10) - 1,
|
||||
};
|
||||
|
||||
/* Flags for dirty pipeline state.
|
||||
/* Flags for custom dirty state, that could lead to packet emission.
|
||||
*
|
||||
* Note *custom*, for all the dynamic state tracking coming from the Vulkan
|
||||
* API, we use the Mesa runtime framework and their predefined flags
|
||||
* (MESA_VK_DYNAMIC_XXX).
|
||||
*
|
||||
* Here we defined additional flags used to track dirty state.
|
||||
*/
|
||||
enum v3dv_cmd_dirty_bits {
|
||||
V3DV_CMD_DIRTY_VIEWPORT = 1 << 0,
|
||||
V3DV_CMD_DIRTY_SCISSOR = 1 << 1,
|
||||
V3DV_CMD_DIRTY_STENCIL_COMPARE_MASK = 1 << 2,
|
||||
V3DV_CMD_DIRTY_STENCIL_WRITE_MASK = 1 << 3,
|
||||
V3DV_CMD_DIRTY_STENCIL_REFERENCE = 1 << 4,
|
||||
V3DV_CMD_DIRTY_PIPELINE = 1 << 5,
|
||||
V3DV_CMD_DIRTY_COMPUTE_PIPELINE = 1 << 6,
|
||||
V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 7,
|
||||
V3DV_CMD_DIRTY_INDEX_BUFFER = 1 << 8,
|
||||
V3DV_CMD_DIRTY_DESCRIPTOR_SETS = 1 << 9,
|
||||
V3DV_CMD_DIRTY_COMPUTE_DESCRIPTOR_SETS = 1 << 10,
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS = 1 << 11,
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS_UBO = 1 << 12,
|
||||
V3DV_CMD_DIRTY_BLEND_CONSTANTS = 1 << 13,
|
||||
V3DV_CMD_DIRTY_OCCLUSION_QUERY = 1 << 14,
|
||||
V3DV_CMD_DIRTY_DEPTH_BIAS = 1 << 15,
|
||||
V3DV_CMD_DIRTY_LINE_WIDTH = 1 << 16,
|
||||
V3DV_CMD_DIRTY_VIEW_INDEX = 1 << 17,
|
||||
V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE = 1 << 18,
|
||||
V3DV_CMD_DIRTY_DEPTH_BOUNDS = 1 << 19,
|
||||
V3DV_CMD_DIRTY_DRAW_ID = 1 << 20,
|
||||
V3DV_CMD_DIRTY_PIPELINE = 1 << 0,
|
||||
V3DV_CMD_DIRTY_COMPUTE_PIPELINE = 1 << 1,
|
||||
V3DV_CMD_DIRTY_VERTEX_BUFFER = 1 << 2,
|
||||
V3DV_CMD_DIRTY_INDEX_BUFFER = 1 << 3,
|
||||
V3DV_CMD_DIRTY_DESCRIPTOR_SETS = 1 << 4,
|
||||
V3DV_CMD_DIRTY_COMPUTE_DESCRIPTOR_SETS = 1 << 5,
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS = 1 << 6,
|
||||
V3DV_CMD_DIRTY_PUSH_CONSTANTS_UBO = 1 << 7,
|
||||
V3DV_CMD_DIRTY_OCCLUSION_QUERY = 1 << 8,
|
||||
V3DV_CMD_DIRTY_VIEW_INDEX = 1 << 9,
|
||||
V3DV_CMD_DIRTY_DRAW_ID = 1 << 10,
|
||||
V3DV_CMD_DIRTY_ALL = (1 << 10) - 1,
|
||||
};
|
||||
|
||||
struct v3dv_dynamic_state {
|
||||
/**
|
||||
* Bitmask of (1 << VK_DYNAMIC_STATE_*).
|
||||
* Defines the set of saved dynamic state.
|
||||
/* FIXME: we keep some viewport info cached (translate, scale) because we
|
||||
* use that on more that one place. But note that translate_z and scale_z
|
||||
* is also used in several places, and we recompute it based on
|
||||
* scissor/viewport info all time. So perhaps we could do the same with the
|
||||
* x and y component.
|
||||
*/
|
||||
uint32_t mask;
|
||||
|
||||
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;
|
||||
|
||||
float blend_constants[4];
|
||||
|
||||
struct {
|
||||
float constant_factor;
|
||||
float depth_bias_clamp;
|
||||
float slope_factor;
|
||||
} depth_bias;
|
||||
|
||||
struct {
|
||||
float min;
|
||||
float max;
|
||||
} depth_bounds;
|
||||
|
||||
float line_width;
|
||||
|
||||
/* We cache the color_write_enable as the vulkan runtime keeps a 8-bit
|
||||
* bitset with a bit per attachment, but in order to combine with the
|
||||
* color_write_masks is easier to cache a 32-bit bitset with 4 bits per
|
||||
* attachment.
|
||||
*/
|
||||
uint32_t color_write_enable;
|
||||
};
|
||||
|
||||
@@ -1520,8 +1467,16 @@ struct v3dv_cmd_buffer_state {
|
||||
struct v3dv_cmd_pipeline_state gfx;
|
||||
struct v3dv_cmd_pipeline_state compute;
|
||||
|
||||
/* For most state tracking we rely on vk_dynamic_graphics_state, but we
|
||||
* maintain a custom structure for some state-related data that we want to
|
||||
* cache.
|
||||
*/
|
||||
struct v3dv_dynamic_state dynamic;
|
||||
|
||||
/* This dirty is for v3dv_cmd_dirty_bits (FIXME: perhaps we should be more
|
||||
* explicit about it). For dirty flags coming from Vulkan dynamic state,
|
||||
* use the vk_dynamic_graphics_state handled by the vk_cmd_buffer
|
||||
*/
|
||||
uint32_t dirty;
|
||||
VkShaderStageFlagBits dirty_descriptor_stages;
|
||||
VkShaderStageFlagBits dirty_push_constants_stages;
|
||||
@@ -1606,6 +1561,7 @@ struct v3dv_cmd_buffer_state {
|
||||
bool tile_aligned_render_area;
|
||||
VkRect2D render_area;
|
||||
|
||||
struct vk_dynamic_graphics_state dynamic_graphics_state;
|
||||
struct v3dv_dynamic_state dynamic;
|
||||
|
||||
struct v3dv_cmd_pipeline_state gfx;
|
||||
@@ -1650,7 +1606,7 @@ struct v3dv_cmd_buffer_state {
|
||||
};
|
||||
|
||||
void
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state,
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
uint32_t vp_idx,
|
||||
float *translate_z, float *scale_z);
|
||||
|
||||
@@ -2299,7 +2255,8 @@ struct v3dv_pipeline {
|
||||
uint32_t size_per_thread;
|
||||
} spill;
|
||||
|
||||
struct v3dv_dynamic_state dynamic_state;
|
||||
struct vk_dynamic_graphics_state dynamic_graphics_state;
|
||||
struct v3dv_dynamic_state dynamic;
|
||||
|
||||
struct v3dv_pipeline_layout *layout;
|
||||
|
||||
@@ -2386,9 +2343,6 @@ struct v3dv_pipeline {
|
||||
bool is_z16;
|
||||
} depth_bias;
|
||||
|
||||
/* Depth bounds */
|
||||
bool depth_bounds_test_enabled;
|
||||
|
||||
struct {
|
||||
void *mem_ctx;
|
||||
struct util_dynarray data; /* Array of v3dv_pipeline_executable_data */
|
||||
|
@@ -521,7 +521,7 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
|
||||
case QUNIFORM_VIEWPORT_Z_OFFSET: {
|
||||
float translate_z;
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(cmd_buffer, 0,
|
||||
&translate_z, NULL);
|
||||
cl_aligned_f(&uniforms, translate_z);
|
||||
break;
|
||||
@@ -529,7 +529,7 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
|
||||
case QUNIFORM_VIEWPORT_Z_SCALE: {
|
||||
float scale_z;
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(cmd_buffer, 0,
|
||||
NULL, &scale_z);
|
||||
cl_aligned_f(&uniforms, scale_z);
|
||||
break;
|
||||
@@ -662,7 +662,8 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
break;
|
||||
|
||||
case QUNIFORM_LINE_WIDTH:
|
||||
cl_aligned_u32(&uniforms, job->cmd_buffer->state.dynamic.line_width);
|
||||
cl_aligned_u32(&uniforms,
|
||||
job->cmd_buffer->vk.dynamic_graphics_state.rs.line.width);
|
||||
break;
|
||||
|
||||
case QUNIFORM_AA_LINE_WIDTH:
|
||||
|
@@ -1329,8 +1329,8 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
assert(pipeline);
|
||||
|
||||
/* FIXME: right now we only support one viewport. viewporst[0] would work
|
||||
* now, would need to change if we allow multiple viewports
|
||||
/* FIXME: right now we don't support multiViewport so viewports[0] would
|
||||
* work now, but would need to change if we allow multiple viewports.
|
||||
*/
|
||||
float *vptranslate = dynamic->viewport.translate[0];
|
||||
float *vpscale = dynamic->viewport.scale[0];
|
||||
@@ -1360,7 +1360,7 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
#endif
|
||||
|
||||
float translate_z, scale_z;
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0,
|
||||
v3dv_cmd_buffer_state_get_viewport_z_xform(cmd_buffer, 0,
|
||||
&translate_z, &scale_z);
|
||||
|
||||
#if V3D_VERSION == 42
|
||||
@@ -1421,7 +1421,8 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
vp.coarse_y = vp_coarse_y;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEWPORT;
|
||||
BITSET_CLEAR(cmd_buffer->vk.dynamic_graphics_state.dirty,
|
||||
MESA_VK_DYNAMIC_VP_VIEWPORTS);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1431,52 +1432,50 @@ v3dX(cmd_buffer_emit_stencil)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
assert(job);
|
||||
|
||||
struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.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;
|
||||
struct vk_dynamic_graphics_state *dyn =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
v3dv_cl_ensure_space_with_branch(&job->bcl,
|
||||
2 * cl_packet_length(STENCIL_CFG));
|
||||
v3dv_return_if_oom(cmd_buffer, NULL);
|
||||
|
||||
bool any_dynamic_stencil_state =
|
||||
BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) ||
|
||||
BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) ||
|
||||
BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE);
|
||||
|
||||
bool emitted_stencil = false;
|
||||
const struct vk_stencil_test_face_state *front = &dyn->ds.stencil.front;
|
||||
const struct vk_stencil_test_face_state *back = &dyn->ds.stencil.back;
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (pipeline->emit_stencil_cfg[i]) {
|
||||
if (dynamic_state->mask & dynamic_stencil_states) {
|
||||
if (any_dynamic_stencil_state) {
|
||||
cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
|
||||
pipeline->stencil_cfg[i], config) {
|
||||
if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) {
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) {
|
||||
config.stencil_test_mask =
|
||||
i == 0 ? dynamic_state->stencil_compare_mask.front :
|
||||
dynamic_state->stencil_compare_mask.back;
|
||||
i == 0 ? front->compare_mask : back->compare_mask;
|
||||
}
|
||||
if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK) {
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) {
|
||||
config.stencil_write_mask =
|
||||
i == 0 ? dynamic_state->stencil_write_mask.front :
|
||||
dynamic_state->stencil_write_mask.back;
|
||||
i == 0 ? front->write_mask : back->write_mask;
|
||||
}
|
||||
if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_REFERENCE) {
|
||||
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) {
|
||||
config.stencil_ref_value =
|
||||
i == 0 ? dynamic_state->stencil_reference.front :
|
||||
dynamic_state->stencil_reference.back;
|
||||
i == 0 ? front->reference : back->reference;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]);
|
||||
}
|
||||
|
||||
emitted_stencil = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (emitted_stencil) {
|
||||
const uint32_t dynamic_stencil_dirty_flags =
|
||||
V3DV_CMD_DIRTY_STENCIL_COMPARE_MASK |
|
||||
V3DV_CMD_DIRTY_STENCIL_WRITE_MASK |
|
||||
V3DV_CMD_DIRTY_STENCIL_REFERENCE;
|
||||
cmd_buffer->state.dirty &= ~dynamic_stencil_dirty_flags;
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK);
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE);
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1492,21 +1491,22 @@ v3dX(cmd_buffer_emit_depth_bias)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
struct v3dv_job *job = cmd_buffer->state.job;
|
||||
assert(job);
|
||||
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(DEPTH_OFFSET));
|
||||
v3dv_return_if_oom(cmd_buffer, NULL);
|
||||
|
||||
struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
|
||||
cl_emit(&job->bcl, DEPTH_OFFSET, bias) {
|
||||
bias.depth_offset_factor = dynamic->depth_bias.slope_factor;
|
||||
bias.depth_offset_units = dynamic->depth_bias.constant_factor;
|
||||
bias.depth_offset_factor = dyn->rs.depth_bias.slope;
|
||||
bias.depth_offset_units = dyn->rs.depth_bias.constant;
|
||||
#if V3D_VERSION <= 42
|
||||
if (pipeline->depth_bias.is_z16)
|
||||
bias.depth_offset_units *= 256.0f;
|
||||
#endif
|
||||
bias.limit = dynamic->depth_bias.depth_bias_clamp;
|
||||
bias.limit = dyn->rs.depth_bias.clamp;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_DEPTH_BIAS;
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1517,12 +1517,11 @@ v3dX(cmd_buffer_emit_depth_bounds)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
* Note that this method is being called as v3dv_job_init flags all state
|
||||
* as dirty. See FIXME note in v3dv_job_init.
|
||||
*/
|
||||
|
||||
#if V3D_VERSION >= 71
|
||||
struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
assert(pipeline);
|
||||
struct vk_dynamic_graphics_state *dyn =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
if (!pipeline->depth_bounds_test_enabled)
|
||||
if (!dyn->ds.depth.bounds_test.enable)
|
||||
return;
|
||||
|
||||
struct v3dv_job *job = cmd_buffer->state.job;
|
||||
@@ -1531,13 +1530,11 @@ v3dX(cmd_buffer_emit_depth_bounds)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(DEPTH_BOUNDS_TEST_LIMITS));
|
||||
v3dv_return_if_oom(cmd_buffer, NULL);
|
||||
|
||||
struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
|
||||
cl_emit(&job->bcl, DEPTH_BOUNDS_TEST_LIMITS, bounds) {
|
||||
bounds.lower_test_limit = dynamic->depth_bounds.min;
|
||||
bounds.upper_test_limit = dynamic->depth_bounds.max;
|
||||
bounds.lower_test_limit = dyn->ds.depth.bounds_test.min;
|
||||
bounds.upper_test_limit = dyn->ds.depth.bounds_test.max;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_DEPTH_BOUNDS;
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1547,6 +1544,8 @@ v3dX(cmd_buffer_emit_line_width)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
struct v3dv_job *job = cmd_buffer->state.job;
|
||||
assert(job);
|
||||
|
||||
struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(LINE_WIDTH));
|
||||
v3dv_return_if_oom(cmd_buffer, NULL);
|
||||
|
||||
@@ -1555,7 +1554,7 @@ v3dX(cmd_buffer_emit_line_width)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
cmd_buffer);
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_LINE_WIDTH;
|
||||
BITSET_CLEAR(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_WIDTH);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1609,17 +1608,20 @@ v3dX(cmd_buffer_emit_blend)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
}
|
||||
}
|
||||
|
||||
if (pipeline->blend.needs_color_constants &&
|
||||
cmd_buffer->state.dirty & V3DV_CMD_DIRTY_BLEND_CONSTANTS) {
|
||||
struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
|
||||
if (pipeline->blend.needs_color_constants) {
|
||||
const struct vk_dynamic_graphics_state *dyn =
|
||||
&cmd_buffer->vk.dynamic_graphics_state;
|
||||
|
||||
cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {
|
||||
color.red_f16 = _mesa_float_to_half(dynamic->blend_constants[0]);
|
||||
color.green_f16 = _mesa_float_to_half(dynamic->blend_constants[1]);
|
||||
color.blue_f16 = _mesa_float_to_half(dynamic->blend_constants[2]);
|
||||
color.alpha_f16 = _mesa_float_to_half(dynamic->blend_constants[3]);
|
||||
color.red_f16 = _mesa_float_to_half(dyn->cb.blend_constants[0]);
|
||||
color.green_f16 = _mesa_float_to_half(dyn->cb.blend_constants[1]);
|
||||
color.blue_f16 = _mesa_float_to_half(dyn->cb.blend_constants[2]);
|
||||
color.alpha_f16 = _mesa_float_to_half(dyn->cb.blend_constants[3]);
|
||||
}
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_BLEND_CONSTANTS;
|
||||
}
|
||||
|
||||
BITSET_CLEAR(cmd_buffer->vk.dynamic_graphics_state.dirty,
|
||||
MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1629,9 +1631,10 @@ v3dX(cmd_buffer_emit_color_write_mask)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(COLOR_WRITE_MASKS));
|
||||
|
||||
struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;
|
||||
uint32_t color_write_mask = ~dynamic->color_write_enable |
|
||||
struct v3dv_dynamic_state *v3dv_dyn = &cmd_buffer->state.dynamic;
|
||||
uint32_t color_write_mask = ~v3dv_dyn->color_write_enable |
|
||||
pipeline->blend.color_write_masks;
|
||||
|
||||
#if V3D_VERSION <= 42
|
||||
/* Only 4 RTs */
|
||||
color_write_mask &= 0xffff;
|
||||
@@ -1641,7 +1644,8 @@ v3dX(cmd_buffer_emit_color_write_mask)(struct v3dv_cmd_buffer *cmd_buffer)
|
||||
mask.mask = color_write_mask;
|
||||
}
|
||||
|
||||
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE;
|
||||
BITSET_CLEAR(cmd_buffer->vk.dynamic_graphics_state.dirty,
|
||||
MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -293,7 +293,8 @@ pack_single_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
uint8_t *stencil_cfg,
|
||||
bool is_front,
|
||||
bool is_back,
|
||||
const VkStencilOpState *stencil_state)
|
||||
const VkStencilOpState *stencil_state,
|
||||
const struct vk_graphics_pipeline_state *state)
|
||||
{
|
||||
/* From the Vulkan spec:
|
||||
*
|
||||
@@ -311,16 +312,16 @@ pack_single_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
* the old.
|
||||
*/
|
||||
const uint8_t write_mask =
|
||||
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK ?
|
||||
0 : stencil_state->writeMask & 0xff;
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) ?
|
||||
0 : stencil_state->writeMask & 0xff;
|
||||
|
||||
const uint8_t compare_mask =
|
||||
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
|
||||
0 : stencil_state->compareMask & 0xff;
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) ?
|
||||
0 : stencil_state->compareMask & 0xff;
|
||||
|
||||
const uint8_t reference =
|
||||
pipeline->dynamic_state.mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK ?
|
||||
0 : stencil_state->reference & 0xff;
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE) ?
|
||||
0 : stencil_state->reference & 0xff;
|
||||
|
||||
v3dvx_pack(stencil_cfg, STENCIL_CFG, config) {
|
||||
config.front_config = is_front;
|
||||
@@ -337,7 +338,8 @@ pack_single_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
|
||||
static void
|
||||
pack_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineDepthStencilStateCreateInfo *ds_info)
|
||||
const VkPipelineDepthStencilStateCreateInfo *ds_info,
|
||||
const struct vk_graphics_pipeline_state *state)
|
||||
{
|
||||
assert(sizeof(pipeline->stencil_cfg) == 2 * cl_packet_length(STENCIL_CFG));
|
||||
|
||||
@@ -348,18 +350,19 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
if (ri->stencil_attachment_format == VK_FORMAT_UNDEFINED)
|
||||
return;
|
||||
|
||||
const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK |
|
||||
V3DV_DYNAMIC_STENCIL_WRITE_MASK |
|
||||
V3DV_DYNAMIC_STENCIL_REFERENCE;
|
||||
|
||||
const bool any_dynamic_stencil_states =
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) ||
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK) ||
|
||||
BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_DS_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)))
|
||||
if ((any_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.
|
||||
@@ -367,16 +370,22 @@ pack_stencil_cfg(struct v3dv_pipeline *pipeline,
|
||||
pipeline->emit_stencil_cfg[0] = true;
|
||||
if (!needs_front_and_back) {
|
||||
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
|
||||
true, true, &ds_info->front);
|
||||
true, true, &ds_info->front, state);
|
||||
} else {
|
||||
pipeline->emit_stencil_cfg[1] = true;
|
||||
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[0],
|
||||
true, false, &ds_info->front);
|
||||
true, false, &ds_info->front, state);
|
||||
pack_single_stencil_cfg(pipeline, pipeline->stencil_cfg[1],
|
||||
false, true, &ds_info->back);
|
||||
false, true, &ds_info->back, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Now that we are passing the vk_graphics_pipeline_state we could
|
||||
* avoid passing all those parameters. But doing that we would need to change
|
||||
* all the code that uses the VkXXX structures, and use instead the equivalent
|
||||
* vk_xxx
|
||||
*/
|
||||
void
|
||||
v3dX(pipeline_pack_state)(struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineColorBlendStateCreateInfo *cb_info,
|
||||
@@ -384,11 +393,12 @@ v3dX(pipeline_pack_state)(struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineRasterizationStateCreateInfo *rs_info,
|
||||
const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_info,
|
||||
const VkPipelineRasterizationLineStateCreateInfoEXT *ls_info,
|
||||
const VkPipelineMultisampleStateCreateInfo *ms_info)
|
||||
const VkPipelineMultisampleStateCreateInfo *ms_info,
|
||||
const struct vk_graphics_pipeline_state *state)
|
||||
{
|
||||
pack_blend(pipeline, cb_info);
|
||||
pack_cfg_bits(pipeline, ds_info, rs_info, pv_info, ls_info, ms_info);
|
||||
pack_stencil_cfg(pipeline, ds_info);
|
||||
pack_stencil_cfg(pipeline, ds_info, state);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -318,7 +318,8 @@ v3dX(pipeline_pack_state)(struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineRasterizationStateCreateInfo *rs_info,
|
||||
const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_info,
|
||||
const VkPipelineRasterizationLineStateCreateInfoEXT *ls_info,
|
||||
const VkPipelineMultisampleStateCreateInfo *ms_info);
|
||||
const VkPipelineMultisampleStateCreateInfo *ms_info,
|
||||
const struct vk_graphics_pipeline_state *state);
|
||||
void
|
||||
v3dX(pipeline_pack_compile_state)(struct v3dv_pipeline *pipeline,
|
||||
const VkPipelineVertexInputStateCreateInfo *vi_info,
|
||||
|
Reference in New Issue
Block a user