mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
hal/gles: fences and queries
This commit is contained in:
parent
d3d2ed5a9e
commit
91f9806831
@ -279,7 +279,7 @@ impl super::Adapter {
|
||||
impl crate::Adapter<super::Api> for super::Adapter {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
features: wgt::Features,
|
||||
_features: wgt::Features,
|
||||
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
||||
let gl = &self.shared.context;
|
||||
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
||||
@ -294,8 +294,8 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
},
|
||||
queue: super::Queue {
|
||||
shared: Arc::clone(&self.shared),
|
||||
features,
|
||||
copy_fbo: gl.create_framebuffer().unwrap(),
|
||||
temp_query_results: Vec::new(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use super::Resource; //TEMP
|
||||
use super::{conv, Command as C};
|
||||
use std::{mem, ops::Range};
|
||||
|
||||
@ -6,13 +5,14 @@ impl super::CommandBuffer {
|
||||
fn clear(&mut self) {
|
||||
self.label = None;
|
||||
self.commands.clear();
|
||||
self.data.clear();
|
||||
self.data_bytes.clear();
|
||||
self.data_words.clear();
|
||||
}
|
||||
|
||||
fn add_marker(&mut self, marker: &str) -> Range<u32> {
|
||||
let start = self.data.len() as u32;
|
||||
self.data.extend(marker.as_bytes());
|
||||
start..self.data.len() as u32
|
||||
let start = self.data_bytes.len() as u32;
|
||||
self.data_bytes.extend(marker.as_bytes());
|
||||
start..self.data_bytes.len() as u32
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,17 +153,39 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn begin_query(&mut self, set: &Resource, index: u32) {}
|
||||
unsafe fn end_query(&mut self, set: &Resource, index: u32) {}
|
||||
unsafe fn write_timestamp(&mut self, set: &Resource, index: u32) {}
|
||||
unsafe fn reset_queries(&mut self, set: &Resource, range: Range<u32>) {}
|
||||
unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {
|
||||
let query = set.queries[index as usize];
|
||||
self.cmd_buffer
|
||||
.commands
|
||||
.push(C::BeginQuery(query, set.target));
|
||||
}
|
||||
unsafe fn end_query(&mut self, set: &super::QuerySet, _index: u32) {
|
||||
self.cmd_buffer.commands.push(C::EndQuery(set.target));
|
||||
}
|
||||
unsafe fn write_timestamp(&mut self, _set: &super::QuerySet, _index: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
unsafe fn reset_queries(&mut self, _set: &super::QuerySet, _range: Range<u32>) {
|
||||
//TODO: what do we do here?
|
||||
}
|
||||
unsafe fn copy_query_results(
|
||||
&mut self,
|
||||
set: &Resource,
|
||||
set: &super::QuerySet,
|
||||
range: Range<u32>,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
) {
|
||||
let start = self.cmd_buffer.data_words.len();
|
||||
self.cmd_buffer
|
||||
.data_words
|
||||
.extend_from_slice(&set.queries[range.start as usize..range.end as usize]);
|
||||
let query_range = start as u32..self.cmd_buffer.data_words.len() as u32;
|
||||
self.cmd_buffer.commands.push(C::CopyQueryResults {
|
||||
query_range,
|
||||
dst: buffer.raw,
|
||||
dst_target: buffer.target,
|
||||
dst_offset: offset,
|
||||
});
|
||||
}
|
||||
|
||||
// render
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use super::conv;
|
||||
use super::Resource; //TEMP
|
||||
use crate::util::map_naga_stage;
|
||||
use glow::HasContext;
|
||||
use std::{convert::TryInto, iter, ptr::NonNull, sync::Arc};
|
||||
@ -713,28 +712,72 @@ impl crate::Device<super::Api> for super::Device {
|
||||
unsafe fn create_query_set(
|
||||
&self,
|
||||
desc: &wgt::QuerySetDescriptor<crate::Label>,
|
||||
) -> Result<Resource, crate::DeviceError> {
|
||||
Ok(Resource)
|
||||
) -> Result<super::QuerySet, crate::DeviceError> {
|
||||
let gl = &self.shared.context;
|
||||
|
||||
let mut queries = Vec::with_capacity(desc.count as usize);
|
||||
for _ in 0..desc.count {
|
||||
let query = gl
|
||||
.create_query()
|
||||
.map_err(|_| crate::DeviceError::OutOfMemory)?;
|
||||
queries.push(query);
|
||||
}
|
||||
|
||||
Ok(super::QuerySet {
|
||||
queries: queries.into_boxed_slice(),
|
||||
target: match desc.ty {
|
||||
wgt::QueryType::Occlusion => glow::ANY_SAMPLES_PASSED,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
})
|
||||
}
|
||||
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
||||
let gl = &self.shared.context;
|
||||
for &query in set.queries.iter() {
|
||||
gl.delete_query(query);
|
||||
}
|
||||
}
|
||||
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
||||
Ok(super::Fence {
|
||||
last_completed: 0,
|
||||
pending: Vec::new(),
|
||||
})
|
||||
}
|
||||
unsafe fn destroy_fence(&self, fence: super::Fence) {
|
||||
let gl = &self.shared.context;
|
||||
for (_, sync) in fence.pending {
|
||||
gl.delete_sync(sync);
|
||||
}
|
||||
unsafe fn destroy_query_set(&self, set: Resource) {}
|
||||
unsafe fn create_fence(&self) -> Result<Resource, crate::DeviceError> {
|
||||
Ok(Resource)
|
||||
}
|
||||
unsafe fn destroy_fence(&self, fence: Resource) {}
|
||||
unsafe fn get_fence_value(
|
||||
&self,
|
||||
fence: &Resource,
|
||||
fence: &super::Fence,
|
||||
) -> Result<crate::FenceValue, crate::DeviceError> {
|
||||
Ok(0)
|
||||
Ok(fence.get_latest(&self.shared.context))
|
||||
}
|
||||
unsafe fn wait(
|
||||
&self,
|
||||
fence: &Resource,
|
||||
value: crate::FenceValue,
|
||||
fence: &super::Fence,
|
||||
wait_value: crate::FenceValue,
|
||||
timeout_ms: u32,
|
||||
) -> Result<bool, crate::DeviceError> {
|
||||
if fence.last_completed < wait_value {
|
||||
let gl = &self.shared.context;
|
||||
let timeout_ns = (timeout_ms as u64 * 1_000_000).min(!0u32 as u64);
|
||||
let &(_, sync) = fence
|
||||
.pending
|
||||
.iter()
|
||||
.find(|&&(value, _)| value >= wait_value)
|
||||
.unwrap();
|
||||
match gl.client_wait_sync(sync, glow::SYNC_FLUSH_COMMANDS_BIT, timeout_ns as i32) {
|
||||
glow::TIMEOUT_EXPIRED => Ok(false),
|
||||
glow::CONDITION_SATISFIED | glow::ALREADY_SIGNALED => Ok(true),
|
||||
_ => Err(crate::DeviceError::Lost),
|
||||
}
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn start_capture(&self) -> bool {
|
||||
false
|
||||
|
||||
@ -18,12 +18,9 @@ use std::{ops::Range, sync::Arc};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Api;
|
||||
#[derive(Debug)]
|
||||
pub struct Resource;
|
||||
|
||||
//Note: we can support more samplers if not every one of them is used at a time,
|
||||
// but it probably doesn't worth it.
|
||||
const MAX_SAMPLER_SLOTS: usize = 16;
|
||||
const MAX_TEXTURE_SLOTS: usize = 16;
|
||||
|
||||
impl crate::Api for Api {
|
||||
@ -41,8 +38,8 @@ impl crate::Api for Api {
|
||||
type SurfaceTexture = Texture;
|
||||
type TextureView = TextureView;
|
||||
type Sampler = Sampler;
|
||||
type QuerySet = Resource;
|
||||
type Fence = Resource;
|
||||
type QuerySet = QuerySet;
|
||||
type Fence = Fence;
|
||||
|
||||
type BindGroupLayout = BindGroupLayout;
|
||||
type BindGroup = BindGroup;
|
||||
@ -184,8 +181,8 @@ pub struct Device {
|
||||
|
||||
pub struct Queue {
|
||||
shared: Arc<AdapterShared>,
|
||||
features: wgt::Features,
|
||||
copy_fbo: glow::Framebuffer,
|
||||
temp_query_results: Vec<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -344,6 +341,47 @@ pub struct ComputePipeline {
|
||||
inner: PipelineInner,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QuerySet {
|
||||
queries: Box<[glow::Query]>,
|
||||
target: BindTarget,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Fence {
|
||||
last_completed: crate::FenceValue,
|
||||
pending: Vec<(crate::FenceValue, glow::Fence)>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Fence {}
|
||||
unsafe impl Sync for Fence {}
|
||||
|
||||
impl Fence {
|
||||
fn get_latest(&self, gl: &glow::Context) -> crate::FenceValue {
|
||||
let mut max_value = self.last_completed;
|
||||
for &(value, sync) in self.pending.iter() {
|
||||
let status = unsafe { gl.get_sync_status(sync) };
|
||||
if status == glow::SIGNALED {
|
||||
max_value = value;
|
||||
}
|
||||
}
|
||||
max_value
|
||||
}
|
||||
|
||||
fn maintain(&mut self, gl: &glow::Context) {
|
||||
let latest = self.get_latest(gl);
|
||||
for &(value, sync) in self.pending.iter() {
|
||||
if value <= latest {
|
||||
unsafe {
|
||||
gl.delete_sync(sync);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.pending.retain(|&(value, _)| value > latest);
|
||||
self.last_completed = latest;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TextureCopyInfo {
|
||||
external_format: u32,
|
||||
@ -419,6 +457,14 @@ enum Command {
|
||||
copy: crate::BufferTextureCopy,
|
||||
},
|
||||
SetIndexBuffer(glow::Buffer),
|
||||
BeginQuery(glow::Query, BindTarget),
|
||||
EndQuery(BindTarget),
|
||||
CopyQueryResults {
|
||||
query_range: Range<u32>,
|
||||
dst: glow::Buffer,
|
||||
dst_target: BindTarget,
|
||||
dst_offset: wgt::BufferAddress,
|
||||
},
|
||||
InsertDebugMarker(Range<u32>),
|
||||
PushDebugGroup(Range<u32>),
|
||||
PopDebugGroup,
|
||||
@ -428,7 +474,8 @@ enum Command {
|
||||
pub struct CommandBuffer {
|
||||
label: Option<String>,
|
||||
commands: Vec<Command>,
|
||||
data: Vec<u8>,
|
||||
data_bytes: Vec<u8>,
|
||||
data_words: Vec<u32>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use super::Command as C;
|
||||
use glow::HasContext;
|
||||
use std::ops::Range;
|
||||
use std::{mem, ops::Range, slice};
|
||||
|
||||
const DEBUG_ID: u32 = 0;
|
||||
|
||||
@ -16,7 +16,7 @@ fn is_3d_target(target: super::BindTarget) -> bool {
|
||||
}
|
||||
|
||||
impl super::Queue {
|
||||
unsafe fn process(&mut self, command: &C, data: &[u8]) {
|
||||
unsafe fn process(&mut self, command: &C, data_bytes: &[u8], data_words: &[u32]) {
|
||||
let gl = &self.shared.context;
|
||||
match *command {
|
||||
C::Draw {
|
||||
@ -265,8 +265,34 @@ impl super::Queue {
|
||||
C::SetIndexBuffer(buffer) => {
|
||||
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(buffer));
|
||||
}
|
||||
C::BeginQuery(query, target) => {
|
||||
gl.begin_query(target, query);
|
||||
}
|
||||
C::EndQuery(target) => {
|
||||
gl.end_query(target);
|
||||
}
|
||||
C::CopyQueryResults {
|
||||
ref query_range,
|
||||
dst,
|
||||
dst_target,
|
||||
dst_offset,
|
||||
} => {
|
||||
self.temp_query_results.clear();
|
||||
for &query in
|
||||
data_words[query_range.start as usize..query_range.end as usize].iter()
|
||||
{
|
||||
let result = gl.get_query_parameter_u32(query, glow::QUERY_RESULT);
|
||||
self.temp_query_results.push(result as u64);
|
||||
}
|
||||
let query_data = slice::from_raw_parts(
|
||||
self.temp_query_results.as_ptr() as *const u8,
|
||||
self.temp_query_results.len() * mem::size_of::<u64>(),
|
||||
);
|
||||
gl.bind_buffer(dst_target, Some(dst));
|
||||
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data);
|
||||
}
|
||||
C::InsertDebugMarker(ref range) => {
|
||||
let marker = extract_marker(data, range);
|
||||
let marker = extract_marker(data_bytes, range);
|
||||
gl.debug_message_insert(
|
||||
glow::DEBUG_SOURCE_APPLICATION,
|
||||
glow::DEBUG_TYPE_MARKER,
|
||||
@ -276,7 +302,7 @@ impl super::Queue {
|
||||
);
|
||||
}
|
||||
C::PushDebugGroup(ref range) => {
|
||||
let marker = extract_marker(data, range);
|
||||
let marker = extract_marker(data_bytes, range);
|
||||
gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, marker);
|
||||
}
|
||||
C::PopDebugGroup => {
|
||||
@ -290,13 +316,23 @@ impl crate::Queue<super::Api> for super::Queue {
|
||||
unsafe fn submit(
|
||||
&mut self,
|
||||
command_buffers: &[&super::CommandBuffer],
|
||||
signal_fence: Option<(&mut super::Resource, crate::FenceValue)>,
|
||||
signal_fence: Option<(&mut super::Fence, crate::FenceValue)>,
|
||||
) -> Result<(), crate::DeviceError> {
|
||||
for cmd_buf in command_buffers.iter() {
|
||||
for command in cmd_buf.commands.iter() {
|
||||
self.process(command, &cmd_buf.data);
|
||||
self.process(command, &cmd_buf.data_bytes, &cmd_buf.data_words);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((fence, value)) = signal_fence {
|
||||
let gl = &self.shared.context;
|
||||
fence.maintain(gl);
|
||||
let sync = gl
|
||||
.fence_sync(glow::SYNC_GPU_COMMANDS_COMPLETE, 0)
|
||||
.map_err(|_| crate::DeviceError::OutOfMemory)?;
|
||||
fence.pending.push((value, sync));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user