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::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<ProtocolObject<dyn MTLBuffer>> for 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") {
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 })
}

View file

@ -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);
}
}
}

View file

@ -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<OwnedTexture>,
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,

View file

@ -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<u32> {
@ -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,
)

View file

@ -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<MTLRenderPipelineColorAttachmentDescriptor>,
format: MTLPixelFormat,
) -> Id<MTLRenderPipelineColorAttachmentDescriptor> {
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<Id<ProtocolObject<dyn MTLRenderCommandEncoder>>> {
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)
}
}

View file

@ -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;
}

View file

@ -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/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();

View file

@ -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);

View file

@ -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,