anv: implement VK_KHR_dynamic_rendering_local_read

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Ivan Briano <ivan.briano@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27270>
This commit is contained in:
Lionel Landwerlin
2024-09-20 14:29:03 +03:00
committed by Marge Bot
parent 15987f49bb
commit d2f7b6d5a7
7 changed files with 143 additions and 88 deletions

View File

@@ -2113,7 +2113,8 @@ anv_image_view_surface_data_for_plane_layout(struct anv_image_view *image_view,
if (desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || if (desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
desc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || desc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
desc_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) { desc_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) {
return layout == VK_IMAGE_LAYOUT_GENERAL ? return (layout == VK_IMAGE_LAYOUT_GENERAL ||
layout == VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) ?
&image_view->planes[plane].general_sampler.state_data : &image_view->planes[plane].general_sampler.state_data :
&image_view->planes[plane].optimal_sampler.state_data; &image_view->planes[plane].optimal_sampler.state_data;
} }

View File

@@ -85,6 +85,7 @@ get_device_extensions(const struct anv_physical_device *device,
.KHR_draw_indirect_count = true, .KHR_draw_indirect_count = true,
.KHR_driver_properties = true, .KHR_driver_properties = true,
.KHR_dynamic_rendering = true, .KHR_dynamic_rendering = true,
.KHR_dynamic_rendering_local_read = true,
.KHR_external_fence = has_syncobj_wait, .KHR_external_fence = has_syncobj_wait,
.KHR_external_fence_fd = has_syncobj_wait, .KHR_external_fence_fd = has_syncobj_wait,
.KHR_external_memory = true, .KHR_external_memory = true,
@@ -809,6 +810,9 @@ get_features(const struct anv_physical_device *pdevice,
/* VK_KHR_shader_relaxed_extended_instruction */ /* VK_KHR_shader_relaxed_extended_instruction */
.shaderRelaxedExtendedInstruction = true, .shaderRelaxedExtendedInstruction = true,
/* VK_KHR_dynamic_rendering_local_read */
.dynamicRenderingLocalRead = true,
}; };
/* The new DOOM and Wolfenstein games require depthBounds without /* The new DOOM and Wolfenstein games require depthBounds without

View File

@@ -2969,6 +2969,36 @@ anv_graphics_pipeline_emit(struct anv_graphics_pipeline *pipeline,
pipeline->min_sample_shading = state->ms->min_sample_shading; pipeline->min_sample_shading = state->ms->min_sample_shading;
} }
if (anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) {
/* Count the number of color attachments in the binding table */
const struct anv_pipeline_bind_map *bind_map =
&pipeline->base.shaders[MESA_SHADER_FRAGMENT]->bind_map;
memset(pipeline->color_output_mapping,
MESA_VK_ATTACHMENT_UNUSED,
sizeof(pipeline->color_output_mapping));
if (state->cal != NULL) {
for (uint32_t i = 0; i < MAX_RTS; i++) {
if (state->cal->color_map[i] != MESA_VK_ATTACHMENT_UNUSED)
pipeline->color_output_mapping[state->cal->color_map[i]] = i;
}
unsigned i;
for (i = 0; i < MIN2(bind_map->surface_count, MAX_RTS); i++) {
if (bind_map->surface_to_descriptor[i].set !=
ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
break;
/* Helping Alpine builders... */
assert(i < MAX_RTS);
if (bind_map->surface_to_descriptor[i].index >= MAX_RTS)
pipeline->color_output_mapping[i] = MESA_VK_ATTACHMENT_UNUSED;
}
pipeline->num_color_outputs = i;
}
}
const struct anv_device *device = pipeline->base.base.device; const struct anv_device *device = pipeline->base.base.device;
const struct intel_device_info *devinfo = device->info; const struct intel_device_info *devinfo = device->info;
anv_genX(devinfo, graphics_pipeline_emit)(pipeline, state); anv_genX(devinfo, graphics_pipeline_emit)(pipeline, state);

View File

@@ -3822,11 +3822,10 @@ struct anv_cmd_graphics_state {
struct anv_attachment stencil_att; struct anv_attachment stencil_att;
struct anv_state null_surface_state; struct anv_state null_surface_state;
/* Bitfield of color attachments disabled by a pipeline (pointing a null /* Map of color output from the last dispatched fragment shader to color
* surface state in the last emitted binding table for the fragment * attachments in the render pass.
* stage)
*/ */
uint8_t disabled_color_atts; uint8_t color_output_mapping[MAX_RTS];
anv_cmd_dirty_mask_t dirty; anv_cmd_dirty_mask_t dirty;
uint32_t vb_dirty; uint32_t vb_dirty;
@@ -4781,6 +4780,13 @@ struct anv_graphics_pipeline {
uint32_t vertex_input_elems; uint32_t vertex_input_elems;
uint32_t vertex_input_data[2 * 31 /* MAX_VES + 2 internal */]; uint32_t vertex_input_data[2 * 31 /* MAX_VES + 2 internal */];
/* Number of color outputs used by the fragment shader. */
uint8_t num_color_outputs;
/* Map of color output of the fragment shader to color attachments in the
* render pass.
*/
uint8_t color_output_mapping[MAX_RTS];
/* Pre computed CS instructions that can directly be copied into /* Pre computed CS instructions that can directly be copied into
* anv_cmd_buffer. * anv_cmd_buffer.
*/ */
@@ -5901,7 +5907,8 @@ static inline const struct anv_surface_state *
anv_image_view_texture_surface_state(const struct anv_image_view *iview, anv_image_view_texture_surface_state(const struct anv_image_view *iview,
uint32_t plane, VkImageLayout layout) uint32_t plane, VkImageLayout layout)
{ {
return layout == VK_IMAGE_LAYOUT_GENERAL ? return (layout == VK_IMAGE_LAYOUT_GENERAL ||
layout == VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) ?
&iview->planes[plane].general_sampler : &iview->planes[plane].general_sampler :
&iview->planes[plane].optimal_sampler; &iview->planes[plane].optimal_sampler;
} }

View File

@@ -2098,9 +2098,12 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
case ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS: case ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS:
/* Color attachment binding */ /* Color attachment binding */
assert(shader->stage == MESA_SHADER_FRAGMENT); assert(shader->stage == MESA_SHADER_FRAGMENT);
if (binding->index < cmd_buffer->state.gfx.color_att_count) { uint32_t index = binding->index < MAX_RTS ?
cmd_buffer->state.gfx.color_output_mapping[binding->index] :
binding->index;
if (index < cmd_buffer->state.gfx.color_att_count) {
const struct anv_attachment *att = const struct anv_attachment *att =
&cmd_buffer->state.gfx.color_att[binding->index]; &cmd_buffer->state.gfx.color_att[index];
surface_state = att->surface_state.state; surface_state = att->surface_state.state;
} else { } else {
surface_state = cmd_buffer->state.gfx.null_surface_state; surface_state = cmd_buffer->state.gfx.null_surface_state;

View File

@@ -689,35 +689,24 @@ genX(emit_ds)(struct anv_cmd_buffer *cmd_buffer)
ALWAYS_INLINE static void ALWAYS_INLINE static void
cmd_buffer_maybe_flush_rt_writes(struct anv_cmd_buffer *cmd_buffer, cmd_buffer_maybe_flush_rt_writes(struct anv_cmd_buffer *cmd_buffer,
struct anv_graphics_pipeline *pipeline) const struct anv_graphics_pipeline *pipeline)
{ {
#if GFX_VER >= 11
if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT))
return; return;
const struct anv_shader_bin *shader = UNUSED bool need_rt_flush = false;
pipeline->base.shaders[MESA_SHADER_FRAGMENT]; if (memcmp(cmd_buffer->state.gfx.color_output_mapping,
const struct anv_pipeline_bind_map *bind_map = &shader->bind_map; pipeline->color_output_mapping,
pipeline->num_color_outputs)) {
unsigned s; memcpy(cmd_buffer->state.gfx.color_output_mapping,
uint8_t disabled_mask = 0; pipeline->color_output_mapping,
for (s = 0; s < bind_map->surface_count; s++) { pipeline->num_color_outputs);
const struct anv_pipeline_binding *binding = need_rt_flush = true;
&bind_map->surface_to_descriptor[s]; cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_FRAGMENT_BIT;
if (binding->set != ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
break;
if (binding->index >= cmd_buffer->state.gfx.color_att_count)
disabled_mask |= BITFIELD_BIT(s);
} }
const uint8_t diff_mask = (1u << s) - 1; #if GFX_VER >= 11
if (need_rt_flush) {
if ((cmd_buffer->state.gfx.disabled_color_atts & diff_mask) != disabled_mask) {
cmd_buffer->state.gfx.disabled_color_atts = disabled_mask |
(cmd_buffer->state.gfx.disabled_color_atts & ~diff_mask);
/* The PIPE_CONTROL command description says: /* The PIPE_CONTROL command description says:
* *
* "Whenever a Binding Table Index (BTI) used by a Render Target Message * "Whenever a Binding Table Index (BTI) used by a Render Target Message

View File

@@ -132,8 +132,10 @@ get_cps_state_offset(struct anv_cmd_buffer *cmd_buffer, bool cps_enabled,
static bool static bool
has_ds_feedback_loop(const struct vk_dynamic_graphics_state *dyn) has_ds_feedback_loop(const struct vk_dynamic_graphics_state *dyn)
{ {
return dyn->feedback_loops & (VK_IMAGE_ASPECT_DEPTH_BIT | return (dyn->feedback_loops & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT); VK_IMAGE_ASPECT_STENCIL_BIT)) ||
dyn->ial.depth_att != MESA_VK_ATTACHMENT_UNUSED ||
dyn->ial.stencil_att != MESA_VK_ATTACHMENT_UNUSED;
} }
UNUSED static bool UNUSED static bool
@@ -1081,32 +1083,41 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
SET(BLEND_STATE, blend.AlphaToOneEnable, SET(BLEND_STATE, blend.AlphaToOneEnable,
dyn->ms.alpha_to_one_enable); dyn->ms.alpha_to_one_enable);
SET(BLEND_STATE, blend.ColorDitherEnable, SET(BLEND_STATE, blend.ColorDitherEnable,
cmd_buffer->state.gfx.rendering_flags & VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT); cmd_buffer->state.gfx.rendering_flags &
VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT);
bool independent_alpha_blend = false; bool independent_alpha_blend = false;
/* Wa_14018912822, check if we set these during RT setup. */ /* Wa_14018912822, check if we set these during RT setup. */
bool color_blend_zero = false; bool color_blend_zero = false;
bool alpha_blend_zero = false; bool alpha_blend_zero = false;
for (uint32_t i = 0; i < MAX_RTS; i++) { uint32_t rt_0 = MESA_VK_ATTACHMENT_UNUSED;
/* Disable anything above the current number of color attachments. */ for (uint32_t rt = 0; rt < MAX_RTS; rt++) {
bool write_disabled = i >= gfx->color_att_count || if (cmd_buffer->state.gfx.color_output_mapping[rt] >=
(color_writes & BITFIELD_BIT(i)) == 0; cmd_buffer->state.gfx.color_att_count)
continue;
SET(BLEND_STATE, blend.rts[i].WriteDisableAlpha, uint32_t att = cmd_buffer->state.gfx.color_output_mapping[rt];
if (att == 0)
rt_0 = att;
/* Disable anything above the current number of color attachments. */
bool write_disabled = (color_writes & BITFIELD_BIT(att)) == 0;
SET(BLEND_STATE, blend.rts[rt].WriteDisableAlpha,
write_disabled || write_disabled ||
(dyn->cb.attachments[i].write_mask & (dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_A_BIT) == 0); VK_COLOR_COMPONENT_A_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableRed, SET(BLEND_STATE, blend.rts[rt].WriteDisableRed,
write_disabled || write_disabled ||
(dyn->cb.attachments[i].write_mask & (dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_R_BIT) == 0); VK_COLOR_COMPONENT_R_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableGreen, SET(BLEND_STATE, blend.rts[rt].WriteDisableGreen,
write_disabled || write_disabled ||
(dyn->cb.attachments[i].write_mask & (dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_G_BIT) == 0); VK_COLOR_COMPONENT_G_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableBlue, SET(BLEND_STATE, blend.rts[rt].WriteDisableBlue,
write_disabled || write_disabled ||
(dyn->cb.attachments[i].write_mask & (dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_B_BIT) == 0); VK_COLOR_COMPONENT_B_BIT) == 0);
/* Vulkan specification 1.2.168, VkLogicOp: /* Vulkan specification 1.2.168, VkLogicOp:
* *
@@ -1123,28 +1134,28 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
* "Enabling LogicOp and Color Buffer Blending at the same time is * "Enabling LogicOp and Color Buffer Blending at the same time is
* UNDEFINED" * UNDEFINED"
*/ */
SET(BLEND_STATE, blend.rts[i].LogicOpFunction, SET(BLEND_STATE, blend.rts[rt].LogicOpFunction,
genX(vk_to_intel_logic_op)[dyn->cb.logic_op]); genX(vk_to_intel_logic_op)[dyn->cb.logic_op]);
SET(BLEND_STATE, blend.rts[i].LogicOpEnable, dyn->cb.logic_op_enable); SET(BLEND_STATE, blend.rts[rt].LogicOpEnable, dyn->cb.logic_op_enable);
SET(BLEND_STATE, blend.rts[i].ColorClampRange, COLORCLAMP_RTFORMAT); SET(BLEND_STATE, blend.rts[rt].ColorClampRange, COLORCLAMP_RTFORMAT);
SET(BLEND_STATE, blend.rts[i].PreBlendColorClampEnable, true); SET(BLEND_STATE, blend.rts[rt].PreBlendColorClampEnable, true);
SET(BLEND_STATE, blend.rts[i].PostBlendColorClampEnable, true); SET(BLEND_STATE, blend.rts[rt].PostBlendColorClampEnable, true);
/* Setup blend equation. */ /* Setup blend equation. */
SET(BLEND_STATE, blend.rts[i].ColorBlendFunction, SET(BLEND_STATE, blend.rts[rt].ColorBlendFunction,
genX(vk_to_intel_blend_op)[ genX(vk_to_intel_blend_op)[
dyn->cb.attachments[i].color_blend_op]); dyn->cb.attachments[att].color_blend_op]);
SET(BLEND_STATE, blend.rts[i].AlphaBlendFunction, SET(BLEND_STATE, blend.rts[rt].AlphaBlendFunction,
genX(vk_to_intel_blend_op)[ genX(vk_to_intel_blend_op)[
dyn->cb.attachments[i].alpha_blend_op]); dyn->cb.attachments[att].alpha_blend_op]);
if (dyn->cb.attachments[i].src_color_blend_factor != if (dyn->cb.attachments[att].src_color_blend_factor !=
dyn->cb.attachments[i].src_alpha_blend_factor || dyn->cb.attachments[att].src_alpha_blend_factor ||
dyn->cb.attachments[i].dst_color_blend_factor != dyn->cb.attachments[att].dst_color_blend_factor !=
dyn->cb.attachments[i].dst_alpha_blend_factor || dyn->cb.attachments[att].dst_alpha_blend_factor ||
dyn->cb.attachments[i].color_blend_op != dyn->cb.attachments[att].color_blend_op !=
dyn->cb.attachments[i].alpha_blend_op) { dyn->cb.attachments[att].alpha_blend_op) {
independent_alpha_blend = true; independent_alpha_blend = true;
} }
@@ -1160,12 +1171,12 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
* so we just disable the blending to prevent possible issues. * so we just disable the blending to prevent possible issues.
*/ */
if (wm_prog_data && !wm_prog_data->dual_src_blend && if (wm_prog_data && !wm_prog_data->dual_src_blend &&
anv_is_dual_src_blend_equation(&dyn->cb.attachments[i])) { anv_is_dual_src_blend_equation(&dyn->cb.attachments[att])) {
SET(BLEND_STATE, blend.rts[i].ColorBufferBlendEnable, false); SET(BLEND_STATE, blend.rts[rt].ColorBufferBlendEnable, false);
} else { } else {
SET(BLEND_STATE, blend.rts[i].ColorBufferBlendEnable, SET(BLEND_STATE, blend.rts[rt].ColorBufferBlendEnable,
!dyn->cb.logic_op_enable && !dyn->cb.logic_op_enable &&
dyn->cb.attachments[i].blend_enable); dyn->cb.attachments[att].blend_enable);
} }
/* Our hardware applies the blend factor prior to the blend function /* Our hardware applies the blend factor prior to the blend function
@@ -1178,26 +1189,26 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
uint32_t DestinationBlendFactor; uint32_t DestinationBlendFactor;
uint32_t SourceAlphaBlendFactor; uint32_t SourceAlphaBlendFactor;
uint32_t DestinationAlphaBlendFactor; uint32_t DestinationAlphaBlendFactor;
if (dyn->cb.attachments[i].color_blend_op == VK_BLEND_OP_MIN || if (dyn->cb.attachments[att].color_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[i].color_blend_op == VK_BLEND_OP_MAX) { dyn->cb.attachments[att].color_blend_op == VK_BLEND_OP_MAX) {
SourceBlendFactor = BLENDFACTOR_ONE; SourceBlendFactor = BLENDFACTOR_ONE;
DestinationBlendFactor = BLENDFACTOR_ONE; DestinationBlendFactor = BLENDFACTOR_ONE;
} else { } else {
SourceBlendFactor = genX(vk_to_intel_blend)[ SourceBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].src_color_blend_factor]; dyn->cb.attachments[att].src_color_blend_factor];
DestinationBlendFactor = genX(vk_to_intel_blend)[ DestinationBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].dst_color_blend_factor]; dyn->cb.attachments[att].dst_color_blend_factor];
} }
if (dyn->cb.attachments[i].alpha_blend_op == VK_BLEND_OP_MIN || if (dyn->cb.attachments[att].alpha_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[i].alpha_blend_op == VK_BLEND_OP_MAX) { dyn->cb.attachments[att].alpha_blend_op == VK_BLEND_OP_MAX) {
SourceAlphaBlendFactor = BLENDFACTOR_ONE; SourceAlphaBlendFactor = BLENDFACTOR_ONE;
DestinationAlphaBlendFactor = BLENDFACTOR_ONE; DestinationAlphaBlendFactor = BLENDFACTOR_ONE;
} else { } else {
SourceAlphaBlendFactor = genX(vk_to_intel_blend)[ SourceAlphaBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].src_alpha_blend_factor]; dyn->cb.attachments[att].src_alpha_blend_factor];
DestinationAlphaBlendFactor = genX(vk_to_intel_blend)[ DestinationAlphaBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].dst_alpha_blend_factor]; dyn->cb.attachments[att].dst_alpha_blend_factor];
} }
/* Replace and Src1 value by 1.0 if dual source blending is not /* Replace and Src1 value by 1.0 if dual source blending is not
@@ -1223,32 +1234,42 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
} }
} }
SET(BLEND_STATE, blend.rts[i].SourceBlendFactor, SourceBlendFactor); SET(BLEND_STATE, blend.rts[rt].SourceBlendFactor, SourceBlendFactor);
SET(BLEND_STATE, blend.rts[i].DestinationBlendFactor, DestinationBlendFactor); SET(BLEND_STATE, blend.rts[rt].DestinationBlendFactor, DestinationBlendFactor);
SET(BLEND_STATE, blend.rts[i].SourceAlphaBlendFactor, SourceAlphaBlendFactor); SET(BLEND_STATE, blend.rts[rt].SourceAlphaBlendFactor, SourceAlphaBlendFactor);
SET(BLEND_STATE, blend.rts[i].DestinationAlphaBlendFactor, DestinationAlphaBlendFactor); SET(BLEND_STATE, blend.rts[rt].DestinationAlphaBlendFactor, DestinationAlphaBlendFactor);
} }
gfx->color_blend_zero = color_blend_zero; gfx->color_blend_zero = color_blend_zero;
gfx->alpha_blend_zero = alpha_blend_zero; gfx->alpha_blend_zero = alpha_blend_zero;
SET(BLEND_STATE, blend.IndependentAlphaBlendEnable, independent_alpha_blend); SET(BLEND_STATE, blend.IndependentAlphaBlendEnable, independent_alpha_blend);
if (rt_0 == MESA_VK_ATTACHMENT_UNUSED)
rt_0 = 0;
/* 3DSTATE_PS_BLEND to be consistent with the rest of the /* 3DSTATE_PS_BLEND to be consistent with the rest of the
* BLEND_STATE_ENTRY. * BLEND_STATE_ENTRY.
*/ */
SET(PS_BLEND, ps_blend.HasWriteableRT, has_writeable_rt); SET(PS_BLEND, ps_blend.HasWriteableRT, has_writeable_rt);
SET(PS_BLEND, ps_blend.ColorBufferBlendEnable, GET(blend.rts[0].ColorBufferBlendEnable)); SET(PS_BLEND, ps_blend.ColorBufferBlendEnable,
SET(PS_BLEND, ps_blend.SourceAlphaBlendFactor, GET(blend.rts[0].SourceAlphaBlendFactor)); GET(blend.rts[rt_0].ColorBufferBlendEnable));
SET(PS_BLEND, ps_blend.DestinationAlphaBlendFactor, gfx->alpha_blend_zero ? SET(PS_BLEND, ps_blend.SourceAlphaBlendFactor,
BLENDFACTOR_CONST_ALPHA : GET(blend.rts[rt_0].SourceAlphaBlendFactor));
GET(blend.rts[0].DestinationAlphaBlendFactor)); SET(PS_BLEND, ps_blend.DestinationAlphaBlendFactor,
SET(PS_BLEND, ps_blend.SourceBlendFactor, GET(blend.rts[0].SourceBlendFactor)); gfx->alpha_blend_zero ?
SET(PS_BLEND, ps_blend.DestinationBlendFactor, gfx->color_blend_zero ? BLENDFACTOR_CONST_ALPHA :
BLENDFACTOR_CONST_COLOR : GET(blend.rts[rt_0].DestinationAlphaBlendFactor));
GET(blend.rts[0].DestinationBlendFactor)); SET(PS_BLEND, ps_blend.SourceBlendFactor,
GET(blend.rts[rt_0].SourceBlendFactor));
SET(PS_BLEND, ps_blend.DestinationBlendFactor,
gfx->color_blend_zero ?
BLENDFACTOR_CONST_COLOR :
GET(blend.rts[rt_0].DestinationBlendFactor));
SET(PS_BLEND, ps_blend.AlphaTestEnable, false); SET(PS_BLEND, ps_blend.AlphaTestEnable, false);
SET(PS_BLEND, ps_blend.IndependentAlphaBlendEnable, GET(blend.IndependentAlphaBlendEnable)); SET(PS_BLEND, ps_blend.IndependentAlphaBlendEnable,
SET(PS_BLEND, ps_blend.AlphaToCoverageEnable, dyn->ms.alpha_to_coverage_enable); GET(blend.IndependentAlphaBlendEnable));
SET(PS_BLEND, ps_blend.AlphaToCoverageEnable,
dyn->ms.alpha_to_coverage_enable);
} }
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) { if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {