Module: Mesa Branch: main Commit: 5ff33f99058b5338fa83689da3d3c34d7079f4f7 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5ff33f99058b5338fa83689da3d3c34d7079f4f7
Author: Karol Herbst <kher...@redhat.com> Date: Sat Oct 28 02:01:07 2023 +0200 rusticl: use real buffer for cb0 for drivers prefering At the moment it's radeonsi and zink. Consequentially this also fixes data races in zink due to driver internal reasons. Signed-off-by: Karol Herbst <kher...@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25946> --- src/gallium/frontends/rusticl/core/device.rs | 6 ++++ src/gallium/frontends/rusticl/core/kernel.rs | 2 +- src/gallium/frontends/rusticl/core/queue.rs | 39 +++++++++++++++++++--- src/gallium/frontends/rusticl/mesa/pipe/context.rs | 18 ++++++++++ src/gallium/frontends/rusticl/mesa/pipe/screen.rs | 11 ++++-- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/gallium/frontends/rusticl/core/device.rs b/src/gallium/frontends/rusticl/core/device.rs index 5a0e7bdc915..b6c74006d6b 100644 --- a/src/gallium/frontends/rusticl/core/device.rs +++ b/src/gallium/frontends/rusticl/core/device.rs @@ -1006,6 +1006,12 @@ impl Device { id as u32 } + pub fn prefers_real_buffer_in_cb0(&self) -> bool { + self.screen + .param(pipe_cap::PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0) + == 1 + } + pub fn shareable_shaders(&self) -> bool { self.screen.param(pipe_cap::PIPE_CAP_SHAREABLE_SHADERS) == 1 } diff --git a/src/gallium/frontends/rusticl/core/kernel.rs b/src/gallium/frontends/rusticl/core/kernel.rs index 6ab38c5c9d4..a73638fdb54 100644 --- a/src/gallium/frontends/rusticl/core/kernel.rs +++ b/src/gallium/frontends/rusticl/core/kernel.rs @@ -1085,7 +1085,7 @@ impl Kernel { ctx.set_sampler_views(&mut sviews); ctx.set_shader_images(&iviews); ctx.set_global_binding(resources.as_slice(), &mut globals); - ctx.set_constant_buffer(0, &input); + ctx.update_cb0(&input); ctx.launch_grid(work_dim, block, grid, variable_local_size as u32); diff --git a/src/gallium/frontends/rusticl/core/queue.rs b/src/gallium/frontends/rusticl/core/queue.rs index 1275f48786e..85cb6f39552 100644 --- a/src/gallium/frontends/rusticl/core/queue.rs +++ b/src/gallium/frontends/rusticl/core/queue.rs @@ -6,6 +6,8 @@ use crate::core::platform::*; use crate::impl_cl_type_trait; use mesa_rust::pipe::context::PipeContext; +use mesa_rust::pipe::resource::PipeResource; +use mesa_rust::pipe::screen::ResourceType; use mesa_rust_util::properties::*; use rusticl_opencl_gen::*; @@ -23,16 +25,43 @@ use std::thread::JoinHandle; /// Used for tracking bound GPU state to lower CPU overhead and centralize state tracking pub struct QueueContext { ctx: PipeContext, + cb0: Option<PipeResource>, } impl QueueContext { fn new_for(device: &Device) -> CLResult<Self> { - Ok(Self { - ctx: device + let ctx = device + .screen() + .create_context() + .ok_or(CL_OUT_OF_HOST_MEMORY)?; + let size = device.param_max_size() as u32; + let cb0 = if device.prefers_real_buffer_in_cb0() { + device .screen() - .create_context() - .ok_or(CL_OUT_OF_HOST_MEMORY)?, - }) + .resource_create_buffer(size, ResourceType::Cb0, 0) + } else { + None + }; + + if let Some(cb0) = &cb0 { + ctx.bind_constant_buffer(0, cb0); + } + + Ok(Self { ctx: ctx, cb0: cb0 }) + } + + pub fn update_cb0(&self, data: &[u8]) { + // only update if we actually bind data + if !data.is_empty() { + // if we have a real buffer, update that, otherwise just set the data directly + if let Some(cb) = &self.cb0 { + debug_assert!(data.len() <= cb.width() as usize); + self.ctx + .buffer_subdata(cb, 0, data.as_ptr().cast(), data.len() as u32); + } else { + self.ctx.set_constant_buffer(0, data); + } + } } } diff --git a/src/gallium/frontends/rusticl/mesa/pipe/context.rs b/src/gallium/frontends/rusticl/mesa/pipe/context.rs index 26512cbf8b4..0d0faeda33a 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/context.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/context.rs @@ -381,6 +381,24 @@ impl PipeContext { unsafe { self.pipe.as_ref().delete_sampler_state.unwrap()(self.pipe.as_ptr(), ptr) } } + pub fn bind_constant_buffer(&self, idx: u32, res: &PipeResource) { + let cb = pipe_constant_buffer { + buffer: res.pipe(), + buffer_offset: 0, + buffer_size: res.width(), + user_buffer: ptr::null(), + }; + unsafe { + self.pipe.as_ref().set_constant_buffer.unwrap()( + self.pipe.as_ptr(), + pipe_shader_type::PIPE_SHADER_COMPUTE, + idx, + false, + &cb, + ) + } + } + pub fn set_constant_buffer(&self, idx: u32, data: &[u8]) { let cb = pipe_constant_buffer { buffer: ptr::null_mut(), diff --git a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs index ff11cae7343..4c3f4d23aae 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/screen.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/screen.rs @@ -73,16 +73,21 @@ impl ComputeParam<Vec<u64>> for PipeScreen { pub enum ResourceType { Normal, Staging, + Cb0, } impl ResourceType { - fn apply(&self, tmpl: &mut pipe_resource) { + fn apply(&self, tmpl: &mut pipe_resource, screen: &PipeScreen) { match self { Self::Staging => { tmpl.set_usage(pipe_resource_usage::PIPE_USAGE_STAGING.0); tmpl.flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT | PIPE_RESOURCE_FLAG_MAP_COHERENT; tmpl.bind |= PIPE_BIND_LINEAR; } + Self::Cb0 => { + tmpl.flags |= screen.param(pipe_cap::PIPE_CAP_CONSTBUF0_FLAGS) as u32; + tmpl.bind |= PIPE_BIND_CONSTANT_BUFFER; + } Self::Normal => {} } } @@ -146,7 +151,7 @@ impl PipeScreen { tmpl.array_size = 1; tmpl.bind = pipe_bind; - res_type.apply(&mut tmpl); + res_type.apply(&mut tmpl, self); self.resource_create(&tmpl) } @@ -194,7 +199,7 @@ impl PipeScreen { tmpl.bind |= PIPE_BIND_SHADER_IMAGE; } - res_type.apply(&mut tmpl); + res_type.apply(&mut tmpl, self); self.resource_create(&tmpl) }