rt(mtl): set up pipeline objects and renderpass
This commit is contained in:
parent
f40df9a54a
commit
8dc0e0d100
6 changed files with 317 additions and 18 deletions
66
Cargo.lock
generated
66
Cargo.lock
generated
|
@ -327,7 +327,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68"
|
checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-sys",
|
"block-sys",
|
||||||
"objc2",
|
"objc2 0.4.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block2"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f"
|
||||||
|
dependencies = [
|
||||||
|
"block-sys",
|
||||||
|
"objc2 0.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1306,9 +1316,19 @@ version = "0.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319"
|
checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2 0.3.0",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"objc2",
|
"objc2 0.4.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icrate"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e286f4b975ac6c054971a0600a9b76438b332edace54bff79c71c9d3adfc9772"
|
||||||
|
dependencies = [
|
||||||
|
"block2 0.4.0",
|
||||||
|
"objc2 0.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1555,6 +1575,7 @@ version = "0.2.0-beta.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ash",
|
"ash",
|
||||||
"gl",
|
"gl",
|
||||||
|
"icrate 0.1.0",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
"windows 0.48.0",
|
"windows 0.48.0",
|
||||||
|
@ -1703,6 +1724,23 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "librashader-runtime-metal"
|
||||||
|
version = "0.2.0-beta.7"
|
||||||
|
dependencies = [
|
||||||
|
"array-concat",
|
||||||
|
"bytemuck",
|
||||||
|
"icrate 0.1.0",
|
||||||
|
"librashader-common 0.2.0-beta.9",
|
||||||
|
"librashader-preprocess",
|
||||||
|
"librashader-presets 0.2.0-beta.9",
|
||||||
|
"librashader-reflect",
|
||||||
|
"librashader-runtime",
|
||||||
|
"objc2 0.5.0",
|
||||||
|
"rustc-hash",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "librashader-runtime-vk"
|
name = "librashader-runtime-vk"
|
||||||
version = "0.2.0-beta.9"
|
version = "0.2.0-beta.9"
|
||||||
|
@ -2067,7 +2105,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d"
|
checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc-sys",
|
"objc-sys",
|
||||||
"objc2-encode",
|
"objc2-encode 3.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a9c7f0d511a4ce26b078183179dca908171cfc69f88986fe36c5138e1834476"
|
||||||
|
dependencies = [
|
||||||
|
"objc-sys",
|
||||||
|
"objc2-encode 4.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2076,6 +2124,12 @@ version = "3.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666"
|
checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-encode"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ff06a6505cde0766484f38d8479ac8e6d31c66fbc2d5492f65ca8c091456379"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc_exception"
|
name = "objc_exception"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -3636,14 +3690,14 @@ dependencies = [
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"cursor-icon",
|
"cursor-icon",
|
||||||
"icrate",
|
"icrate 0.0.4",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
"objc2",
|
"objc2 0.4.1",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"orbclient",
|
"orbclient",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
|
|
@ -1,13 +1,43 @@
|
||||||
use std::ffi::c_void;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
use array_concat::concat_arrays;
|
use array_concat::concat_arrays;
|
||||||
use icrate::Metal::{MTLBuffer, MTLDevice, MTLPrimitiveTypeTriangleStrip, MTLRenderCommandEncoder, MTLResourceStorageModeManaged, MTLResourceStorageModeShared};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use icrate::Metal::{
|
||||||
|
MTLBuffer, MTLDevice, MTLPrimitiveTypeTriangleStrip, MTLRenderCommandEncoder,
|
||||||
|
MTLResourceStorageModeManaged, MTLResourceStorageModeShared,
|
||||||
|
};
|
||||||
|
use librashader_runtime::quad::QuadType;
|
||||||
use objc2::rc::Id;
|
use objc2::rc::Id;
|
||||||
use objc2::runtime::ProtocolObject;
|
use objc2::runtime::ProtocolObject;
|
||||||
use librashader_runtime::quad::QuadType;
|
use std::ffi::c_void;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use crate::error::{FilterChainError, Result};
|
use crate::error::{FilterChainError, Result};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone, Default, Zeroable, Pod)]
|
||||||
|
struct MetalVertex {
|
||||||
|
position: [f32; 4],
|
||||||
|
texcoord: [f32; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
const FINAL_VBO_DATA: [MetalVertex; 4] = [
|
||||||
|
MetalVertex {
|
||||||
|
position: [0.0, 1.0, 0.0, 1.0],
|
||||||
|
texcoord: [0.0, 1.0],
|
||||||
|
},
|
||||||
|
MetalVertex {
|
||||||
|
position: [1.0, 1.0, 0.0, 1.0],
|
||||||
|
texcoord: [1.0, 1.0],
|
||||||
|
},
|
||||||
|
MetalVertex {
|
||||||
|
position: [0.0, 0.0, 0.0, 1.0],
|
||||||
|
texcoord: [0.0, 0.0],
|
||||||
|
},
|
||||||
|
MetalVertex {
|
||||||
|
position: [1.0, 0.0, 0.0, 1.0],
|
||||||
|
texcoord: [1.0, 0.0],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const VBO_OFFSCREEN: [f32; 16] = [
|
const VBO_OFFSCREEN: [f32; 16] = [
|
||||||
// Offscreen
|
// Offscreen
|
||||||
|
@ -45,16 +75,17 @@ impl DrawQuad {
|
||||||
MTLResourceStorageModeShared
|
MTLResourceStorageModeShared
|
||||||
} else {
|
} else {
|
||||||
MTLResourceStorageModeManaged
|
MTLResourceStorageModeManaged
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}) else {
|
}) else {
|
||||||
return Err(FilterChainError::BufferError)
|
return Err(FilterChainError::BufferError);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(DrawQuad { buffer })
|
Ok(DrawQuad { buffer })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_quad(&self, cmd: &ProtocolObject<dyn MTLRenderCommandEncoder>, vbo: QuadType) {
|
pub fn draw_quad(&self, cmd: &ProtocolObject<dyn MTLRenderCommandEncoder>, vbo: QuadType) {
|
||||||
|
// TODO: need to see how naga outputs MSL
|
||||||
let offset = match vbo {
|
let offset = match vbo {
|
||||||
QuadType::Offscreen => 0,
|
QuadType::Offscreen => 0,
|
||||||
QuadType::Final => 4,
|
QuadType::Final => 4,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
//! Metal shader runtime errors.
|
//! Metal shader runtime errors.
|
||||||
|
use icrate::Foundation::NSError;
|
||||||
|
use librashader_common::{FilterMode, WrapMode};
|
||||||
use librashader_preprocess::PreprocessError;
|
use librashader_preprocess::PreprocessError;
|
||||||
use librashader_presets::ParsePresetError;
|
use librashader_presets::ParsePresetError;
|
||||||
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
|
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
|
||||||
use librashader_runtime::image::ImageError;
|
use librashader_runtime::image::ImageError;
|
||||||
|
use objc2::rc::Id;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
|
||||||
|
|
||||||
/// Cumulative error type for Metal filter chains.
|
/// Cumulative error type for Metal filter chains.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -22,7 +24,13 @@ pub enum FilterChainError {
|
||||||
#[error("sampler create error")]
|
#[error("sampler create error")]
|
||||||
SamplerError(WrapMode, FilterMode, FilterMode),
|
SamplerError(WrapMode, FilterMode, FilterMode),
|
||||||
#[error("buffer creation error")]
|
#[error("buffer creation error")]
|
||||||
BufferError
|
BufferError,
|
||||||
|
#[error("metal error")]
|
||||||
|
MetalError(Id<NSError>),
|
||||||
|
#[error("couldn't find entry for shader")]
|
||||||
|
ShaderWrongEntryName,
|
||||||
|
#[error("couldn't create render pass")]
|
||||||
|
FailedToCreateRenderPass,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result type for Metal filter chains.
|
/// Result type for Metal filter chains.
|
||||||
|
|
206
librashader-runtime-metal/src/graphics_pipeline.rs
Normal file
206
librashader-runtime-metal/src/graphics_pipeline.rs
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
use crate::error::{FilterChainError, Result};
|
||||||
|
use icrate::Foundation::NSString;
|
||||||
|
use icrate::Metal::{
|
||||||
|
MTLBlendFactorOneMinusSourceAlpha, MTLBlendFactorSourceAlpha, MTLCommandBuffer,
|
||||||
|
MTLCommandEncoder, MTLDevice, MTLFunction, MTLLibrary, MTLLoadActionDontCare, MTLPixelFormat,
|
||||||
|
MTLPrimitiveTopologyClassTriangle, MTLRenderCommandEncoder, MTLRenderPassDescriptor,
|
||||||
|
MTLRenderPipelineColorAttachmentDescriptor, MTLRenderPipelineDescriptor,
|
||||||
|
MTLRenderPipelineState, MTLScissorRect, MTLStoreActionStore, MTLTexture,
|
||||||
|
MTLVertexAttributeDescriptor, MTLVertexBufferLayoutDescriptor, MTLVertexDescriptor,
|
||||||
|
MTLVertexFormatFloat2, MTLVertexStepFunctionPerVertex, MTLViewport,
|
||||||
|
};
|
||||||
|
use librashader_reflect::back::msl::{CrossMslContext, NagaMslContext};
|
||||||
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
use librashader_runtime::render_target::RenderTarget;
|
||||||
|
use objc2::rc::Id;
|
||||||
|
use objc2::runtime::ProtocolObject;
|
||||||
|
|
||||||
|
pub struct MetalGraphicsPipeline {
|
||||||
|
pub layout: PipelineLayoutObjects,
|
||||||
|
render_pipeline: Id<ProtocolObject<dyn MTLRenderPipelineState>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PipelineLayoutObjects {
|
||||||
|
vertex_lib: Id<ProtocolObject<dyn MTLLibrary>>,
|
||||||
|
fragment_lib: Id<ProtocolObject<dyn MTLLibrary>>,
|
||||||
|
vertex_entry: Id<ProtocolObject<dyn MTLFunction>>,
|
||||||
|
fragment_entry: Id<ProtocolObject<dyn MTLFunction>>,
|
||||||
|
device: Id<ProtocolObject<dyn MTLDevice>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
trait MslEntryPoint {
|
||||||
|
fn entry_point() -> NSString;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MslEntryPoint for CrossMslContext {
|
||||||
|
fn entry_point() -> Id<NSString> {
|
||||||
|
NSString::from_str("main0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MslEntryPoint for NagaMslContext {
|
||||||
|
fn entry_point() -> Id<NSString> {
|
||||||
|
NSString::from_str("main_")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelineLayoutObjects {
|
||||||
|
pub fn new<T: MslEntryPoint>(
|
||||||
|
shader_assembly: &ShaderCompilerOutput<String, T>,
|
||||||
|
device: Id<ProtocolObject<dyn MTLDevice>>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let entry = T::entry_point();
|
||||||
|
|
||||||
|
let vertex = NSString::from_str(&shader_assembly.vertex);
|
||||||
|
let vertex = device.newLibraryWithSource_options_error(&vertex, None)?;
|
||||||
|
let vertex_entry = vertex
|
||||||
|
.newFunctionWithName(&entry)
|
||||||
|
.ok_or(FilterChainError::ShaderWrongEntryName)?;
|
||||||
|
|
||||||
|
let fragment = NSString::from_str(&shader_assembly.fragment);
|
||||||
|
let fragment = device.newLibraryWithSource_options_error(&fragment, None)?;
|
||||||
|
let fragment_entry = fragment
|
||||||
|
.newFunctionWithName(&entry)
|
||||||
|
.ok_or(FilterChainError::ShaderWrongEntryName)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
vertex_lib: vertex,
|
||||||
|
fragment_lib: fragment,
|
||||||
|
vertex_entry,
|
||||||
|
fragment_entry,
|
||||||
|
device,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_vertex_descriptor() -> Id<MTLVertexDescriptor> {
|
||||||
|
let descriptor = MTLVertexDescriptor::new();
|
||||||
|
let attributes = descriptor.attributes();
|
||||||
|
let layouts = descriptor.layouts();
|
||||||
|
|
||||||
|
let binding = MTLVertexBufferLayoutDescriptor::new();
|
||||||
|
|
||||||
|
let vertex_0 = MTLVertexAttributeDescriptor::new();
|
||||||
|
let vertex_1 = MTLVertexAttributeDescriptor::new();
|
||||||
|
|
||||||
|
// hopefully metal fills in vertices otherwise we'll need to use the vec4 stuff.
|
||||||
|
vertex_0.setFormat(MTLVertexFormatFloat2);
|
||||||
|
vertex_0.setBufferIndex(4);
|
||||||
|
vertex_0.setOffset(0);
|
||||||
|
|
||||||
|
vertex_1.setFormat(MTLVertexFormatFloat2);
|
||||||
|
vertex_1.setBufferIndex(4);
|
||||||
|
vertex_1.setOffset(2 * std::mem::size_of::<f32>());
|
||||||
|
|
||||||
|
attributes.setObject_atIndexedSubscript(Some(&vertex_0), 0);
|
||||||
|
|
||||||
|
attributes.setObject_atIndexedSubscript(Some(&vertex_1), 1);
|
||||||
|
|
||||||
|
binding.setStepFunction(MTLVertexStepFunctionPerVertex);
|
||||||
|
binding.setStride(4 * std::mem::size_of::<f32>());
|
||||||
|
layouts.setObject_atIndexedSubscript(Some(&binding), 0);
|
||||||
|
|
||||||
|
descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_color_attachments(
|
||||||
|
format: MTLPixelFormat,
|
||||||
|
) -> Id<MTLRenderPipelineColorAttachmentDescriptor> {
|
||||||
|
let ca = MTLRenderPipelineColorAttachmentDescriptor::new();
|
||||||
|
ca.setPixelFormat(format);
|
||||||
|
ca.setBlendingEnabled(false);
|
||||||
|
ca.setSourceAlphaBlendFactor(MTLBlendFactorSourceAlpha);
|
||||||
|
ca.setSourceRGBBlendFactor(MTLBlendFactorSourceAlpha);
|
||||||
|
ca.setDestinationAlphaBlendFactor(MTLBlendFactorOneMinusSourceAlpha);
|
||||||
|
ca.setDetinationRGBBlendFactor(MTLBlendFactorOneMinusSourceAlpha);
|
||||||
|
|
||||||
|
ca
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_pipeline(
|
||||||
|
&self,
|
||||||
|
format: MTLPixelFormat,
|
||||||
|
) -> Result<Id<ProtocolObject<dyn MTLRenderPipelineState>>> {
|
||||||
|
let descriptor = MTLRenderPipelineDescriptor::new();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let vertex = Self::create_vertex_descriptor();
|
||||||
|
let ca = Self::create_color_attachments(format);
|
||||||
|
|
||||||
|
descriptor.setInputPrimitiveTopology(MTLPrimitiveTopologyClassTriangle);
|
||||||
|
descriptor.setVertexDescriptor(Some(&vertex));
|
||||||
|
|
||||||
|
descriptor
|
||||||
|
.colorAttachments()
|
||||||
|
.setObject_atIndexedSubscript(Some(&ca), 0);
|
||||||
|
|
||||||
|
descriptor.setRasterSampleCount(1);
|
||||||
|
|
||||||
|
descriptor.setVertexFunction(Some(&self.vertex_entry));
|
||||||
|
descriptor.setFragmentFunction(Some(&self.fragment_entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(self
|
||||||
|
.device
|
||||||
|
.newRenderPipelineStateWithDescriptor_error(descriptor.as_ref())?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetalGraphicsPipeline {
|
||||||
|
pub fn new<T: MslEntryPoint>(
|
||||||
|
device: Id<ProtocolObject<dyn MTLDevice>>,
|
||||||
|
shader_assembly: &ShaderCompilerOutput<String, T>,
|
||||||
|
render_pass_format: MTLPixelFormat,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let layout = PipelineLayoutObjects::new(shader_assembly, device)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
layout,
|
||||||
|
render_pipeline: layout.create_pipeline(render_pass_format)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recompile(&mut self, format: MTLPixelFormat) -> Result<()> {
|
||||||
|
let render_pipeline = self.layout.create_pipeline(format)?;
|
||||||
|
self.render_pipeline = render_pipeline;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn begin_rendering<'pass>(
|
||||||
|
&self,
|
||||||
|
output: RenderTarget<&'pass ProtocolObject<dyn MTLTexture>>,
|
||||||
|
buffer: Id<ProtocolObject<dyn MTLCommandBuffer>>,
|
||||||
|
) -> Result<Id<ProtocolObject<dyn MTLRenderCommandEncoder>>> {
|
||||||
|
unsafe {
|
||||||
|
let descriptor = MTLRenderPassDescriptor::new();
|
||||||
|
let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0);
|
||||||
|
ca.setLoadAction(MTLLoadActionDontCare);
|
||||||
|
ca.setStoreAction(MTLStoreActionStore);
|
||||||
|
ca.setTexture(Some(output.output));
|
||||||
|
|
||||||
|
let rpass = buffer
|
||||||
|
.renderCommandEncoderWithDescriptor(&descriptor)
|
||||||
|
.ok_or(FilterChainError::FailedToCreateRenderPass)?;
|
||||||
|
|
||||||
|
rpass.setScissorRect(MTLScissorRect {
|
||||||
|
x: output.x as usize,
|
||||||
|
y: output.y as usize,
|
||||||
|
width: output.output.width(),
|
||||||
|
height: output.output.height(),
|
||||||
|
});
|
||||||
|
|
||||||
|
rpass.setViewport(MTLViewport {
|
||||||
|
originX: output.x as f64,
|
||||||
|
originY: output.y as f64,
|
||||||
|
width: output.output.width() as f64,
|
||||||
|
height: output.output.height() as f64,
|
||||||
|
znear: 0.0,
|
||||||
|
zfar: 1.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
rpass.setRenderPipelineState(&self.render_pipeline);
|
||||||
|
|
||||||
|
Ok(rpass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
mod error;
|
|
||||||
mod samplers;
|
|
||||||
mod draw_quad;
|
mod draw_quad;
|
||||||
|
mod error;
|
||||||
|
mod graphics_pipeline;
|
||||||
|
mod samplers;
|
||||||
|
|
|
@ -28,8 +28,7 @@ impl SamplerSet {
|
||||||
// SAFETY: the sampler set is complete for the matrix
|
// SAFETY: the sampler set is complete for the matrix
|
||||||
// wrap x filter x mipmap
|
// wrap x filter x mipmap
|
||||||
let id: &Id<ProtocolObject<dyn MTLSamplerState>> = unsafe {
|
let id: &Id<ProtocolObject<dyn MTLSamplerState>> = unsafe {
|
||||||
self
|
self.samplers
|
||||||
.samplers
|
|
||||||
.get(&(wrap, filter, mipmap))
|
.get(&(wrap, filter, mipmap))
|
||||||
.unwrap_unchecked()
|
.unwrap_unchecked()
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue