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 <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25946>
This commit is contained in:
Karol Herbst 2023-10-28 02:01:07 +02:00
parent 900ce1f4f4
commit 5ff33f9905
5 changed files with 67 additions and 9 deletions

View file

@ -1006,6 +1006,12 @@ impl Device {
id as u32 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 { pub fn shareable_shaders(&self) -> bool {
self.screen.param(pipe_cap::PIPE_CAP_SHAREABLE_SHADERS) == 1 self.screen.param(pipe_cap::PIPE_CAP_SHAREABLE_SHADERS) == 1
} }

View file

@ -1085,7 +1085,7 @@ impl Kernel {
ctx.set_sampler_views(&mut sviews); ctx.set_sampler_views(&mut sviews);
ctx.set_shader_images(&iviews); ctx.set_shader_images(&iviews);
ctx.set_global_binding(resources.as_slice(), &mut globals); 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); ctx.launch_grid(work_dim, block, grid, variable_local_size as u32);

View file

@ -6,6 +6,8 @@ use crate::core::platform::*;
use crate::impl_cl_type_trait; use crate::impl_cl_type_trait;
use mesa_rust::pipe::context::PipeContext; use mesa_rust::pipe::context::PipeContext;
use mesa_rust::pipe::resource::PipeResource;
use mesa_rust::pipe::screen::ResourceType;
use mesa_rust_util::properties::*; use mesa_rust_util::properties::*;
use rusticl_opencl_gen::*; 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 /// Used for tracking bound GPU state to lower CPU overhead and centralize state tracking
pub struct QueueContext { pub struct QueueContext {
ctx: PipeContext, ctx: PipeContext,
cb0: Option<PipeResource>,
} }
impl QueueContext { impl QueueContext {
fn new_for(device: &Device) -> CLResult<Self> { fn new_for(device: &Device) -> CLResult<Self> {
Ok(Self { let ctx = device
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() .screen()
.create_context() .resource_create_buffer(size, ResourceType::Cb0, 0)
.ok_or(CL_OUT_OF_HOST_MEMORY)?, } 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);
}
}
} }
} }

View file

@ -381,6 +381,24 @@ impl PipeContext {
unsafe { self.pipe.as_ref().delete_sampler_state.unwrap()(self.pipe.as_ptr(), ptr) } 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]) { pub fn set_constant_buffer(&self, idx: u32, data: &[u8]) {
let cb = pipe_constant_buffer { let cb = pipe_constant_buffer {
buffer: ptr::null_mut(), buffer: ptr::null_mut(),

View file

@ -73,16 +73,21 @@ impl ComputeParam<Vec<u64>> for PipeScreen {
pub enum ResourceType { pub enum ResourceType {
Normal, Normal,
Staging, Staging,
Cb0,
} }
impl ResourceType { impl ResourceType {
fn apply(&self, tmpl: &mut pipe_resource) { fn apply(&self, tmpl: &mut pipe_resource, screen: &PipeScreen) {
match self { match self {
Self::Staging => { Self::Staging => {
tmpl.set_usage(pipe_resource_usage::PIPE_USAGE_STAGING.0); tmpl.set_usage(pipe_resource_usage::PIPE_USAGE_STAGING.0);
tmpl.flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT | PIPE_RESOURCE_FLAG_MAP_COHERENT; tmpl.flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT | PIPE_RESOURCE_FLAG_MAP_COHERENT;
tmpl.bind |= PIPE_BIND_LINEAR; 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 => {} Self::Normal => {}
} }
} }
@ -146,7 +151,7 @@ impl PipeScreen {
tmpl.array_size = 1; tmpl.array_size = 1;
tmpl.bind = pipe_bind; tmpl.bind = pipe_bind;
res_type.apply(&mut tmpl); res_type.apply(&mut tmpl, self);
self.resource_create(&tmpl) self.resource_create(&tmpl)
} }
@ -194,7 +199,7 @@ impl PipeScreen {
tmpl.bind |= PIPE_BIND_SHADER_IMAGE; tmpl.bind |= PIPE_BIND_SHADER_IMAGE;
} }
res_type.apply(&mut tmpl); res_type.apply(&mut tmpl, self);
self.resource_create(&tmpl) self.resource_create(&tmpl)
} }