From 2b02117e64390669630e2a3d38fd5fd75f95e92a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alejandro=20Pi=C3=B1eiro?= Date: Fri, 3 Jan 2020 12:43:35 +0100 Subject: [PATCH] v3dv: add v3dv_write_uniforms Initial port of the equivalent v3d_write_uniforms, to be used by the cmd_buffer when emitting the drawing packets. Initially doesn't include all the quniform types, only those needed by the initial basic vulkan tests. Part-of: --- src/broadcom/vulkan/meson.build | 1 + src/broadcom/vulkan/v3dv_cl.h | 13 ++++++ src/broadcom/vulkan/v3dv_cmd_buffer.c | 10 +++-- src/broadcom/vulkan/v3dv_private.h | 3 ++ src/broadcom/vulkan/v3dv_uniforms.c | 85 +++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 src/broadcom/vulkan/v3dv_uniforms.c diff --git a/src/broadcom/vulkan/meson.build b/src/broadcom/vulkan/meson.build index 3aab825..39de45c 100644 --- a/src/broadcom/vulkan/meson.build +++ b/src/broadcom/vulkan/meson.build @@ -66,6 +66,7 @@ libv3dv_files = files( 'v3dv_pipeline.c', 'v3dv_private.h', 'v3dv_queue.c', + 'v3dv_uniforms.c', 'v3dv_util.c', 'v3d_tiling.c', ) diff --git a/src/broadcom/vulkan/v3dv_cl.h b/src/broadcom/vulkan/v3dv_cl.h index d2fcc09..f58b2d5 100644 --- a/src/broadcom/vulkan/v3dv_cl.h +++ b/src/broadcom/vulkan/v3dv_cl.h @@ -106,6 +106,19 @@ cl_advance(struct v3dv_cl_out **cl, uint32_t n) (*cl) = (struct v3dv_cl_out *)((char *)(*cl) + n); } +static inline void +cl_aligned_u32(struct v3dv_cl_out **cl, uint32_t n) +{ + *(uint32_t *)(*cl) = n; + cl_advance(cl, 4); +} + +static inline void +cl_aligned_f(struct v3dv_cl_out **cl, float f) +{ + cl_aligned_u32(cl, fui(f)); +} + uint32_t v3dv_cl_ensure_space(struct v3dv_cl *cl, uint32_t space, uint32_t alignment); void v3dv_cl_ensure_space_with_branch(struct v3dv_cl *cl, uint32_t space); diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index 8930d28..ca302db 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -1239,12 +1239,14 @@ cmd_buffer_emit_graphics_pipeline(struct v3dv_cmd_buffer *cmd_buffer) assert(pipeline); /* Upload the uniforms to the indirect CL first */ + struct v3dv_cl_reloc fs_uniforms = + v3dv_write_uniforms(cmd_buffer, pipeline->fs); - /* FIXME: uniforms not supported yet */ + struct v3dv_cl_reloc vs_uniforms = + v3dv_write_uniforms(cmd_buffer, pipeline->vs); - struct v3dv_cl_reloc vs_uniforms = { NULL, 0 }; - struct v3dv_cl_reloc vs_bin_uniforms = { NULL, 0 }; - struct v3dv_cl_reloc fs_uniforms = { NULL, 0 }; + struct v3dv_cl_reloc vs_bin_uniforms = + v3dv_write_uniforms(cmd_buffer, pipeline->vs_bin); /* Update the cache dirty flag based on the shader progs data */ state->tmu_dirty_rcl |= pipeline->vs_bin->prog_data.vs->base.tmu_dirty_rcl; diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index d9a199a..d9aeac3 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -629,6 +629,9 @@ void v3d_store_tiled_image(void *dst, uint32_t dst_stride, int cpp, uint32_t image_h, const struct pipe_box *box); +struct v3dv_cl_reloc v3dv_write_uniforms(struct v3dv_cmd_buffer *cmd_buffer, + struct v3dv_pipeline_stage *p_stage); + #define V3DV_DEFINE_HANDLE_CASTS(__v3dv_type, __VkType) \ \ static inline struct __v3dv_type * \ diff --git a/src/broadcom/vulkan/v3dv_uniforms.c b/src/broadcom/vulkan/v3dv_uniforms.c new file mode 100644 index 0000000..109dbe4 --- /dev/null +++ b/src/broadcom/vulkan/v3dv_uniforms.c @@ -0,0 +1,85 @@ +/* + * Copyright © 2019 Raspberry Pi + * + * Based in part on v3d driver which is: + * + * Copyright © 2014-2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "v3dv_private.h" + +struct v3dv_cl_reloc +v3dv_write_uniforms(struct v3dv_cmd_buffer *cmd_buffer, + struct v3dv_pipeline_stage *p_stage) +{ + struct v3d_uniform_list *uinfo = &p_stage->prog_data.base->uniforms; + struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic; + + /* The hardware always pre-fetches the next uniform (also when there + * aren't any), so we always allocate space for an extra slot. This + * fixes MMU exceptions reported since Linux kernel 5.4 when the + * uniforms fill up the tail bytes of a page in the indirect + * BO. In that scenario, when the hardware pre-fetches after reading + * the last uniform it will read beyond the end of the page and trigger + * the MMU exception. + */ + v3dv_cl_ensure_space(&cmd_buffer->indirect, (uinfo->count + 1) * 4, 4); + + struct v3dv_cl_reloc uniform_stream = + v3dv_cl_get_address(&cmd_buffer->indirect); + + struct v3dv_cl_out *uniforms = + cl_start(&cmd_buffer->indirect); + + for (int i = 0; i < uinfo->count; i++) { + uint32_t data = uinfo->data[i]; + + switch (uinfo->contents[i]) { + case QUNIFORM_CONSTANT: + cl_aligned_u32(&uniforms, data); + break; + + case QUNIFORM_VIEWPORT_X_SCALE: + cl_aligned_f(&uniforms, dynamic->viewport.scale[0][0] * 256.0f); + break; + + case QUNIFORM_VIEWPORT_Y_SCALE: + 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]); + break; + + case QUNIFORM_VIEWPORT_Z_SCALE: + cl_aligned_f(&uniforms, dynamic->viewport.scale[0][2]); + break; + + default: + unreachable("unsupported quniform_contents uniform type\n"); + } + } + + cl_end(&cmd_buffer->indirect, uniforms); + + return uniform_stream; +} -- 2.7.4