diff --git a/docs/features.txt b/docs/features.txt index c7e4608b92e..806fe22d035 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -508,7 +508,7 @@ Khronos extensions that are not part of any Vulkan version: VK_KHR_zero_initialize_workgroup_memory DONE (anv, radv) VK_EXT_4444_formats DONE (anv, radv, tu) VK_EXT_calibrated_timestamps DONE (anv, lvp, radv) - VK_EXT_color_write_enable DONE (anv, lvp) + VK_EXT_color_write_enable DONE (anv, lvp, v3dv) VK_EXT_conditional_rendering DONE (anv, lvp, radv, tu) VK_EXT_conservative_rasterization DONE (anv/gen9+, radv) VK_EXT_custom_border_color DONE (anv, lvp, radv, tu, v3dv) diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index c52c9093814..7d19091c0d7 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -55,6 +55,7 @@ const struct v3dv_dynamic_state default_dynamic_state = { .slope_factor = 0.0f, }, .line_width = 1.0f, + .color_write_enable = (1ull << (4 * V3D_MAX_DRAW_BUFFERS)) - 1, }; void @@ -1870,6 +1871,13 @@ cmd_buffer_bind_pipeline_static_state(struct v3dv_cmd_buffer *cmd_buffer, } } + 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; } @@ -2541,6 +2549,9 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *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)) + v3dv_X(device, cmd_buffer_emit_color_write_mask)(cmd_buffer); + cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_PIPELINE; } @@ -2965,6 +2976,26 @@ v3dv_CmdSetBlendConstants(VkCommandBuffer commandBuffer, 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_reset_queries(struct v3dv_cmd_buffer *cmd_buffer, struct v3dv_query_pool *pool, diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index 52f3e2612cc..fad94493c29 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -139,6 +139,7 @@ get_device_extensions(const struct v3dv_physical_device *device, .KHR_incremental_present = true, #endif .KHR_variable_pointers = true, + .EXT_color_write_enable = true, .EXT_custom_border_color = true, .EXT_external_memory_dma_buf = true, .EXT_index_type_uint8 = true, @@ -1101,6 +1102,12 @@ v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: { + VkPhysicalDeviceColorWriteEnableFeaturesEXT *features = (void *) ext; + features->colorWriteEnable = true; + break; + } + /* Vulkan 1.1 */ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: { VkPhysicalDeviceVulkan11Features *features = diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index 5f05bd3867d..43a442cd169 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -2548,6 +2548,8 @@ v3dv_dynamic_state_mask(VkDynamicState state) 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; /* Depth bounds testing is not available in in V3D 4.2 so here we are just * ignoring this dynamic state. We are already asserting at pipeline creation @@ -2568,7 +2570,8 @@ pipeline_init_dynamic_state( const VkPipelineViewportStateCreateInfo *pViewportState, const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState, const VkPipelineColorBlendStateCreateInfo *pColorBlendState, - const VkPipelineRasterizationStateCreateInfo *pRasterizationState) + const VkPipelineRasterizationStateCreateInfo *pRasterizationState, + const VkPipelineColorWriteCreateInfoEXT *pColorWriteState) { pipeline->dynamic_state = default_dynamic_state; struct v3dv_dynamic_state *dynamic = &pipeline->dynamic_state; @@ -2644,6 +2647,12 @@ pipeline_init_dynamic_state( 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; } @@ -2843,9 +2852,14 @@ pipeline_init(struct v3dv_pipeline *pipeline, const VkPipelineMultisampleStateCreateInfo *ms_info = raster_enabled ? pCreateInfo->pMultisampleState : NULL; + const VkPipelineColorWriteCreateInfoEXT *cw_info = + cb_info ? vk_find_struct_const(cb_info->pNext, + PIPELINE_COLOR_WRITE_CREATE_INFO_EXT) : + NULL; + pipeline_init_dynamic_state(pipeline, pCreateInfo->pDynamicState, - vp_info, ds_info, cb_info, rs_info); + 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. diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 26585ec72de..48b2e0e54d5 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -797,7 +797,8 @@ enum v3dv_dynamic_state_bits { V3DV_DYNAMIC_BLEND_CONSTANTS = 1 << 5, V3DV_DYNAMIC_DEPTH_BIAS = 1 << 6, V3DV_DYNAMIC_LINE_WIDTH = 1 << 7, - V3DV_DYNAMIC_ALL = (1 << 8) - 1, + V3DV_DYNAMIC_COLOR_WRITE_ENABLE = 1 << 8, + V3DV_DYNAMIC_ALL = (1 << 9) - 1, }; /* Flags for dirty pipeline state. @@ -820,6 +821,7 @@ enum v3dv_cmd_dirty_bits { V3DV_CMD_DIRTY_DEPTH_BIAS = 1 << 14, V3DV_CMD_DIRTY_LINE_WIDTH = 1 << 15, V3DV_CMD_DIRTY_VIEW_INDEX = 1 << 16, + V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE = 1 << 17, }; struct v3dv_dynamic_state { @@ -857,6 +859,8 @@ struct v3dv_dynamic_state { } depth_bias; float line_width; + + uint32_t color_write_enable; }; extern const struct v3dv_dynamic_state default_dynamic_state; diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 285fa87e6ce..fee9aee8c52 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1161,8 +1161,7 @@ v3dX(cmd_buffer_emit_blend)(struct v3dv_cmd_buffer *cmd_buffer) const uint32_t blend_packets_size = cl_packet_length(BLEND_ENABLES) + cl_packet_length(BLEND_CONSTANT_COLOR) + - cl_packet_length(BLEND_CFG) * V3D_MAX_DRAW_BUFFERS + - cl_packet_length(COLOR_WRITE_MASKS); + cl_packet_length(BLEND_CFG) * V3D_MAX_DRAW_BUFFERS; v3dv_cl_ensure_space_with_branch(&job->bcl, blend_packets_size); v3dv_return_if_oom(cmd_buffer, NULL); @@ -1178,10 +1177,6 @@ v3dX(cmd_buffer_emit_blend)(struct v3dv_cmd_buffer *cmd_buffer) if (pipeline->blend.enables & (1 << i)) cl_emit_prepacked(&job->bcl, &pipeline->blend.cfg[i]); } - - cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) { - mask.mask = pipeline->blend.color_write_masks; - } } if (pipeline->blend.needs_color_constants && @@ -1197,6 +1192,22 @@ v3dX(cmd_buffer_emit_blend)(struct v3dv_cmd_buffer *cmd_buffer) } } +void +v3dX(cmd_buffer_emit_color_write_mask)(struct v3dv_cmd_buffer *cmd_buffer) +{ + struct v3dv_job *job = cmd_buffer->state.job; + 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; + cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) { + mask.mask = (~dynamic->color_write_enable | + pipeline->blend.color_write_masks) & 0xffff; + } + + cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_COLOR_WRITE_ENABLE; +} + static void emit_flat_shade_flags(struct v3dv_job *job, int varying_offset, diff --git a/src/broadcom/vulkan/v3dvx_private.h b/src/broadcom/vulkan/v3dvx_private.h index b74824a58d8..47ac2947c08 100644 --- a/src/broadcom/vulkan/v3dvx_private.h +++ b/src/broadcom/vulkan/v3dvx_private.h @@ -33,6 +33,9 @@ void v3dX(job_emit_binning_flush)(struct v3dv_job *job); +void +v3dX(cmd_buffer_emit_color_write_mask)(struct v3dv_cmd_buffer *cmd_buffer); + void v3dX(cmd_buffer_end_render_pass_secondary)(struct v3dv_cmd_buffer *cmd_buffer);