anv: fix color write enable interaction with color mask
Color writes & color masks occupy the same fields in the BLEND_STATE
structure. So we need to store color mask (which are not dynamic) on
the pipeline to merge that information with color writes.
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Fixes: b15bfe92f7
("anv: implement VK_EXT_color_write_enable")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6111
Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15310>
This commit is contained in:
parent
a4f502de32
commit
1d250b7b95
|
@ -2058,6 +2058,16 @@ anv_pipeline_compile_cs(struct anv_compute_pipeline *pipeline,
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
anv_rendering_uses_color_attachment(const VkPipelineRenderingCreateInfo *rendering_info)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
|
||||||
|
if (rendering_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy pipeline state not marked as dynamic.
|
* Copy pipeline state not marked as dynamic.
|
||||||
* Dynamic state is pipeline state which hasn't been provided at pipeline
|
* Dynamic state is pipeline state which hasn't been provided at pipeline
|
||||||
|
@ -2176,13 +2186,7 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
|
||||||
* disabled or if the subpass of the render pass the pipeline is
|
* disabled or if the subpass of the render pass the pipeline is
|
||||||
* created against does not use any color attachments.
|
* created against does not use any color attachments.
|
||||||
*/
|
*/
|
||||||
bool uses_color_att = false;
|
bool uses_color_att = anv_rendering_uses_color_attachment(rendering_info);
|
||||||
for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
|
|
||||||
if (rendering_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED) {
|
|
||||||
uses_color_att = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uses_color_att && !raster_discard) {
|
if (uses_color_att && !raster_discard) {
|
||||||
assert(pCreateInfo->pColorBlendState);
|
assert(pCreateInfo->pColorBlendState);
|
||||||
|
@ -2555,6 +2559,17 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
|
||||||
pipeline->rasterization_samples =
|
pipeline->rasterization_samples =
|
||||||
ms_info ? ms_info->rasterizationSamples : 1;
|
ms_info ? ms_info->rasterizationSamples : 1;
|
||||||
|
|
||||||
|
/* Store the color write masks, to be merged with color write enable if
|
||||||
|
* dynamic.
|
||||||
|
*/
|
||||||
|
if (raster_enabled && anv_rendering_uses_color_attachment(rendering_info)) {
|
||||||
|
for (unsigned i = 0; i < pCreateInfo->pColorBlendState->attachmentCount; i++) {
|
||||||
|
const VkPipelineColorBlendAttachmentState *a =
|
||||||
|
&pCreateInfo->pColorBlendState->pAttachments[i];
|
||||||
|
pipeline->color_comp_writes[i] = a->colorWriteMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3383,6 +3383,8 @@ struct anv_graphics_pipeline {
|
||||||
VkPolygonMode polygon_mode;
|
VkPolygonMode polygon_mode;
|
||||||
uint32_t rasterization_samples;
|
uint32_t rasterization_samples;
|
||||||
|
|
||||||
|
VkColorComponentFlags color_comp_writes[MAX_RTS];
|
||||||
|
|
||||||
struct anv_shader_bin * shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
|
struct anv_shader_bin * shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
|
||||||
|
|
||||||
VkShaderStageFlags active_stages;
|
VkShaderStageFlags active_stages;
|
||||||
|
@ -3505,6 +3507,25 @@ anv_pipeline_is_mesh(const struct anv_graphics_pipeline *pipeline)
|
||||||
return anv_pipeline_has_stage(pipeline, MESA_SHADER_MESH);
|
return anv_pipeline_has_stage(pipeline, MESA_SHADER_MESH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
anv_cmd_buffer_all_color_write_masked(const struct anv_cmd_buffer *cmd_buffer)
|
||||||
|
{
|
||||||
|
const struct anv_cmd_graphics_state *state = &cmd_buffer->state.gfx;
|
||||||
|
uint8_t color_writes = state->dynamic.color_writes;
|
||||||
|
|
||||||
|
/* All writes disabled through vkCmdSetColorWriteEnableEXT */
|
||||||
|
if ((color_writes & ((1u << state->color_att_count) - 1)) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Or all write masks are empty */
|
||||||
|
for (uint32_t i = 0; i < state->color_att_count; i++) {
|
||||||
|
if (state->pipeline->color_comp_writes[i] != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#define ANV_DECL_GET_GRAPHICS_PROG_DATA_FUNC(prefix, stage) \
|
#define ANV_DECL_GET_GRAPHICS_PROG_DATA_FUNC(prefix, stage) \
|
||||||
static inline const struct brw_##prefix##_prog_data * \
|
static inline const struct brw_##prefix##_prog_data * \
|
||||||
get_##prefix##_prog_data(const struct anv_graphics_pipeline *pipeline) \
|
get_##prefix##_prog_data(const struct anv_graphics_pipeline *pipeline) \
|
||||||
|
|
|
@ -1406,8 +1406,6 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
|
||||||
.AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
|
.AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
|
||||||
#endif
|
#endif
|
||||||
.LogicOpEnable = info->logicOpEnable,
|
.LogicOpEnable = info->logicOpEnable,
|
||||||
.LogicOpFunction = dynamic_states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP ?
|
|
||||||
0: genX(vk_to_intel_logic_op)[info->logicOp],
|
|
||||||
|
|
||||||
/* Vulkan specification 1.2.168, VkLogicOp:
|
/* Vulkan specification 1.2.168, VkLogicOp:
|
||||||
*
|
*
|
||||||
|
@ -1434,20 +1432,20 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
|
||||||
.SourceAlphaBlendFactor = vk_to_intel_blend[a->srcAlphaBlendFactor],
|
.SourceAlphaBlendFactor = vk_to_intel_blend[a->srcAlphaBlendFactor],
|
||||||
.DestinationAlphaBlendFactor = vk_to_intel_blend[a->dstAlphaBlendFactor],
|
.DestinationAlphaBlendFactor = vk_to_intel_blend[a->dstAlphaBlendFactor],
|
||||||
.AlphaBlendFunction = vk_to_intel_blend_op[a->alphaBlendOp],
|
.AlphaBlendFunction = vk_to_intel_blend_op[a->alphaBlendOp],
|
||||||
.WriteDisableAlpha =
|
|
||||||
(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
|
|
||||||
!(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT),
|
|
||||||
.WriteDisableRed =
|
|
||||||
(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
|
|
||||||
!(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT),
|
|
||||||
.WriteDisableGreen =
|
|
||||||
(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
|
|
||||||
!(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT),
|
|
||||||
.WriteDisableBlue =
|
|
||||||
(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) == 0 &&
|
|
||||||
!(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Write logic op if not dynamic */
|
||||||
|
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP))
|
||||||
|
entry.LogicOpFunction = genX(vk_to_intel_logic_op)[info->logicOp];
|
||||||
|
|
||||||
|
/* Write blending color if not dynamic */
|
||||||
|
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
|
||||||
|
entry.WriteDisableAlpha = !(a->colorWriteMask & VK_COLOR_COMPONENT_A_BIT);
|
||||||
|
entry.WriteDisableRed = !(a->colorWriteMask & VK_COLOR_COMPONENT_R_BIT);
|
||||||
|
entry.WriteDisableGreen = !(a->colorWriteMask & VK_COLOR_COMPONENT_G_BIT);
|
||||||
|
entry.WriteDisableBlue = !(a->colorWriteMask & VK_COLOR_COMPONENT_B_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
|
if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
|
||||||
a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
|
a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
|
||||||
a->colorBlendOp != a->alphaBlendOp) {
|
a->colorBlendOp != a->alphaBlendOp) {
|
||||||
|
@ -2319,11 +2317,11 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
|
||||||
wm_prog_data->has_side_effects ||
|
wm_prog_data->has_side_effects ||
|
||||||
wm_prog_data->uses_kill;
|
wm_prog_data->uses_kill;
|
||||||
|
|
||||||
if (pipeline->force_fragment_thread_dispatch ||
|
/* Only set this value in non dynamic mode. */
|
||||||
!has_color_buffer_write_enabled(pipeline, blend)) {
|
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
|
||||||
/* Only set this value in non dynamic mode. */
|
|
||||||
wm.ForceThreadDispatchEnable =
|
wm.ForceThreadDispatchEnable =
|
||||||
!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) ? ForceON : 0;
|
(pipeline->force_fragment_thread_dispatch ||
|
||||||
|
!has_color_buffer_write_enabled(pipeline, blend)) ? ForceON : 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2352,10 +2350,11 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
|
||||||
wm_prog_data->has_side_effects ||
|
wm_prog_data->has_side_effects ||
|
||||||
wm.PixelShaderKillsPixel;
|
wm.PixelShaderKillsPixel;
|
||||||
|
|
||||||
if (pipeline->force_fragment_thread_dispatch ||
|
/* Only set this value in non dynamic mode. */
|
||||||
has_color_buffer_write_enabled(pipeline, blend)) {
|
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)) {
|
||||||
/* Only set this value in non dynamic mode. */
|
wm.ThreadDispatchEnable =
|
||||||
wm.ThreadDispatchEnable = !(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE);
|
pipeline->force_fragment_thread_dispatch ||
|
||||||
|
has_color_buffer_write_enabled(pipeline, blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multisample && multisample->rasterizationSamples > 1) {
|
if (multisample && multisample->rasterizationSamples > 1) {
|
||||||
|
|
|
@ -290,13 +290,12 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
|
genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
|
||||||
primitive_topology);
|
primitive_topology);
|
||||||
|
|
||||||
const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
|
|
||||||
uint32_t dwords[GENX(3DSTATE_WM_length)];
|
uint32_t dwords[GENX(3DSTATE_WM_length)];
|
||||||
struct GENX(3DSTATE_WM) wm = {
|
struct GENX(3DSTATE_WM) wm = {
|
||||||
GENX(3DSTATE_WM_header),
|
GENX(3DSTATE_WM_header),
|
||||||
|
|
||||||
.ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch ||
|
.ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch ||
|
||||||
color_writes,
|
!anv_cmd_buffer_all_color_write_masked(cmd_buffer),
|
||||||
.MultisampleRasterizationMode =
|
.MultisampleRasterizationMode =
|
||||||
genX(ms_rasterization_mode)(pipeline,
|
genX(ms_rasterization_mode)(pipeline,
|
||||||
dynamic_raster_mode),
|
dynamic_raster_mode),
|
||||||
|
@ -317,8 +316,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
|
ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
|
||||||
ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)) {
|
ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)) {
|
||||||
const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
|
const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
|
||||||
bool dirty_color_blend =
|
|
||||||
cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
|
|
||||||
|
|
||||||
uint32_t blend_dws[GENX(BLEND_STATE_length) +
|
uint32_t blend_dws[GENX(BLEND_STATE_length) +
|
||||||
MAX_RTS * GENX(BLEND_STATE_ENTRY_length)];
|
MAX_RTS * GENX(BLEND_STATE_ENTRY_length)];
|
||||||
|
@ -328,19 +325,24 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
/* Skip this part */
|
/* Skip this part */
|
||||||
dws += GENX(BLEND_STATE_length);
|
dws += GENX(BLEND_STATE_length);
|
||||||
|
|
||||||
bool dirty_logic_op =
|
|
||||||
cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAX_RTS; i++) {
|
for (uint32_t i = 0; i < MAX_RTS; i++) {
|
||||||
bool write_disabled = dirty_color_blend &&
|
/* Disable anything above the current number of color attachments. */
|
||||||
(color_writes & BITFIELD_BIT(i)) == 0;
|
bool write_disabled = i >= cmd_buffer->state.gfx.color_att_count ||
|
||||||
|
(color_writes & BITFIELD_BIT(i)) == 0;
|
||||||
struct GENX(BLEND_STATE_ENTRY) entry = {
|
struct GENX(BLEND_STATE_ENTRY) entry = {
|
||||||
.WriteDisableAlpha = write_disabled,
|
.WriteDisableAlpha = write_disabled ||
|
||||||
.WriteDisableRed = write_disabled,
|
(pipeline->color_comp_writes[i] &
|
||||||
.WriteDisableGreen = write_disabled,
|
VK_COLOR_COMPONENT_A_BIT) == 0,
|
||||||
.WriteDisableBlue = write_disabled,
|
.WriteDisableRed = write_disabled ||
|
||||||
.LogicOpFunction =
|
(pipeline->color_comp_writes[i] &
|
||||||
dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0,
|
VK_COLOR_COMPONENT_R_BIT) == 0,
|
||||||
|
.WriteDisableGreen = write_disabled ||
|
||||||
|
(pipeline->color_comp_writes[i] &
|
||||||
|
VK_COLOR_COMPONENT_G_BIT) == 0,
|
||||||
|
.WriteDisableBlue = write_disabled ||
|
||||||
|
(pipeline->color_comp_writes[i] &
|
||||||
|
VK_COLOR_COMPONENT_B_BIT) == 0,
|
||||||
|
.LogicOpFunction = genX(vk_to_intel_logic_op)[d->logic_op],
|
||||||
};
|
};
|
||||||
GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
|
GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
|
||||||
dws += GENX(BLEND_STATE_ENTRY_length);
|
dws += GENX(BLEND_STATE_ENTRY_length);
|
||||||
|
|
|
@ -642,7 +642,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
|
ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE |
|
||||||
ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)) {
|
ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)) {
|
||||||
const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
|
const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes;
|
||||||
|
|
||||||
/* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
|
/* 3DSTATE_WM in the hope we can avoid spawning fragment shaders
|
||||||
* threads.
|
* threads.
|
||||||
*/
|
*/
|
||||||
|
@ -651,7 +650,8 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
GENX(3DSTATE_WM_header),
|
GENX(3DSTATE_WM_header),
|
||||||
|
|
||||||
.ForceThreadDispatchEnable = (pipeline->force_fragment_thread_dispatch ||
|
.ForceThreadDispatchEnable = (pipeline->force_fragment_thread_dispatch ||
|
||||||
!color_writes) ? ForceON : 0,
|
anv_cmd_buffer_all_color_write_masked(cmd_buffer)) ?
|
||||||
|
ForceON : 0,
|
||||||
};
|
};
|
||||||
GENX(3DSTATE_WM_pack)(NULL, wm_dwords, &wm);
|
GENX(3DSTATE_WM_pack)(NULL, wm_dwords, &wm);
|
||||||
|
|
||||||
|
@ -677,18 +677,24 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
/* Skip this part */
|
/* Skip this part */
|
||||||
dws += GENX(BLEND_STATE_length);
|
dws += GENX(BLEND_STATE_length);
|
||||||
|
|
||||||
bool dirty_logic_op =
|
|
||||||
cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAX_RTS; i++) {
|
for (uint32_t i = 0; i < MAX_RTS; i++) {
|
||||||
bool write_disabled = (color_writes & BITFIELD_BIT(i)) == 0;
|
/* Disable anything above the current number of color attachments. */
|
||||||
|
bool write_disabled = i >= cmd_buffer->state.gfx.color_att_count ||
|
||||||
|
(color_writes & BITFIELD_BIT(i)) == 0;
|
||||||
struct GENX(BLEND_STATE_ENTRY) entry = {
|
struct GENX(BLEND_STATE_ENTRY) entry = {
|
||||||
.WriteDisableAlpha = write_disabled,
|
.WriteDisableAlpha = write_disabled ||
|
||||||
.WriteDisableRed = write_disabled,
|
(pipeline->color_comp_writes[i] &
|
||||||
.WriteDisableGreen = write_disabled,
|
VK_COLOR_COMPONENT_A_BIT) == 0,
|
||||||
.WriteDisableBlue = write_disabled,
|
.WriteDisableRed = write_disabled ||
|
||||||
.LogicOpFunction =
|
(pipeline->color_comp_writes[i] &
|
||||||
dirty_logic_op ? genX(vk_to_intel_logic_op)[d->logic_op] : 0,
|
VK_COLOR_COMPONENT_R_BIT) == 0,
|
||||||
|
.WriteDisableGreen = write_disabled ||
|
||||||
|
(pipeline->color_comp_writes[i] &
|
||||||
|
VK_COLOR_COMPONENT_G_BIT) == 0,
|
||||||
|
.WriteDisableBlue = write_disabled ||
|
||||||
|
(pipeline->color_comp_writes[i] &
|
||||||
|
VK_COLOR_COMPONENT_B_BIT) == 0,
|
||||||
|
.LogicOpFunction = genX(vk_to_intel_logic_op)[d->logic_op],
|
||||||
};
|
};
|
||||||
GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
|
GENX(BLEND_STATE_ENTRY_pack)(NULL, dws, &entry);
|
||||||
dws += GENX(BLEND_STATE_ENTRY_length);
|
dws += GENX(BLEND_STATE_ENTRY_length);
|
||||||
|
|
Loading…
Reference in New Issue