diff --git a/librashader-runtime-metal/src/buffer.rs b/librashader-runtime-metal/src/buffer.rs index 36f9590..40767ab 100644 --- a/librashader-runtime-metal/src/buffer.rs +++ b/librashader-runtime-metal/src/buffer.rs @@ -1,8 +1,8 @@ use crate::error; use crate::error::FilterChainError; -use icrate::Foundation::NSRange; +use icrate::Foundation::{NSRange, NSString}; use icrate::Metal::{ - MTLBuffer, MTLDevice, MTLResourceStorageModeManaged, MTLResourceStorageModeShared, + MTLBuffer, MTLDevice, MTLResource, MTLResourceStorageModeManaged, MTLResourceStorageModeShared, }; use objc2::rc::Id; use objc2::runtime::ProtocolObject; @@ -20,7 +20,11 @@ impl AsRef> for MetalBuffer { } impl MetalBuffer { - pub fn new(device: &ProtocolObject, size: usize) -> error::Result { + pub fn new( + device: &ProtocolObject, + size: usize, + label: &str, + ) -> error::Result { let resource_mode = if cfg!(target_os = "ios") { MTLResourceStorageModeShared } else { @@ -30,6 +34,9 @@ impl MetalBuffer { let buffer = device .newBufferWithLength_options(size, resource_mode) .ok_or(FilterChainError::BufferError)?; + + buffer.setLabel(Some(&*NSString::from_str(label))); + Ok(Self { buffer, size }) } diff --git a/librashader-runtime-metal/src/draw_quad.rs b/librashader-runtime-metal/src/draw_quad.rs index 872d103..97196c0 100644 --- a/librashader-runtime-metal/src/draw_quad.rs +++ b/librashader-runtime-metal/src/draw_quad.rs @@ -39,7 +39,6 @@ const OFFSCREEN_VBO_DATA: [MetalVertex; 4] = [ }, ]; - const FINAL_VBO_DATA: [MetalVertex; 4] = [ MetalVertex { position: [0.0, 0.0, 0.0, 1.0], @@ -130,9 +129,7 @@ impl DrawQuad { unsafe { cmd.setVertexBuffer_offset_atIndex(Some(&self.buffer), 0, VERTEX_BUFFER_INDEX); - cmd.drawPrimitives_vertexStart_vertexCount(MTLPrimitiveTypeTriangleStrip, - offset, - 4); + cmd.drawPrimitives_vertexStart_vertexCount(MTLPrimitiveTypeTriangleStrip, offset, 4); } } } diff --git a/librashader-runtime-metal/src/filter_chain.rs b/librashader-runtime-metal/src/filter_chain.rs index a912e46..8923599 100644 --- a/librashader-runtime-metal/src/filter_chain.rs +++ b/librashader-runtime-metal/src/filter_chain.rs @@ -8,9 +8,10 @@ use crate::luts::LutTexture; use crate::options::{FilterChainOptionsMetal, FrameOptionsMetal}; use crate::samplers::SamplerSet; use crate::texture::{get_texture_size, InputTexture, OwnedTexture}; +use icrate::Foundation::NSString; use icrate::Metal::{ - MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, - MTLPixelFormat, MTLPixelFormatRGBA8Unorm, MTLTexture, + MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLPixelFormat, + MTLPixelFormatRGBA8Unorm, MTLResource, MTLTexture, }; use librashader_common::{ImageFormat, Size, Viewport}; use librashader_presets::context::VideoDriver; @@ -59,7 +60,7 @@ pub struct FilterChainMetal { feedback_framebuffers: Box<[OwnedTexture]>, history_framebuffers: VecDeque, disable_mipmaps: bool, - default_options: FrameOptionsMetal + default_options: FrameOptionsMetal, } impl Debug for FilterChainMetal { @@ -160,8 +161,8 @@ impl FilterChainMetal { .map_or(0, |push| push.size); let uniform_storage = UniformStorage::new_with_storage( - MetalBuffer::new(&device, ubo_size)?, - MetalBuffer::new(&device, push_size as usize)?, + MetalBuffer::new(&device, ubo_size, "ubo")?, + MetalBuffer::new(&device, push_size as usize, "pcb")?, ); let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset()); @@ -366,6 +367,9 @@ impl FilterChainMetal { let mut source = original.try_clone()?; + source + .texture + .setLabel(Some(&*NSString::from_str("sourcetex"))); // swap output and feedback **before** recording command buffers std::mem::swap( &mut self.output_framebuffers, @@ -404,8 +408,7 @@ impl FilterChainMetal { source.wrap_mode = pass.config.wrap_mode; source.mip_filter = pass.config.filter; - let out = - RenderTarget::identity(target.texture.as_ref()); + let out = RenderTarget::identity(target.texture.as_ref()); pass.draw( &cmd_buffer, index, diff --git a/librashader-runtime-metal/src/filter_pass.rs b/librashader-runtime-metal/src/filter_pass.rs index 3dcaef1..3d6f2c8 100644 --- a/librashader-runtime-metal/src/filter_pass.rs +++ b/librashader-runtime-metal/src/filter_pass.rs @@ -2,6 +2,7 @@ use crate::buffer::MetalBuffer; use crate::error; use crate::filter_chain::FilterCommon; use crate::graphics_pipeline::MetalGraphicsPipeline; +use crate::options::FrameOptionsMetal; use crate::samplers::SamplerSet; use crate::texture::{get_texture_size, InputTexture}; use icrate::Metal::{MTLCommandBuffer, MTLCommandEncoder, MTLRenderCommandEncoder, MTLTexture}; @@ -17,7 +18,6 @@ use librashader_runtime::render_target::RenderTarget; use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage}; use objc2::runtime::ProtocolObject; use rustc_hash::FxHashMap; -use crate::options::FrameOptionsMetal; impl TextureInput for InputTexture { fn size(&self) -> Size { @@ -106,12 +106,12 @@ impl FilterPass { unsafe { // SPIRV-Cross always has PCB bound to 1. Naga is arbitrary but their compilation provides the next free binding for drawquad. cmd.setVertexBuffer_offset_atIndex( - Some(self.uniform_storage.inner_ubo().as_ref()), + Some(self.uniform_storage.inner_push().as_ref()), 0, pcb.binding.unwrap_or(1) as usize, ); cmd.setFragmentBuffer_offset_atIndex( - Some(self.uniform_storage.inner_ubo().as_ref()), + Some(self.uniform_storage.inner_push().as_ref()), 0, pcb.binding.unwrap_or(1) as usize, ) diff --git a/librashader-runtime-metal/src/graphics_pipeline.rs b/librashader-runtime-metal/src/graphics_pipeline.rs index 92b4abb..4bc7a6c 100644 --- a/librashader-runtime-metal/src/graphics_pipeline.rs +++ b/librashader-runtime-metal/src/graphics_pipeline.rs @@ -1,13 +1,22 @@ -use std::mem::offset_of; +use crate::draw_quad::MetalVertex; use crate::error::{FilterChainError, Result}; +use crate::select_optimal_pixel_format; use icrate::Foundation::NSString; -use icrate::Metal::{MTLBlendFactorOneMinusSourceAlpha, MTLBlendFactorSourceAlpha, MTLClearColor, MTLCommandBuffer, MTLDevice, MTLFunction, MTLLibrary, MTLLoadActionDontCare, MTLPixelFormat, MTLPrimitiveTopologyClassTriangle, MTLRenderCommandEncoder, MTLRenderPassDescriptor, MTLRenderPipelineColorAttachmentDescriptor, MTLRenderPipelineDescriptor, MTLRenderPipelineState, MTLScissorRect, MTLStoreActionStore, MTLTexture, MTLVertexAttributeDescriptor, MTLVertexBufferLayoutDescriptor, MTLVertexDescriptor, MTLVertexFormatFloat2, MTLVertexFormatFloat4, MTLVertexStepFunctionPerVertex, MTLViewport}; +use icrate::Metal::{ + MTLBlendFactorOneMinusSourceAlpha, MTLBlendFactorSourceAlpha, MTLClearColor, MTLCommandBuffer, + MTLCommandEncoder, MTLDevice, MTLFunction, MTLLibrary, MTLLoadActionDontCare, MTLPixelFormat, + MTLPrimitiveTopologyClassTriangle, MTLRenderCommandEncoder, MTLRenderPassDescriptor, + MTLRenderPipelineColorAttachmentDescriptor, MTLRenderPipelineDescriptor, + MTLRenderPipelineState, MTLScissorRect, MTLStoreActionStore, MTLTexture, + MTLVertexAttributeDescriptor, MTLVertexBufferLayoutDescriptor, MTLVertexDescriptor, + MTLVertexFormatFloat2, MTLVertexFormatFloat4, MTLVertexStepFunctionPerVertex, MTLViewport, +}; use librashader_reflect::back::msl::{CrossMslContext, NagaMslContext}; use librashader_reflect::back::ShaderCompilerOutput; use librashader_runtime::render_target::RenderTarget; use objc2::rc::Id; use objc2::runtime::ProtocolObject; -use crate::draw_quad::MetalVertex; +use std::mem::offset_of; /// This is only really plausible for SPIRV-Cross, for Naga we need to supply the next plausible binding. pub const VERTEX_BUFFER_INDEX: usize = 4; @@ -99,10 +108,10 @@ impl PipelineLayoutObjects { } unsafe fn create_color_attachments( + ca: Id, format: MTLPixelFormat, ) -> Id { - let ca = MTLRenderPipelineColorAttachmentDescriptor::new(); - ca.setPixelFormat(format); + ca.setPixelFormat(select_optimal_pixel_format(format)); ca.setBlendingEnabled(false); ca.setSourceAlphaBlendFactor(MTLBlendFactorSourceAlpha); ca.setSourceRGBBlendFactor(MTLBlendFactorSourceAlpha); @@ -121,14 +130,11 @@ impl PipelineLayoutObjects { 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); + let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0); + Self::create_color_attachments(ca, format); descriptor.setRasterSampleCount(1); @@ -172,8 +178,7 @@ impl MetalGraphicsPipeline { ) -> Result>> { unsafe { let descriptor = MTLRenderPassDescriptor::new(); - let ca = descriptor.colorAttachments() - .objectAtIndexedSubscript(0); + let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0); ca.setLoadAction(MTLLoadActionDontCare); ca.setStoreAction(MTLStoreActionStore); ca.setTexture(Some(output.output)); @@ -182,6 +187,9 @@ impl MetalGraphicsPipeline { .renderCommandEncoderWithDescriptor(&descriptor) .ok_or(FilterChainError::FailedToCreateRenderPass)?; + rpass.setLabel(Some(&*NSString::from_str("librashader rpass"))); + rpass.setRenderPipelineState(&self.render_pipeline); + rpass.setScissorRect(MTLScissorRect { x: output.x as usize, y: output.y as usize, @@ -198,8 +206,6 @@ impl MetalGraphicsPipeline { zfar: 1.0, }); - rpass.setRenderPipelineState(&self.render_pipeline); - Ok(rpass) } } diff --git a/librashader-runtime-metal/src/lib.rs b/librashader-runtime-metal/src/lib.rs index 5932176..1da3053 100644 --- a/librashader-runtime-metal/src/lib.rs +++ b/librashader-runtime-metal/src/lib.rs @@ -11,8 +11,23 @@ mod samplers; mod texture; pub use filter_chain::FilterChainMetal; +use icrate::Metal::{ + MTLPixelFormat, MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB, + MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB, +}; pub mod error; pub mod options; use librashader_runtime::impl_filter_chain_parameters; impl_filter_chain_parameters!(FilterChainMetal); + +fn select_optimal_pixel_format(format: MTLPixelFormat) -> MTLPixelFormat { + if format == MTLPixelFormatRGBA8Unorm { + return MTLPixelFormatBGRA8Unorm; + } + + if format == MTLPixelFormatRGBA8Unorm_sRGB { + return MTLPixelFormatBGRA8Unorm_sRGB; + } + return format; +} diff --git a/librashader-runtime-metal/src/main.rs b/librashader-runtime-metal/src/main.rs index c91ed34..2e4967a 100644 --- a/librashader-runtime-metal/src/main.rs +++ b/librashader-runtime-metal/src/main.rs @@ -3,7 +3,12 @@ use core::{cell::OnceCell, ptr::NonNull}; use std::sync::RwLock; -use icrate::Metal::{MTLBlitCommandEncoder, MTLClearColor, MTLPixelFormatRGBA8Unorm, MTLTexture, MTLTextureDescriptor, MTLTextureUsagePixelFormatView, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead}; +use icrate::Foundation::NSString; +use icrate::Metal::{ + MTLBlitCommandEncoder, MTLClearColor, MTLPixelFormatRGBA8Unorm, MTLResource, MTLTexture, + MTLTextureDescriptor, MTLTextureUsagePixelFormatView, MTLTextureUsageRenderTarget, + MTLTextureUsageShaderRead, +}; use icrate::{ AppKit::{ NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate, @@ -218,11 +223,10 @@ declare_class!( let pipeline_state = device .newRenderPipelineStateWithDescriptor_error(&pipeline_descriptor) .expect("Failed to create a pipeline state."); + // let preset = ShaderPreset::try_parse("./test/shaders_slang/crt/crt-lottes.slangp").unwrap(); - // let preset = ShaderPreset::try_parse("./test/shaders_slang/crt/crt-lottes.slangp").unwrap(); - - // let preset = ShaderPreset::try_parse("./test/shaders_slang/crt/crt-lottes.slangp").unwrap(); - let preset = ShaderPreset::try_parse("./test/basic.slangp").unwrap(); + let preset = ShaderPreset::try_parse("./test/shaders_slang/crt/crt-royale.slangp").unwrap(); + // let preset = ShaderPreset::try_parse("./test/basic.slangp").unwrap(); let filter_chain = FilterChainMetal::load_from_preset( preset, @@ -389,11 +393,16 @@ declare_class!( .newTextureWithDescriptor(&tex_desc) .unwrap(); + frontbuffer + .setLabel(Some(&*NSString::from_str("librashader frontbuffer"))); + let backbuffer = command_queue .device() .newTextureWithDescriptor(&tex_desc) .unwrap(); + backbuffer + .setLabel(Some(&*NSString::from_str("librashader backbuffer"))); let blit = command_buffer .blitCommandEncoder() .unwrap(); diff --git a/librashader-runtime-metal/src/texture.rs b/librashader-runtime-metal/src/texture.rs index 1eb238f..38bb3ec 100644 --- a/librashader-runtime-metal/src/texture.rs +++ b/librashader-runtime-metal/src/texture.rs @@ -1,4 +1,5 @@ use crate::error::{FilterChainError, Result}; +use crate::select_optimal_pixel_format; use icrate::Metal::{ MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLDevice, MTLPixelFormat, MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead, @@ -54,7 +55,7 @@ impl OwnedTexture { let descriptor = unsafe { let descriptor = MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped( - format, + select_optimal_pixel_format(format), size.width as usize, size.height as usize, max_miplevels <= 1, @@ -102,7 +103,7 @@ impl OwnedTexture { if self.size != size || (mipmap && self.max_miplevels == 1) || (!mipmap && self.max_miplevels != 1) - || format != self.texture.pixelFormat() + || format != select_optimal_pixel_format(format) { let mut new = OwnedTexture::new(device, size, self.max_miplevels, format)?; std::mem::swap(self, &mut new); diff --git a/librashader-runtime-metal/tests/hello_triangle/main.rs b/librashader-runtime-metal/tests/hello_triangle/main.rs index 2ad62fb..183fd7a 100644 --- a/librashader-runtime-metal/tests/hello_triangle/main.rs +++ b/librashader-runtime-metal/tests/hello_triangle/main.rs @@ -3,7 +3,10 @@ use core::{cell::OnceCell, ptr::NonNull}; use std::sync::RwLock; -use icrate::Metal::{MTLBlitCommandEncoder, MTLClearColor, MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget}; +use icrate::Metal::{ + MTLBlitCommandEncoder, MTLClearColor, MTLTexture, MTLTextureDescriptor, + MTLTextureUsageRenderTarget, +}; use icrate::{ AppKit::{ NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate,