From bcc37775f1c3dc57f35eed3c739dc90a317d14aa Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Fri, 2 Sep 2022 08:49:12 +0200 Subject: [PATCH] v3dv: implement VK_EXT_depth_clip_control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alejandro PiƱeiro Part-of: --- docs/features.txt | 2 +- src/broadcom/vulkan/v3dv_cmd_buffer.c | 27 ++++++++++++++++++++++++++ src/broadcom/vulkan/v3dv_device.c | 8 ++++++++ src/broadcom/vulkan/v3dv_pipeline.c | 8 ++++++++ src/broadcom/vulkan/v3dv_private.h | 6 ++++++ src/broadcom/vulkan/v3dv_uniforms.c | 16 +++++++++++---- src/broadcom/vulkan/v3dvx_cmd_buffer.c | 20 ++++++++++++++----- 7 files changed, 77 insertions(+), 10 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index b48590053f1..c8a5b9b7560 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -545,7 +545,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_custom_border_color DONE (anv, lvp, panvk, radv, tu, v3dv, vn) VK_EXT_debug_marker DONE (radv) VK_EXT_depth_clip_enable DONE (anv, lvp, radv, tu, vn) - VK_EXT_depth_clip_control DONE (anv, lvp, radv, tu) + VK_EXT_depth_clip_control DONE (anv, lvp, radv, tu, v3dv) VK_EXT_depth_range_unrestricted DONE (radv, lvp) VK_EXT_discard_rectangles DONE (radv) VK_EXT_display_control DONE (anv, radv, tu) diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index bb29d0b5f62..78ce5944311 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -2112,6 +2112,33 @@ v3dv_viewport_compute_xform(const VkViewport *viewport, scale[2] = min_abs_scale * (scale[2] < 0 ? -1.0f : 1.0f); } +/* Considers the pipeline's negative_one_to_one state and applies it to the + * current viewport transform if needed to produce the resulting Z translate + * and scale parameters. + */ +void +v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state, + uint32_t vp_idx, + float *translate_z, float *scale_z) +{ + const struct v3dv_viewport_state *vp_state = &state->dynamic.viewport; + + 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; + s *= 0.5f; + } + + if (translate_z) + *translate_z = t; + + if (scale_z) + *scale_z = s; +} + VKAPI_ATTR void VKAPI_CALL v3dv_CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index ec0fc4ed6f9..741c8d47e4c 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -169,6 +169,7 @@ get_device_extensions(const struct v3dv_physical_device *device, .EXT_border_color_swizzle = true, .EXT_color_write_enable = true, .EXT_custom_border_color = true, + .EXT_depth_clip_control = true, .EXT_inline_uniform_block = true, .EXT_external_memory_dma_buf = true, .EXT_host_query_reset = true, @@ -1314,6 +1315,13 @@ v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT: { + VkPhysicalDeviceDepthClipControlFeaturesEXT *features = + (VkPhysicalDeviceDepthClipControlFeaturesEXT *)ext; + features->depthClipControl = true; + break; + } + default: v3dv_debug_ignored_stype(ext->sType); break; diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index 08bf637e011..717dfd8b6ca 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -2977,6 +2977,14 @@ pipeline_init(struct v3dv_pipeline *pipeline, PIPELINE_COLOR_WRITE_CREATE_INFO_EXT) : NULL; + if (vp_info) { + const VkPipelineViewportDepthClipControlCreateInfoEXT *depth_clip_control = + vk_find_struct_const(vp_info->pNext, + PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT); + 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); diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index a2196386fcc..7e536d8104c 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -1432,6 +1432,11 @@ struct v3dv_cmd_buffer_state { } query; }; +void +v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer_state *state, + uint32_t vp_idx, + float *translate_z, float *scale_z); + /* The following struct represents the info from a descriptor that we store on * the host memory. They are mostly links to other existing vulkan objects, * like the image_view in order to access to swizzle info, or the buffer used @@ -2077,6 +2082,7 @@ struct v3dv_pipeline { uint32_t sample_mask; bool primitive_restart; + bool negative_one_to_one; /* Accessed by binding. So vb[binding]->stride is the stride of the vertex * array with such binding diff --git a/src/broadcom/vulkan/v3dv_uniforms.c b/src/broadcom/vulkan/v3dv_uniforms.c index 425b84e0e1a..f3a98ab7ef0 100644 --- a/src/broadcom/vulkan/v3dv_uniforms.c +++ b/src/broadcom/vulkan/v3dv_uniforms.c @@ -527,13 +527,21 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer, cl_aligned_f(&uniforms, dynamic->viewport.scale[0][1] * 256.0f); break; - case QUNIFORM_VIEWPORT_Z_OFFSET: - cl_aligned_f(&uniforms, dynamic->viewport.translate[0][2]); + case QUNIFORM_VIEWPORT_Z_OFFSET: { + float translate_z; + v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0, + &translate_z, NULL); + cl_aligned_f(&uniforms, translate_z); break; + } - case QUNIFORM_VIEWPORT_Z_SCALE: - cl_aligned_f(&uniforms, dynamic->viewport.scale[0][2]); + case QUNIFORM_VIEWPORT_Z_SCALE: { + float scale_z; + v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0, + NULL, &scale_z); + cl_aligned_f(&uniforms, scale_z); break; + } case QUNIFORM_SSBO_OFFSET: case QUNIFORM_UBO_ADDR: diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 89f3b5a4ab4..3b283e2ad96 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1008,6 +1008,9 @@ void v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer) { struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic; + 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 */ @@ -1030,14 +1033,21 @@ v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer) clip.viewport_half_height_in_1_256th_of_pixel = vpscale[1] * 256.0f; } + float translate_z, scale_z; + v3dv_cmd_buffer_state_get_viewport_z_xform(&cmd_buffer->state, 0, + &translate_z, &scale_z); + cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) { - clip.viewport_z_offset_zc_to_zs = vptranslate[2]; - clip.viewport_z_scale_zc_to_zs = vpscale[2]; + clip.viewport_z_offset_zc_to_zs = translate_z; + clip.viewport_z_scale_zc_to_zs = scale_z; } cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) { - /* Vulkan's Z NDC is [0..1], unlile OpenGL which is [-1, 1] */ - float z1 = vptranslate[2]; - float z2 = vptranslate[2] + vpscale[2]; + /* Vulkan's default Z NDC is [0..1]. If 'negative_one_to_one' is enabled, + * we are using OpenGL's [-1, 1] instead. + */ + float z1 = pipeline->negative_one_to_one ? translate_z - scale_z : + translate_z; + float z2 = translate_z + scale_z; clip.minimum_zw = MIN2(z1, z2); clip.maximum_zw = MAX2(z1, z2); }