use crate::gles3::{
BufferId, DescriptorSetArrayData, FramebufferId, Gles3Attribute, Gles3PipelineInfo,
RafxCommandBufferGles3, RafxDeviceContextGles3, RafxQueueGles3, RafxRootSignatureGles3,
};
use crate::{
RafxCommandBufferDef, RafxCommandPoolDef, RafxExtents2D, RafxQueueType, RafxResult,
MAX_DESCRIPTOR_SET_LAYOUTS, MAX_RENDER_TARGET_ATTACHMENTS, MAX_VERTEX_INPUT_BINDINGS,
};
use rafx_base::trust_cell::TrustCell;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
static NEXT_COMMAND_POOL_STATE_ID: AtomicU32 = AtomicU32::new(0);
pub(crate) type AttributeEnabledBits = u32;
pub(crate) struct BoundDescriptorSet {
pub(crate) data: Arc<TrustCell<DescriptorSetArrayData>>,
pub(crate) array_index: u32,
}
#[derive(Debug, Copy, Clone)]
pub(crate) struct BoundVertexBuffer {
pub(crate) buffer_id: BufferId,
pub(crate) byte_offset: u32,
pub(crate) attribute_enabled_bits: AttributeEnabledBits,
}
pub(crate) struct CommandPoolGles3StateInner {
device_context: RafxDeviceContextGles3,
pub(crate) id: u32,
pub(crate) framebuffer_id: FramebufferId,
pub(crate) framebuffer_color_bound: [bool; MAX_RENDER_TARGET_ATTACHMENTS],
pub(crate) framebuffer_depth_bound: bool,
pub(crate) framebuffer_stencil_bound: bool,
pub(crate) is_started: bool,
pub(crate) surface_size: Option<RafxExtents2D>,
pub(crate) current_gl_pipeline_info: Option<Arc<Gles3PipelineInfo>>,
pub(crate) stencil_reference_value: u32,
pub(crate) bound_descriptor_sets: [Option<BoundDescriptorSet>; MAX_DESCRIPTOR_SET_LAYOUTS],
pub(crate) bound_descriptor_sets_root_signature: Option<RafxRootSignatureGles3>,
pub(crate) descriptor_sets_update_index: [u64; MAX_DESCRIPTOR_SET_LAYOUTS],
pub(crate) vertex_attribute_enabled_bits: AttributeEnabledBits,
pub(crate) vertex_attributes: Vec<Option<Gles3Attribute>>,
pub(crate) currently_bound_vertex_offset: [Option<i32>; MAX_VERTEX_INPUT_BINDINGS],
pub(crate) bound_vertex_buffers: [Option<BoundVertexBuffer>; MAX_VERTEX_INPUT_BINDINGS],
pub(crate) index_buffer_byte_offset: u32,
}
impl Drop for CommandPoolGles3StateInner {
fn drop(&mut self) {
self.device_context
.gl_context()
.gl_destroy_framebuffer(self.framebuffer_id)
.unwrap();
}
}
impl PartialEq for CommandPoolGles3StateInner {
fn eq(
&self,
other: &Self,
) -> bool {
self.id == other.id
}
}
impl std::fmt::Debug for CommandPoolGles3StateInner {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("CommandPoolGlStateInner")
.field("is_started", &self.is_started)
.field("surface_size", &self.surface_size)
.field("current_gl_pipeline_info", &self.current_gl_pipeline_info)
.field("stencil_reference_value", &self.stencil_reference_value)
.field("bound_vertex_buffers", &self.bound_vertex_buffers)
.field("index_buffer_byte_offset", &self.index_buffer_byte_offset)
.finish()
}
}
impl CommandPoolGles3StateInner {
pub(crate) fn clear_bindings(&mut self) {
for i in 0..MAX_DESCRIPTOR_SET_LAYOUTS {
self.bound_descriptor_sets[i] = None;
self.descriptor_sets_update_index[i] += 1;
self.bound_descriptor_sets_root_signature = None;
}
}
}
#[derive(Clone, Debug)]
pub(crate) struct CommandPoolGles3State {
inner: Arc<TrustCell<CommandPoolGles3StateInner>>,
}
impl CommandPoolGles3State {
fn new(device_context: &RafxDeviceContextGles3) -> RafxResult<Self> {
let framebuffer_id = device_context.gl_context().gl_create_framebuffer()?;
let attribute_count = device_context.device_info().max_vertex_attribute_count as usize;
let inner = CommandPoolGles3StateInner {
device_context: device_context.clone(),
id: NEXT_COMMAND_POOL_STATE_ID.fetch_add(1, Ordering::Relaxed),
is_started: false,
framebuffer_color_bound: Default::default(),
framebuffer_depth_bound: false,
framebuffer_stencil_bound: false,
surface_size: None,
current_gl_pipeline_info: None,
stencil_reference_value: 0,
vertex_attribute_enabled_bits: 0,
vertex_attributes: vec![None; attribute_count],
currently_bound_vertex_offset: [None; MAX_VERTEX_INPUT_BINDINGS],
bound_vertex_buffers: [None; MAX_VERTEX_INPUT_BINDINGS],
index_buffer_byte_offset: 0,
bound_descriptor_sets: Default::default(),
bound_descriptor_sets_root_signature: None,
descriptor_sets_update_index: Default::default(),
framebuffer_id,
};
Ok(CommandPoolGles3State {
inner: Arc::new(TrustCell::new(inner)),
})
}
pub(crate) fn borrow(&self) -> rafx_base::trust_cell::Ref<CommandPoolGles3StateInner> {
self.inner.borrow()
}
pub(crate) fn borrow_mut(&self) -> rafx_base::trust_cell::RefMut<CommandPoolGles3StateInner> {
self.inner.borrow_mut()
}
}
pub struct RafxCommandPoolGles3 {
command_pool_state: CommandPoolGles3State,
queue: RafxQueueGles3,
}
impl RafxCommandPoolGles3 {
pub fn device_context(&self) -> &RafxDeviceContextGles3 {
self.queue.device_context()
}
pub fn queue_type(&self) -> RafxQueueType {
self.queue.queue_type()
}
pub fn queue(&self) -> &RafxQueueGles3 {
&self.queue
}
pub(crate) fn command_pool_state(&self) -> &CommandPoolGles3State {
&self.command_pool_state
}
pub fn create_command_buffer(
&self,
command_buffer_def: &RafxCommandBufferDef,
) -> RafxResult<RafxCommandBufferGles3> {
RafxCommandBufferGles3::new(self, command_buffer_def)
}
pub fn reset_command_pool(&self) -> RafxResult<()> {
let state = self.command_pool_state.borrow_mut();
assert!(!state.is_started);
Ok(())
}
pub fn new(
queue: &RafxQueueGles3,
_command_pool_def: &RafxCommandPoolDef,
) -> RafxResult<RafxCommandPoolGles3> {
Ok(RafxCommandPoolGles3 {
command_pool_state: CommandPoolGles3State::new(queue.device_context())?,
queue: queue.clone(),
})
}
}