rt(mtl): properly bind push buffer and select bgra8 in place of rgba8

This commit is contained in:
chyyran 2024-02-12 19:43:28 -05:00 committed by Ronny Chan
parent 43da6e60c6
commit 05f634a9b9
9 changed files with 80 additions and 39 deletions

View file

@ -1,8 +1,8 @@
use crate::error; use crate::error;
use crate::error::FilterChainError; use crate::error::FilterChainError;
use icrate::Foundation::NSRange; use icrate::Foundation::{NSRange, NSString};
use icrate::Metal::{ use icrate::Metal::{
MTLBuffer, MTLDevice, MTLResourceStorageModeManaged, MTLResourceStorageModeShared, MTLBuffer, MTLDevice, MTLResource, MTLResourceStorageModeManaged, MTLResourceStorageModeShared,
}; };
use objc2::rc::Id; use objc2::rc::Id;
use objc2::runtime::ProtocolObject; use objc2::runtime::ProtocolObject;
@ -20,7 +20,11 @@ impl AsRef<ProtocolObject<dyn MTLBuffer>> for MetalBuffer {
} }
impl MetalBuffer { impl MetalBuffer {
pub fn new(device: &ProtocolObject<dyn MTLDevice>, size: usize) -> error::Result<Self> { pub fn new(
device: &ProtocolObject<dyn MTLDevice>,
size: usize,
label: &str,
) -> error::Result<Self> {
let resource_mode = if cfg!(target_os = "ios") { let resource_mode = if cfg!(target_os = "ios") {
MTLResourceStorageModeShared MTLResourceStorageModeShared
} else { } else {
@ -30,6 +34,9 @@ impl MetalBuffer {
let buffer = device let buffer = device
.newBufferWithLength_options(size, resource_mode) .newBufferWithLength_options(size, resource_mode)
.ok_or(FilterChainError::BufferError)?; .ok_or(FilterChainError::BufferError)?;
buffer.setLabel(Some(&*NSString::from_str(label)));
Ok(Self { buffer, size }) Ok(Self { buffer, size })
} }

View file

@ -39,7 +39,6 @@ const OFFSCREEN_VBO_DATA: [MetalVertex; 4] = [
}, },
]; ];
const FINAL_VBO_DATA: [MetalVertex; 4] = [ const FINAL_VBO_DATA: [MetalVertex; 4] = [
MetalVertex { MetalVertex {
position: [0.0, 0.0, 0.0, 1.0], position: [0.0, 0.0, 0.0, 1.0],
@ -130,9 +129,7 @@ impl DrawQuad {
unsafe { unsafe {
cmd.setVertexBuffer_offset_atIndex(Some(&self.buffer), 0, VERTEX_BUFFER_INDEX); cmd.setVertexBuffer_offset_atIndex(Some(&self.buffer), 0, VERTEX_BUFFER_INDEX);
cmd.drawPrimitives_vertexStart_vertexCount(MTLPrimitiveTypeTriangleStrip, cmd.drawPrimitives_vertexStart_vertexCount(MTLPrimitiveTypeTriangleStrip, offset, 4);
offset,
4);
} }
} }
} }

View file

@ -8,9 +8,10 @@ use crate::luts::LutTexture;
use crate::options::{FilterChainOptionsMetal, FrameOptionsMetal}; use crate::options::{FilterChainOptionsMetal, FrameOptionsMetal};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::{get_texture_size, InputTexture, OwnedTexture}; use crate::texture::{get_texture_size, InputTexture, OwnedTexture};
use icrate::Foundation::NSString;
use icrate::Metal::{ use icrate::Metal::{
MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLPixelFormat,
MTLPixelFormat, MTLPixelFormatRGBA8Unorm, MTLTexture, MTLPixelFormatRGBA8Unorm, MTLResource, MTLTexture,
}; };
use librashader_common::{ImageFormat, Size, Viewport}; use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::context::VideoDriver; use librashader_presets::context::VideoDriver;
@ -59,7 +60,7 @@ pub struct FilterChainMetal {
feedback_framebuffers: Box<[OwnedTexture]>, feedback_framebuffers: Box<[OwnedTexture]>,
history_framebuffers: VecDeque<OwnedTexture>, history_framebuffers: VecDeque<OwnedTexture>,
disable_mipmaps: bool, disable_mipmaps: bool,
default_options: FrameOptionsMetal default_options: FrameOptionsMetal,
} }
impl Debug for FilterChainMetal { impl Debug for FilterChainMetal {
@ -160,8 +161,8 @@ impl FilterChainMetal {
.map_or(0, |push| push.size); .map_or(0, |push| push.size);
let uniform_storage = UniformStorage::new_with_storage( let uniform_storage = UniformStorage::new_with_storage(
MetalBuffer::new(&device, ubo_size)?, MetalBuffer::new(&device, ubo_size, "ubo")?,
MetalBuffer::new(&device, push_size as usize)?, MetalBuffer::new(&device, push_size as usize, "pcb")?,
); );
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset()); let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
@ -366,6 +367,9 @@ impl FilterChainMetal {
let mut source = original.try_clone()?; let mut source = original.try_clone()?;
source
.texture
.setLabel(Some(&*NSString::from_str("sourcetex")));
// swap output and feedback **before** recording command buffers // swap output and feedback **before** recording command buffers
std::mem::swap( std::mem::swap(
&mut self.output_framebuffers, &mut self.output_framebuffers,
@ -404,8 +408,7 @@ impl FilterChainMetal {
source.wrap_mode = pass.config.wrap_mode; source.wrap_mode = pass.config.wrap_mode;
source.mip_filter = pass.config.filter; source.mip_filter = pass.config.filter;
let out = let out = RenderTarget::identity(target.texture.as_ref());
RenderTarget::identity(target.texture.as_ref());
pass.draw( pass.draw(
&cmd_buffer, &cmd_buffer,
index, index,

View file

@ -2,6 +2,7 @@ use crate::buffer::MetalBuffer;
use crate::error; use crate::error;
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::graphics_pipeline::MetalGraphicsPipeline; use crate::graphics_pipeline::MetalGraphicsPipeline;
use crate::options::FrameOptionsMetal;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::{get_texture_size, InputTexture}; use crate::texture::{get_texture_size, InputTexture};
use icrate::Metal::{MTLCommandBuffer, MTLCommandEncoder, MTLRenderCommandEncoder, MTLTexture}; use icrate::Metal::{MTLCommandBuffer, MTLCommandEncoder, MTLRenderCommandEncoder, MTLTexture};
@ -17,7 +18,6 @@ use librashader_runtime::render_target::RenderTarget;
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage}; use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage};
use objc2::runtime::ProtocolObject; use objc2::runtime::ProtocolObject;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::options::FrameOptionsMetal;
impl TextureInput for InputTexture { impl TextureInput for InputTexture {
fn size(&self) -> Size<u32> { fn size(&self) -> Size<u32> {
@ -106,12 +106,12 @@ impl FilterPass {
unsafe { unsafe {
// SPIRV-Cross always has PCB bound to 1. Naga is arbitrary but their compilation provides the next free binding for drawquad. // 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( cmd.setVertexBuffer_offset_atIndex(
Some(self.uniform_storage.inner_ubo().as_ref()), Some(self.uniform_storage.inner_push().as_ref()),
0, 0,
pcb.binding.unwrap_or(1) as usize, pcb.binding.unwrap_or(1) as usize,
); );
cmd.setFragmentBuffer_offset_atIndex( cmd.setFragmentBuffer_offset_atIndex(
Some(self.uniform_storage.inner_ubo().as_ref()), Some(self.uniform_storage.inner_push().as_ref()),
0, 0,
pcb.binding.unwrap_or(1) as usize, pcb.binding.unwrap_or(1) as usize,
) )

View file

@ -1,13 +1,22 @@
use std::mem::offset_of; use crate::draw_quad::MetalVertex;
use crate::error::{FilterChainError, Result}; use crate::error::{FilterChainError, Result};
use crate::select_optimal_pixel_format;
use icrate::Foundation::NSString; 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::msl::{CrossMslContext, NagaMslContext};
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_runtime::render_target::RenderTarget; use librashader_runtime::render_target::RenderTarget;
use objc2::rc::Id; use objc2::rc::Id;
use objc2::runtime::ProtocolObject; 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. /// 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; pub const VERTEX_BUFFER_INDEX: usize = 4;
@ -99,10 +108,10 @@ impl PipelineLayoutObjects {
} }
unsafe fn create_color_attachments( unsafe fn create_color_attachments(
ca: Id<MTLRenderPipelineColorAttachmentDescriptor>,
format: MTLPixelFormat, format: MTLPixelFormat,
) -> Id<MTLRenderPipelineColorAttachmentDescriptor> { ) -> Id<MTLRenderPipelineColorAttachmentDescriptor> {
let ca = MTLRenderPipelineColorAttachmentDescriptor::new(); ca.setPixelFormat(select_optimal_pixel_format(format));
ca.setPixelFormat(format);
ca.setBlendingEnabled(false); ca.setBlendingEnabled(false);
ca.setSourceAlphaBlendFactor(MTLBlendFactorSourceAlpha); ca.setSourceAlphaBlendFactor(MTLBlendFactorSourceAlpha);
ca.setSourceRGBBlendFactor(MTLBlendFactorSourceAlpha); ca.setSourceRGBBlendFactor(MTLBlendFactorSourceAlpha);
@ -121,14 +130,11 @@ impl PipelineLayoutObjects {
unsafe { unsafe {
let vertex = Self::create_vertex_descriptor(); let vertex = Self::create_vertex_descriptor();
let ca = Self::create_color_attachments(format);
descriptor.setInputPrimitiveTopology(MTLPrimitiveTopologyClassTriangle); descriptor.setInputPrimitiveTopology(MTLPrimitiveTopologyClassTriangle);
descriptor.setVertexDescriptor(Some(&vertex)); descriptor.setVertexDescriptor(Some(&vertex));
descriptor let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0);
.colorAttachments() Self::create_color_attachments(ca, format);
.setObject_atIndexedSubscript(Some(&ca), 0);
descriptor.setRasterSampleCount(1); descriptor.setRasterSampleCount(1);
@ -172,8 +178,7 @@ impl MetalGraphicsPipeline {
) -> Result<Id<ProtocolObject<dyn MTLRenderCommandEncoder>>> { ) -> Result<Id<ProtocolObject<dyn MTLRenderCommandEncoder>>> {
unsafe { unsafe {
let descriptor = MTLRenderPassDescriptor::new(); let descriptor = MTLRenderPassDescriptor::new();
let ca = descriptor.colorAttachments() let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0);
.objectAtIndexedSubscript(0);
ca.setLoadAction(MTLLoadActionDontCare); ca.setLoadAction(MTLLoadActionDontCare);
ca.setStoreAction(MTLStoreActionStore); ca.setStoreAction(MTLStoreActionStore);
ca.setTexture(Some(output.output)); ca.setTexture(Some(output.output));
@ -182,6 +187,9 @@ impl MetalGraphicsPipeline {
.renderCommandEncoderWithDescriptor(&descriptor) .renderCommandEncoderWithDescriptor(&descriptor)
.ok_or(FilterChainError::FailedToCreateRenderPass)?; .ok_or(FilterChainError::FailedToCreateRenderPass)?;
rpass.setLabel(Some(&*NSString::from_str("librashader rpass")));
rpass.setRenderPipelineState(&self.render_pipeline);
rpass.setScissorRect(MTLScissorRect { rpass.setScissorRect(MTLScissorRect {
x: output.x as usize, x: output.x as usize,
y: output.y as usize, y: output.y as usize,
@ -198,8 +206,6 @@ impl MetalGraphicsPipeline {
zfar: 1.0, zfar: 1.0,
}); });
rpass.setRenderPipelineState(&self.render_pipeline);
Ok(rpass) Ok(rpass)
} }
} }

View file

@ -11,8 +11,23 @@ mod samplers;
mod texture; mod texture;
pub use filter_chain::FilterChainMetal; pub use filter_chain::FilterChainMetal;
use icrate::Metal::{
MTLPixelFormat, MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB,
MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB,
};
pub mod error; pub mod error;
pub mod options; pub mod options;
use librashader_runtime::impl_filter_chain_parameters; use librashader_runtime::impl_filter_chain_parameters;
impl_filter_chain_parameters!(FilterChainMetal); 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;
}

View file

@ -3,7 +3,12 @@
use core::{cell::OnceCell, ptr::NonNull}; use core::{cell::OnceCell, ptr::NonNull};
use std::sync::RwLock; 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::{ use icrate::{
AppKit::{ AppKit::{
NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate, NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate,
@ -218,11 +223,10 @@ declare_class!(
let pipeline_state = device let pipeline_state = device
.newRenderPipelineStateWithDescriptor_error(&pipeline_descriptor) .newRenderPipelineStateWithDescriptor_error(&pipeline_descriptor)
.expect("Failed to create a pipeline state."); .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-royale.slangp").unwrap();
// let preset = ShaderPreset::try_parse("./test/basic.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 filter_chain = FilterChainMetal::load_from_preset( let filter_chain = FilterChainMetal::load_from_preset(
preset, preset,
@ -389,11 +393,16 @@ declare_class!(
.newTextureWithDescriptor(&tex_desc) .newTextureWithDescriptor(&tex_desc)
.unwrap(); .unwrap();
frontbuffer
.setLabel(Some(&*NSString::from_str("librashader frontbuffer")));
let backbuffer = command_queue let backbuffer = command_queue
.device() .device()
.newTextureWithDescriptor(&tex_desc) .newTextureWithDescriptor(&tex_desc)
.unwrap(); .unwrap();
backbuffer
.setLabel(Some(&*NSString::from_str("librashader backbuffer")));
let blit = command_buffer let blit = command_buffer
.blitCommandEncoder() .blitCommandEncoder()
.unwrap(); .unwrap();

View file

@ -1,4 +1,5 @@
use crate::error::{FilterChainError, Result}; use crate::error::{FilterChainError, Result};
use crate::select_optimal_pixel_format;
use icrate::Metal::{ use icrate::Metal::{
MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLDevice, MTLPixelFormat, MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLDevice, MTLPixelFormat,
MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead, MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead,
@ -54,7 +55,7 @@ impl OwnedTexture {
let descriptor = unsafe { let descriptor = unsafe {
let descriptor = let descriptor =
MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped( MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped(
format, select_optimal_pixel_format(format),
size.width as usize, size.width as usize,
size.height as usize, size.height as usize,
max_miplevels <= 1, max_miplevels <= 1,
@ -102,7 +103,7 @@ impl OwnedTexture {
if self.size != size if self.size != size
|| (mipmap && self.max_miplevels == 1) || (mipmap && self.max_miplevels == 1)
|| (!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)?; let mut new = OwnedTexture::new(device, size, self.max_miplevels, format)?;
std::mem::swap(self, &mut new); std::mem::swap(self, &mut new);

View file

@ -3,7 +3,10 @@
use core::{cell::OnceCell, ptr::NonNull}; use core::{cell::OnceCell, ptr::NonNull};
use std::sync::RwLock; use std::sync::RwLock;
use icrate::Metal::{MTLBlitCommandEncoder, MTLClearColor, MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget}; use icrate::Metal::{
MTLBlitCommandEncoder, MTLClearColor, MTLTexture, MTLTextureDescriptor,
MTLTextureUsageRenderTarget,
};
use icrate::{ use icrate::{
AppKit::{ AppKit::{
NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate, NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate,