summaryrefslogtreecommitdiffstats
path: root/third_party/rust/gfx-backend-metal/src/soft.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/gfx-backend-metal/src/soft.rs
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/gfx-backend-metal/src/soft.rs')
-rw-r--r--third_party/rust/gfx-backend-metal/src/soft.rs524
1 files changed, 524 insertions, 0 deletions
diff --git a/third_party/rust/gfx-backend-metal/src/soft.rs b/third_party/rust/gfx-backend-metal/src/soft.rs
new file mode 100644
index 0000000000..278df1f272
--- /dev/null
+++ b/third_party/rust/gfx-backend-metal/src/soft.rs
@@ -0,0 +1,524 @@
+use crate::{
+ command::IndexBuffer, native::RasterizerState, BufferPtr, ResourceIndex, ResourcePtr,
+ SamplerPtr, TexturePtr,
+};
+
+use auxil::ShaderStage;
+use hal;
+use metal;
+
+use std::{fmt::Debug, ops::Range};
+
+pub type CacheResourceIndex = u32;
+
+pub trait Resources: Debug {
+ type Data: Debug;
+ type BufferArray: Debug;
+ type TextureArray: Debug;
+ type SamplerArray: Debug;
+ type DepthStencil: Debug;
+ type RenderPipeline: Debug;
+ type ComputePipeline: Debug;
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct Own {
+ pub buffers: Vec<Option<BufferPtr>>,
+ pub buffer_offsets: Vec<hal::buffer::Offset>,
+ pub textures: Vec<Option<TexturePtr>>,
+ pub samplers: Vec<Option<SamplerPtr>>,
+}
+
+impl Resources for Own {
+ type Data = Vec<u32>;
+ type BufferArray = Range<CacheResourceIndex>;
+ type TextureArray = Range<CacheResourceIndex>;
+ type SamplerArray = Range<CacheResourceIndex>;
+ type DepthStencil = metal::DepthStencilState;
+ type RenderPipeline = metal::RenderPipelineState;
+ type ComputePipeline = metal::ComputePipelineState;
+}
+
+#[derive(Debug)]
+pub struct Ref;
+impl<'a> Resources for &'a Ref {
+ type Data = &'a [u32];
+ type BufferArray = (&'a [Option<BufferPtr>], &'a [hal::buffer::Offset]);
+ type TextureArray = &'a [Option<TexturePtr>];
+ type SamplerArray = &'a [Option<SamplerPtr>];
+ type DepthStencil = &'a metal::DepthStencilStateRef;
+ type RenderPipeline = &'a metal::RenderPipelineStateRef;
+ type ComputePipeline = &'a metal::ComputePipelineStateRef;
+}
+
+//TODO: Remove `Clone` from here, blocked by arguments of `quick_render` and
+// `quick_compute` which currently use `cloned()` iteration.
+#[derive(Clone, Debug)]
+pub enum RenderCommand<R: Resources> {
+ SetViewport(hal::pso::Rect, Range<f32>),
+ SetScissor(metal::MTLScissorRect),
+ SetBlendColor(hal::pso::ColorValue),
+ SetDepthBias(hal::pso::DepthBias),
+ SetDepthStencilState(R::DepthStencil),
+ SetStencilReferenceValues(hal::pso::Sided<hal::pso::StencilValue>),
+ SetRasterizerState(RasterizerState),
+ SetVisibilityResult(metal::MTLVisibilityResultMode, hal::buffer::Offset),
+ BindBuffer {
+ stage: ShaderStage,
+ index: ResourceIndex,
+ buffer: BufferPtr,
+ offset: hal::buffer::Offset,
+ },
+ BindBuffers {
+ stage: ShaderStage,
+ index: ResourceIndex,
+ buffers: R::BufferArray,
+ },
+ BindBufferData {
+ stage: ShaderStage,
+ index: ResourceIndex,
+ words: R::Data,
+ },
+ BindTextures {
+ stage: ShaderStage,
+ index: ResourceIndex,
+ textures: R::TextureArray,
+ },
+ BindSamplers {
+ stage: ShaderStage,
+ index: ResourceIndex,
+ samplers: R::SamplerArray,
+ },
+ BindPipeline(R::RenderPipeline),
+ UseResource {
+ resource: ResourcePtr,
+ usage: metal::MTLResourceUsage,
+ },
+ Draw {
+ primitive_type: metal::MTLPrimitiveType,
+ vertices: Range<hal::VertexCount>,
+ instances: Range<hal::InstanceCount>,
+ },
+ DrawIndexed {
+ primitive_type: metal::MTLPrimitiveType,
+ index: IndexBuffer<BufferPtr>,
+ indices: Range<hal::IndexCount>,
+ base_vertex: hal::VertexOffset,
+ instances: Range<hal::InstanceCount>,
+ },
+ DrawIndirect {
+ primitive_type: metal::MTLPrimitiveType,
+ buffer: BufferPtr,
+ offset: hal::buffer::Offset,
+ },
+ DrawIndexedIndirect {
+ primitive_type: metal::MTLPrimitiveType,
+ index: IndexBuffer<BufferPtr>,
+ buffer: BufferPtr,
+ offset: hal::buffer::Offset,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum BlitCommand {
+ FillBuffer {
+ dst: BufferPtr,
+ range: Range<hal::buffer::Offset>,
+ value: u8,
+ },
+ CopyBuffer {
+ src: BufferPtr,
+ dst: BufferPtr,
+ region: hal::command::BufferCopy,
+ },
+ CopyImage {
+ src: TexturePtr,
+ dst: TexturePtr,
+ region: hal::command::ImageCopy,
+ },
+ CopyBufferToImage {
+ src: BufferPtr,
+ dst: TexturePtr,
+ dst_desc: hal::format::FormatDesc,
+ region: hal::command::BufferImageCopy,
+ },
+ CopyImageToBuffer {
+ src: TexturePtr,
+ src_desc: hal::format::FormatDesc,
+ dst: BufferPtr,
+ region: hal::command::BufferImageCopy,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum ComputeCommand<R: Resources> {
+ BindBuffer {
+ index: ResourceIndex,
+ buffer: BufferPtr,
+ offset: hal::buffer::Offset,
+ },
+ BindBuffers {
+ index: ResourceIndex,
+ buffers: R::BufferArray,
+ },
+ BindBufferData {
+ index: ResourceIndex,
+ words: R::Data,
+ },
+ BindTextures {
+ index: ResourceIndex,
+ textures: R::TextureArray,
+ },
+ BindSamplers {
+ index: ResourceIndex,
+ samplers: R::SamplerArray,
+ },
+ BindPipeline(R::ComputePipeline),
+ UseResource {
+ resource: ResourcePtr,
+ usage: metal::MTLResourceUsage,
+ },
+ Dispatch {
+ wg_size: metal::MTLSize,
+ wg_count: metal::MTLSize,
+ },
+ DispatchIndirect {
+ wg_size: metal::MTLSize,
+ buffer: BufferPtr,
+ offset: hal::buffer::Offset,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum Pass {
+ Render(metal::RenderPassDescriptor),
+ Blit,
+ Compute,
+}
+
+impl Own {
+ pub fn clear(&mut self) {
+ self.buffers.clear();
+ self.buffer_offsets.clear();
+ self.textures.clear();
+ self.samplers.clear();
+ }
+
+ pub fn own_render(&mut self, com: RenderCommand<&Ref>) -> RenderCommand<Self> {
+ use self::RenderCommand::*;
+ match com {
+ SetViewport(rect, depth) => SetViewport(rect, depth),
+ SetScissor(rect) => SetScissor(rect),
+ SetBlendColor(color) => SetBlendColor(color),
+ SetDepthBias(bias) => SetDepthBias(bias),
+ SetDepthStencilState(state) => SetDepthStencilState(state.to_owned()),
+ SetStencilReferenceValues(sided) => SetStencilReferenceValues(sided),
+ SetRasterizerState(ref state) => SetRasterizerState(state.clone()),
+ SetVisibilityResult(mode, offset) => SetVisibilityResult(mode, offset),
+ BindBuffer {
+ stage,
+ index,
+ buffer,
+ offset,
+ } => BindBuffer {
+ stage,
+ index,
+ buffer,
+ offset,
+ },
+ BindBuffers {
+ stage,
+ index,
+ buffers: (buffers, offsets),
+ } => BindBuffers {
+ stage,
+ index,
+ buffers: {
+ let start = self.buffers.len() as CacheResourceIndex;
+ self.buffers.extend_from_slice(buffers);
+ self.buffer_offsets.extend_from_slice(offsets);
+ start..self.buffers.len() as CacheResourceIndex
+ },
+ },
+ BindBufferData {
+ stage,
+ index,
+ words,
+ } => BindBufferData {
+ stage,
+ index,
+ words: words.to_vec(),
+ },
+ BindTextures {
+ stage,
+ index,
+ textures,
+ } => BindTextures {
+ stage,
+ index,
+ textures: {
+ let start = self.textures.len() as CacheResourceIndex;
+ self.textures.extend_from_slice(textures);
+ start..self.textures.len() as CacheResourceIndex
+ },
+ },
+ BindSamplers {
+ stage,
+ index,
+ samplers,
+ } => BindSamplers {
+ stage,
+ index,
+ samplers: {
+ let start = self.samplers.len() as CacheResourceIndex;
+ self.samplers.extend_from_slice(samplers);
+ start..self.samplers.len() as CacheResourceIndex
+ },
+ },
+ BindPipeline(pso) => BindPipeline(pso.to_owned()),
+ UseResource { resource, usage } => UseResource { resource, usage },
+ Draw {
+ primitive_type,
+ vertices,
+ instances,
+ } => Draw {
+ primitive_type,
+ vertices,
+ instances,
+ },
+ DrawIndexed {
+ primitive_type,
+ index,
+ indices,
+ base_vertex,
+ instances,
+ } => DrawIndexed {
+ primitive_type,
+ index,
+ indices,
+ base_vertex,
+ instances,
+ },
+ DrawIndirect {
+ primitive_type,
+ buffer,
+ offset,
+ } => DrawIndirect {
+ primitive_type,
+ buffer,
+ offset,
+ },
+ DrawIndexedIndirect {
+ primitive_type,
+ index,
+ buffer,
+ offset,
+ } => DrawIndexedIndirect {
+ primitive_type,
+ index,
+ buffer,
+ offset,
+ },
+ }
+ }
+
+ pub fn own_compute(&mut self, com: ComputeCommand<&Ref>) -> ComputeCommand<Self> {
+ use self::ComputeCommand::*;
+ match com {
+ BindBuffer {
+ index,
+ buffer,
+ offset,
+ } => BindBuffer {
+ index,
+ buffer,
+ offset,
+ },
+ BindBuffers {
+ index,
+ buffers: (buffers, offsets),
+ } => BindBuffers {
+ index,
+ buffers: {
+ let start = self.buffers.len() as CacheResourceIndex;
+ self.buffers.extend_from_slice(buffers);
+ self.buffer_offsets.extend_from_slice(offsets);
+ start..self.buffers.len() as CacheResourceIndex
+ },
+ },
+ BindBufferData { index, words } => BindBufferData {
+ index,
+ words: words.to_vec(),
+ },
+ BindTextures { index, textures } => BindTextures {
+ index,
+ textures: {
+ let start = self.textures.len() as CacheResourceIndex;
+ self.textures.extend_from_slice(textures);
+ start..self.textures.len() as CacheResourceIndex
+ },
+ },
+ BindSamplers { index, samplers } => BindSamplers {
+ index,
+ samplers: {
+ let start = self.samplers.len() as CacheResourceIndex;
+ self.samplers.extend_from_slice(samplers);
+ start..self.samplers.len() as CacheResourceIndex
+ },
+ },
+ BindPipeline(pso) => BindPipeline(pso.to_owned()),
+ UseResource { resource, usage } => UseResource { resource, usage },
+ Dispatch { wg_size, wg_count } => Dispatch { wg_size, wg_count },
+ DispatchIndirect {
+ wg_size,
+ buffer,
+ offset,
+ } => DispatchIndirect {
+ wg_size,
+ buffer,
+ offset,
+ },
+ }
+ }
+
+ pub fn rebase_render(&self, com: &mut RenderCommand<Own>) {
+ use self::RenderCommand::*;
+ match *com {
+ SetViewport(..)
+ | SetScissor(..)
+ | SetBlendColor(..)
+ | SetDepthBias(..)
+ | SetDepthStencilState(..)
+ | SetStencilReferenceValues(..)
+ | SetRasterizerState(..)
+ | SetVisibilityResult(..)
+ | BindBuffer { .. } => {}
+ BindBuffers {
+ ref mut buffers, ..
+ } => {
+ buffers.start += self.buffers.len() as CacheResourceIndex;
+ buffers.end += self.buffers.len() as CacheResourceIndex;
+ }
+ BindBufferData { .. } => {}
+ BindTextures {
+ ref mut textures, ..
+ } => {
+ textures.start += self.textures.len() as CacheResourceIndex;
+ textures.end += self.textures.len() as CacheResourceIndex;
+ }
+ BindSamplers {
+ ref mut samplers, ..
+ } => {
+ samplers.start += self.samplers.len() as CacheResourceIndex;
+ samplers.end += self.samplers.len() as CacheResourceIndex;
+ }
+ BindPipeline(..)
+ | UseResource { .. }
+ | Draw { .. }
+ | DrawIndexed { .. }
+ | DrawIndirect { .. }
+ | DrawIndexedIndirect { .. } => {}
+ }
+ }
+
+ pub fn rebase_compute(&self, com: &mut ComputeCommand<Own>) {
+ use self::ComputeCommand::*;
+ match *com {
+ BindBuffer { .. } => {}
+ BindBuffers {
+ ref mut buffers, ..
+ } => {
+ buffers.start += self.buffers.len() as CacheResourceIndex;
+ buffers.end += self.buffers.len() as CacheResourceIndex;
+ }
+ BindBufferData { .. } => {}
+ BindTextures {
+ ref mut textures, ..
+ } => {
+ textures.start += self.textures.len() as CacheResourceIndex;
+ textures.end += self.textures.len() as CacheResourceIndex;
+ }
+ BindSamplers {
+ ref mut samplers, ..
+ } => {
+ samplers.start += self.samplers.len() as CacheResourceIndex;
+ samplers.end += self.samplers.len() as CacheResourceIndex;
+ }
+ BindPipeline(..) | UseResource { .. } | Dispatch { .. } | DispatchIndirect { .. } => {}
+ }
+ }
+
+ pub fn extend(&mut self, other: &Self) {
+ self.buffers.extend_from_slice(&other.buffers);
+ self.buffer_offsets.extend_from_slice(&other.buffer_offsets);
+ self.textures.extend_from_slice(&other.textures);
+ self.samplers.extend_from_slice(&other.samplers);
+ }
+}
+
+/// This is a helper trait that allows us to unify owned and non-owned handling
+/// of the context-dependent data, such as resource arrays.
+pub trait AsSlice<T, R> {
+ fn as_slice<'a>(&'a self, resources: &'a R) -> &'a [T];
+}
+impl<'b, T> AsSlice<Option<T>, &'b Ref> for &'b [Option<T>] {
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, _: &'a &'b Ref) -> &'a [Option<T>] {
+ self
+ }
+}
+impl<'b> AsSlice<Option<BufferPtr>, &'b Ref>
+ for (&'b [Option<BufferPtr>], &'b [hal::buffer::Offset])
+{
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, _: &'a &'b Ref) -> &'a [Option<BufferPtr>] {
+ self.0
+ }
+}
+impl<'b> AsSlice<hal::buffer::Offset, &'b Ref>
+ for (&'b [Option<BufferPtr>], &'b [hal::buffer::Offset])
+{
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, _: &'a &'b Ref) -> &'a [hal::buffer::Offset] {
+ self.1
+ }
+}
+impl AsSlice<Option<BufferPtr>, Own> for Range<CacheResourceIndex> {
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, resources: &'a Own) -> &'a [Option<BufferPtr>] {
+ &resources.buffers[self.start as usize..self.end as usize]
+ }
+}
+impl AsSlice<hal::buffer::Offset, Own> for Range<CacheResourceIndex> {
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, resources: &'a Own) -> &'a [hal::buffer::Offset] {
+ &resources.buffer_offsets[self.start as usize..self.end as usize]
+ }
+}
+impl AsSlice<Option<TexturePtr>, Own> for Range<CacheResourceIndex> {
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, resources: &'a Own) -> &'a [Option<TexturePtr>] {
+ &resources.textures[self.start as usize..self.end as usize]
+ }
+}
+impl AsSlice<Option<SamplerPtr>, Own> for Range<CacheResourceIndex> {
+ #[inline(always)]
+ fn as_slice<'a>(&'a self, resources: &'a Own) -> &'a [Option<SamplerPtr>] {
+ &resources.samplers[self.start as usize..self.end as usize]
+ }
+}
+
+fn _test_command_sizes(
+ render: RenderCommand<&Ref>,
+ blit: BlitCommand,
+ compute: ComputeCommand<&Ref>,
+) {
+ use std::mem::transmute;
+ let _ = unsafe {
+ (
+ transmute::<_, [usize; 6]>(render),
+ transmute::<_, [usize; 9]>(blit),
+ transmute::<_, [usize; 7]>(compute),
+ )
+ };
+}