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
}
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
}

View file

@ -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);

View file

@ -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);
}
}
}
}

View file

@ -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(),

View file

@ -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)
}