rt(mtl): draw final pass to output targets
This commit is contained in:
parent
22b2118e97
commit
e24beede0b
|
@ -58,22 +58,6 @@ pub struct DrawQuad {
|
||||||
impl DrawQuad {
|
impl DrawQuad {
|
||||||
pub fn new(device: &ProtocolObject<dyn MTLDevice>) -> Result<DrawQuad> {
|
pub fn new(device: &ProtocolObject<dyn MTLDevice>) -> Result<DrawQuad> {
|
||||||
let vbo_data: &'static [u8] = bytemuck::cast_slice(&VBO_DATA);
|
let vbo_data: &'static [u8] = bytemuck::cast_slice(&VBO_DATA);
|
||||||
// let buffer = unsafe {
|
|
||||||
// device
|
|
||||||
// .newBufferWithBytes_length_options(
|
|
||||||
// // SAFETY: this pointer is const.
|
|
||||||
// // https://developer.apple.com/documentation/metal/mtldevice/1433429-newbufferwithbytes
|
|
||||||
// NonNull::new_unchecked(vbo_data.as_ptr() as *mut c_void),
|
|
||||||
// vbo_data.len(),
|
|
||||||
// if cfg!(target_os = "ios") {
|
|
||||||
// MTLResourceStorageModeShared
|
|
||||||
// } else {
|
|
||||||
// MTLResourceStorageModeManaged
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// .ok_or(FilterChainError::BufferError)?
|
|
||||||
// };
|
|
||||||
|
|
||||||
let buffer = unsafe {
|
let buffer = unsafe {
|
||||||
device
|
device
|
||||||
.newBufferWithBytes_length_options(
|
.newBufferWithBytes_length_options(
|
||||||
|
|
|
@ -27,7 +27,7 @@ use librashader_runtime::quad::QuadType;
|
||||||
use librashader_runtime::render_target::RenderTarget;
|
use librashader_runtime::render_target::RenderTarget;
|
||||||
use librashader_runtime::scaling::ScaleFramebuffer;
|
use librashader_runtime::scaling::ScaleFramebuffer;
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
use objc2::rc::{Id, Retained};
|
use objc2::rc::Id;
|
||||||
use objc2::runtime::ProtocolObject;
|
use objc2::runtime::ProtocolObject;
|
||||||
use objc2_foundation::NSString;
|
use objc2_foundation::NSString;
|
||||||
use objc2_metal::{
|
use objc2_metal::{
|
||||||
|
@ -206,7 +206,6 @@ impl FilterChainMetal {
|
||||||
cmd: &ProtocolObject<dyn MTLCommandBuffer>,
|
cmd: &ProtocolObject<dyn MTLCommandBuffer>,
|
||||||
input: &ProtocolObject<dyn MTLTexture>,
|
input: &ProtocolObject<dyn MTLTexture>,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
|
|
||||||
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
||||||
let mipmapper = cmd
|
let mipmapper = cmd
|
||||||
.blitCommandEncoder()
|
.blitCommandEncoder()
|
||||||
|
@ -436,6 +435,8 @@ impl FilterChainMetal {
|
||||||
target.generate_mipmaps(&cmd)?;
|
target.generate_mipmaps(&cmd)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.common.output_textures[index] =
|
||||||
|
Some(target.as_input(pass.config.filter, pass.config.wrap_mode)?);
|
||||||
source = self.common.output_textures[index]
|
source = self.common.output_textures[index]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(InputTexture::try_clone)
|
.map(InputTexture::try_clone)
|
||||||
|
@ -446,7 +447,10 @@ impl FilterChainMetal {
|
||||||
assert_eq!(last.len(), 1);
|
assert_eq!(last.len(), 1);
|
||||||
|
|
||||||
if let Some(pass) = last.iter_mut().next() {
|
if let Some(pass) = last.iter_mut().next() {
|
||||||
if pass.graphics_pipeline.render_pass_format != viewport.output.pixelFormat() {
|
if !pass
|
||||||
|
.graphics_pipeline
|
||||||
|
.has_format(viewport.output.pixelFormat())
|
||||||
|
{
|
||||||
// need to recompile
|
// need to recompile
|
||||||
pass.graphics_pipeline
|
pass.graphics_pipeline
|
||||||
.recompile(&self.common.device, viewport.output.pixelFormat())?;
|
.recompile(&self.common.device, viewport.output.pixelFormat())?;
|
||||||
|
@ -455,6 +459,24 @@ impl FilterChainMetal {
|
||||||
source.filter_mode = pass.config.filter;
|
source.filter_mode = pass.config.filter;
|
||||||
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 index = passes_len - 1;
|
||||||
|
|
||||||
|
let output_image = &self.output_framebuffers[index].texture;
|
||||||
|
|
||||||
|
let out = RenderTarget::viewport_with_output(output_image.as_ref(), viewport);
|
||||||
|
pass.draw(
|
||||||
|
&cmd,
|
||||||
|
passes_len - 1,
|
||||||
|
&self.common,
|
||||||
|
pass.config.get_frame_count(frame_count),
|
||||||
|
options,
|
||||||
|
viewport,
|
||||||
|
&original,
|
||||||
|
&source,
|
||||||
|
&out,
|
||||||
|
QuadType::Final,
|
||||||
|
)?;
|
||||||
|
|
||||||
let output_image = viewport.output;
|
let output_image = viewport.output;
|
||||||
let out = RenderTarget::viewport_with_output(output_image, viewport);
|
let out = RenderTarget::viewport_with_output(output_image, viewport);
|
||||||
pass.draw(
|
pass.draw(
|
||||||
|
|
|
@ -15,6 +15,7 @@ use objc2_metal::{
|
||||||
MTLVertexFormat, MTLVertexStepFunction, MTLViewport,
|
MTLVertexFormat, MTLVertexStepFunction, MTLViewport,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use librashader_common::map::FastHashMap;
|
||||||
use objc2::rc::Retained;
|
use objc2::rc::Retained;
|
||||||
use objc2::runtime::ProtocolObject;
|
use objc2::runtime::ProtocolObject;
|
||||||
|
|
||||||
|
@ -23,8 +24,8 @@ pub const VERTEX_BUFFER_INDEX: usize = 4;
|
||||||
|
|
||||||
pub struct MetalGraphicsPipeline {
|
pub struct MetalGraphicsPipeline {
|
||||||
pub layout: PipelineLayoutObjects,
|
pub layout: PipelineLayoutObjects,
|
||||||
render_pipeline: Retained<ProtocolObject<dyn MTLRenderPipelineState>>,
|
render_pipelines:
|
||||||
pub render_pass_format: MTLPixelFormat,
|
FastHashMap<MTLPixelFormat, Retained<ProtocolObject<dyn MTLRenderPipelineState>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PipelineLayoutObjects {
|
pub struct PipelineLayoutObjects {
|
||||||
|
@ -154,20 +155,25 @@ impl MetalGraphicsPipeline {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let layout = PipelineLayoutObjects::new(shader_assembly, device)?;
|
let layout = PipelineLayoutObjects::new(shader_assembly, device)?;
|
||||||
let pipeline = layout.create_pipeline(device, render_pass_format)?;
|
let pipeline = layout.create_pipeline(device, render_pass_format)?;
|
||||||
|
let mut pipelines = FastHashMap::default();
|
||||||
|
pipelines.insert(render_pass_format, pipeline);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
layout,
|
layout,
|
||||||
render_pipeline: pipeline,
|
render_pipelines: pipelines,
|
||||||
render_pass_format,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_format(&self, format: MTLPixelFormat) -> bool {
|
||||||
|
self.render_pipelines.contains_key(&format)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn recompile(
|
pub fn recompile(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &ProtocolObject<dyn MTLDevice>,
|
device: &ProtocolObject<dyn MTLDevice>,
|
||||||
format: MTLPixelFormat,
|
format: MTLPixelFormat,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let render_pipeline = self.layout.create_pipeline(device, format)?;
|
let render_pipeline = self.layout.create_pipeline(device, format)?;
|
||||||
self.render_pipeline = render_pipeline;
|
self.render_pipelines.insert(format, render_pipeline);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +183,14 @@ impl MetalGraphicsPipeline {
|
||||||
buffer: &ProtocolObject<dyn MTLCommandBuffer>,
|
buffer: &ProtocolObject<dyn MTLCommandBuffer>,
|
||||||
) -> Result<Retained<ProtocolObject<dyn MTLRenderCommandEncoder>>> {
|
) -> Result<Retained<ProtocolObject<dyn MTLRenderCommandEncoder>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let Some(pipeline) = self
|
||||||
|
.render_pipelines
|
||||||
|
.get(&output.output.pixelFormat())
|
||||||
|
.or_else(|| self.render_pipelines.values().next())
|
||||||
|
else {
|
||||||
|
panic!("No render available pipeline found");
|
||||||
|
};
|
||||||
|
|
||||||
let descriptor = MTLRenderPassDescriptor::new();
|
let descriptor = MTLRenderPassDescriptor::new();
|
||||||
let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0);
|
let ca = descriptor.colorAttachments().objectAtIndexedSubscript(0);
|
||||||
ca.setLoadAction(MTLLoadAction::DontCare);
|
ca.setLoadAction(MTLLoadAction::DontCare);
|
||||||
|
@ -188,7 +202,7 @@ impl MetalGraphicsPipeline {
|
||||||
.ok_or(FilterChainError::FailedToCreateRenderPass)?;
|
.ok_or(FilterChainError::FailedToCreateRenderPass)?;
|
||||||
|
|
||||||
rpass.setLabel(Some(&*NSString::from_str("librashader rpass")));
|
rpass.setLabel(Some(&*NSString::from_str("librashader rpass")));
|
||||||
rpass.setRenderPipelineState(&self.render_pipeline);
|
rpass.setRenderPipelineState(pipeline);
|
||||||
|
|
||||||
rpass.setScissorRect(MTLScissorRect {
|
rpass.setScissorRect(MTLScissorRect {
|
||||||
x: output.x as usize,
|
x: output.x as usize,
|
||||||
|
|
|
@ -220,7 +220,7 @@ declare_class!(
|
||||||
.expect("Failed to create a pipeline state.");
|
.expect("Failed to create a pipeline state.");
|
||||||
|
|
||||||
let preset =
|
let preset =
|
||||||
ShaderPreset::try_parse("../test/shaders_slang/crt/crt-royale.slangp").unwrap();
|
ShaderPreset::try_parse("../test/shaders_slang/test/feedback.slangp").unwrap();
|
||||||
|
|
||||||
let filter_chain = FilterChainMetal::load_from_preset(
|
let filter_chain = FilterChainMetal::load_from_preset(
|
||||||
preset,
|
preset,
|
||||||
|
|
|
@ -3,4 +3,4 @@ include!("./hello_triangle/main.rs");
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mtl() {
|
fn test_mtl() {
|
||||||
main()
|
main()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue