diff --git a/docs/features.txt b/docs/features.txt index e380cc4f1f6..4f2e78678c5 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -537,7 +537,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_custom_border_color DONE (anv, lvp, radv, tu, v3dv) VK_EXT_debug_marker DONE (radv) VK_EXT_depth_clip_enable DONE (anv, lvp, radv, tu) - VK_EXT_depth_clip_control DONE (lvp) + VK_EXT_depth_clip_control DONE (lvp, tu) VK_EXT_depth_range_unrestricted DONE (radv) VK_EXT_discard_rectangles DONE (radv) VK_EXT_display_control DONE (anv, tu) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 24e716207e0..f8764fd90ea 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -2330,6 +2330,12 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer, } } + if ((pipeline->dynamic_state_mask & BIT(VK_DYNAMIC_STATE_VIEWPORT)) && + (pipeline->z_negative_one_to_one != cmd->state.z_negative_one_to_one)) { + cmd->state.z_negative_one_to_one = pipeline->z_negative_one_to_one; + cmd->state.dirty |= TU_CMD_DIRTY_VIEWPORTS; + } + /* the vertex_buffers draw state always contains all the currently * bound vertex buffers. update its size to only emit the vbs which * are actually used by the pipeline @@ -2383,13 +2389,15 @@ tu_CmdSetViewport(VkCommandBuffer commandBuffer, const VkViewport *pViewports) { TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); - struct tu_cs cs; memcpy(&cmd->state.viewport[firstViewport], pViewports, viewportCount * sizeof(*pViewports)); cmd->state.max_viewport = MAX2(cmd->state.max_viewport, firstViewport + viewportCount); - cs = tu_cmd_dynamic_state(cmd, VK_DYNAMIC_STATE_VIEWPORT, 8 + 10 * cmd->state.max_viewport); - tu6_emit_viewport(&cs, cmd->state.viewport, cmd->state.max_viewport); + /* With VK_EXT_depth_clip_control we have to take into account + * negativeOneToOne property of the pipeline, so the viewport calculations + * are deferred until it is known. + */ + cmd->state.dirty |= TU_CMD_DIRTY_VIEWPORTS; } VKAPI_ATTR void VKAPI_CALL @@ -3933,6 +3941,12 @@ tu6_draw_common(struct tu_cmd_buffer *cmd, tu6_emit_consts(cmd, pipeline, descriptors_state, MESA_SHADER_FRAGMENT); } + if (cmd->state.dirty & TU_CMD_DIRTY_VIEWPORTS) { + struct tu_cs cs = tu_cmd_dynamic_state(cmd, VK_DYNAMIC_STATE_VIEWPORT, 8 + 10 * cmd->state.max_viewport); + tu6_emit_viewport(&cs, cmd->state.viewport, cmd->state.max_viewport, + pipeline->z_negative_one_to_one); + } + /* for the first draw in a renderpass, re-emit all the draw states * * and if a draw-state disabling path (CmdClearAttachments 3D fallback) was diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index fb0e920dd4d..d3794a71fe8 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -182,6 +182,7 @@ get_device_extensions(const struct tu_physical_device *device, .EXT_4444_formats = true, .EXT_conditional_rendering = true, .EXT_custom_border_color = true, + .EXT_depth_clip_control = true, .EXT_depth_clip_enable = true, .EXT_descriptor_indexing = true, .EXT_extended_dynamic_state = true, @@ -824,6 +825,12 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->rasterizationOrderStencilAttachmentAccess = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: { + VkPhysicalDeviceDepthClipControlFeaturesEXT *features = + (VkPhysicalDeviceDepthClipControlFeaturesEXT *)ext; + features->depthClipControl = true; + break; + } default: break; @@ -2709,9 +2716,9 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion) * * - Loader interface v4 differs from v3 in: * - The ICD must implement vk_icdGetPhysicalDeviceProcAddr(). - * + * * - Loader interface v5 differs from v4 in: - * - The ICD must support Vulkan API version 1.1 and must not return + * - The ICD must support Vulkan API version 1.1 and must not return * VK_ERROR_INCOMPATIBLE_DRIVER from vkCreateInstance() unless a * Vulkan Loader with interface v4 or smaller is being used and the * application provides an API version that is greater than 1.0. diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 407ce9d59d5..f0ad417e53a 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -1890,7 +1890,8 @@ tu6_emit_vertex_input(struct tu_pipeline *pipeline, } void -tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewports, uint32_t num_viewport) +tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewports, uint32_t num_viewport, + bool z_negative_one_to_one) { VkExtent2D guardband = {511, 511}; @@ -1901,10 +1902,20 @@ tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewports, uint32_t num_vi float scales[3]; scales[0] = viewport->width / 2.0f; scales[1] = viewport->height / 2.0f; - scales[2] = viewport->maxDepth - viewport->minDepth; + if (z_negative_one_to_one) { + scales[2] = 0.5 * (viewport->maxDepth - viewport->minDepth); + } else { + scales[2] = viewport->maxDepth - viewport->minDepth; + } + offsets[0] = viewport->x + scales[0]; offsets[1] = viewport->y + scales[1]; - offsets[2] = viewport->minDepth; + if (z_negative_one_to_one) { + offsets[2] = 0.5 * (viewport->minDepth + viewport->maxDepth); + } else { + offsets[2] = viewport->minDepth; + } + for (uint32_t j = 0; j < 3; j++) { tu_cs_emit(cs, fui(offsets[j])); tu_cs_emit(cs, fui(scales[j])); @@ -2846,11 +2857,14 @@ tu_pipeline_builder_parse_viewport(struct tu_pipeline_builder *builder, const VkPipelineViewportStateCreateInfo *vp_info = builder->create_info->pViewportState; + const VkPipelineViewportDepthClipControlCreateInfoEXT *depth_clip_info = + vk_find_struct_const(vp_info->pNext, PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT); + pipeline->z_negative_one_to_one = depth_clip_info ? depth_clip_info->negativeOneToOne : false; struct tu_cs cs; if (tu_pipeline_static_state(pipeline, &cs, VK_DYNAMIC_STATE_VIEWPORT, 8 + 10 * vp_info->viewportCount)) - tu6_emit_viewport(&cs, vp_info->pViewports, vp_info->viewportCount); + tu6_emit_viewport(&cs, vp_info->pViewports, vp_info->viewportCount, pipeline->z_negative_one_to_one); if (tu_pipeline_static_state(pipeline, &cs, VK_DYNAMIC_STATE_SCISSOR, 1 + 2 * vp_info->scissorCount)) tu6_emit_scissor(&cs, vp_info->pScissors, vp_info->scissorCount); @@ -2897,7 +2911,7 @@ tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder, .zfar_clip_disable = depth_clip_disable, /* TODO should this be depth_clip_disable instead? */ .unk5 = rast_info->depthClampEnable, - .zero_gb_scale_z = 1, + .zero_gb_scale_z = pipeline->z_negative_one_to_one ? 0 : 1, .vp_clip_code_ignore = 1)); tu_cs_emit_regs(&cs, diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 0ece23acb13..0d342343aa4 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -823,8 +823,9 @@ enum tu_cmd_dirty_bits TU_CMD_DIRTY_LRZ = BIT(8), TU_CMD_DIRTY_VS_PARAMS = BIT(9), TU_CMD_DIRTY_RASTERIZER_DISCARD = BIT(10), + TU_CMD_DIRTY_VIEWPORTS = BIT(11), /* all draw states were disabled and need to be re-enabled: */ - TU_CMD_DIRTY_DRAW_STATE = BIT(11) + TU_CMD_DIRTY_DRAW_STATE = BIT(12) }; /* There are only three cache domains we have to care about: the CCU, or @@ -1105,6 +1106,7 @@ struct tu_cmd_state bool predication_active; bool disable_gmem; enum a5xx_line_mode line_mode; + bool z_negative_one_to_one; uint32_t drawcall_count; @@ -1377,6 +1379,8 @@ struct tu_pipeline bool raster_order_attachment_access; bool subpass_feedback_loop_ds; + bool z_negative_one_to_one; + /* Base drawcall cost for sysmem vs gmem autotuner */ uint8_t drawcall_base_cost; @@ -1386,7 +1390,8 @@ struct tu_pipeline }; void -tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewport, uint32_t num_viewport); +tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewport, uint32_t num_viewport, + bool z_negative_one_to_one); void tu6_emit_scissor(struct tu_cs *cs, const VkRect2D *scs, uint32_t scissor_count);