rt(mtl): implement clear textures

This commit is contained in:
chyyran 2024-02-13 02:29:54 -05:00 committed by Ronny Chan
parent ab31abb3d7
commit bceb0623a3
3 changed files with 44 additions and 22 deletions

View file

@ -27,9 +27,9 @@ array-concat = "0.5.2"
bytemuck = { version = "1.12.3", features = ["derive"] } bytemuck = { version = "1.12.3", features = ["derive"] }
rayon = "1.8.1" rayon = "1.8.1"
#[dependencies.icrate] [dependencies.icrate]
#version = "0.1.0" version = "0.1.0"
#features = ["AppKit", "AppKit_all", "Foundation", "Foundation_all", "MetalKit", "MetalKit_all", "Metal", "Metal_all"] features = ["AppKit", "AppKit_all", "Foundation", "Foundation_all", "MetalKit", "MetalKit_all", "Metal", "Metal_all"]
[[test]] [[test]]
name = "triangle" name = "triangle"
@ -40,7 +40,7 @@ harness = false
features = ["librashader-cache/docsrs"] features = ["librashader-cache/docsrs"]
[target.'cfg(target_vendor="apple")'.dependencies] [target.'cfg(target_vendor="apple")'.dependencies]
icrate = { version = "0.1.0" , features = [ "Metal", "Metal_all" ]} #icrate = { version = "0.1.0" , features = [ "Metal", "Metal_all" ]}
objc2 = { version = "0.5.0", features = ["apple"] } objc2 = { version = "0.5.0", features = ["apple"] }
# #
#[lib] #[lib]

View file

@ -10,8 +10,9 @@ use crate::samplers::SamplerSet;
use crate::texture::{get_texture_size, InputTexture, MetalOutputView, OwnedTexture}; use crate::texture::{get_texture_size, InputTexture, MetalOutputView, OwnedTexture};
use icrate::Foundation::NSString; use icrate::Foundation::NSString;
use icrate::Metal::{ use icrate::Metal::{
MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLPixelFormat, MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLLoadActionClear,
MTLPixelFormatRGBA8Unorm, MTLResource, MTLTexture, MTLPixelFormat, MTLPixelFormatRGBA8Unorm, MTLRenderPassDescriptor, MTLResource,
MTLStoreActionDontCare, MTLStoreActionStore, MTLTexture,
}; };
use librashader_common::{ImageFormat, Size, Viewport}; use librashader_common::{ImageFormat, Size, Viewport};
use librashader_presets::context::VideoDriver; use librashader_presets::context::VideoDriver;
@ -320,22 +321,49 @@ impl FilterChainMetal {
} }
/// Records shader rendering commands to the provided command encoder. /// Records shader rendering commands to the provided command encoder.
///
/// SAFETY: The `MTLCommandBuffer` provided must not have an active encoder.
pub fn frame( pub fn frame(
&mut self, &mut self,
input: &ProtocolObject<dyn MTLTexture>, input: &ProtocolObject<dyn MTLTexture>,
viewport: &Viewport<MetalOutputView>, viewport: &Viewport<MetalOutputView>,
cmd_buffer: &ProtocolObject<dyn MTLCommandBuffer>, cmd: &ProtocolObject<dyn MTLCommandBuffer>,
frame_count: usize, frame_count: usize,
options: Option<&FrameOptionsMetal>, options: Option<&FrameOptionsMetal>,
) -> error::Result<()> { ) -> error::Result<()> {
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
let passes = &mut self.passes[0..max]; let passes = &mut self.passes[0..max];
if let Some(options) = &options { if let Some(options) = &options {
let desc = unsafe {
let desc = MTLRenderPassDescriptor::new();
desc.colorAttachments()
.objectAtIndexedSubscript(0)
.setLoadAction(MTLLoadActionClear);
desc.colorAttachments()
.objectAtIndexedSubscript(0)
.setStoreAction(MTLStoreActionDontCare);
desc
};
let clear_desc = unsafe { MTLRenderPassDescriptor::new() };
if options.clear_history { if options.clear_history {
for history in &mut self.history_framebuffers { for (index, history) in self.history_framebuffers.iter().enumerate() {
history.clear(cmd_buffer); unsafe {
let ca = clear_desc
.colorAttachments()
.objectAtIndexedSubscript(index);
ca.setTexture(Some(&history.texture));
ca.setLoadAction(MTLLoadActionClear);
ca.setStoreAction(MTLStoreActionStore);
}
} }
} }
let clearpass = cmd
.renderCommandEncoderWithDescriptor(&desc)
.ok_or(FilterChainError::FailedToCreateCommandBuffer)?;
clearpass.endEncoding();
} }
if passes.is_empty() { if passes.is_empty() {
return Ok(()); return Ok(());
@ -410,7 +438,7 @@ impl FilterChainMetal {
let out = RenderTarget::identity(target.texture.as_ref()); let out = RenderTarget::identity(target.texture.as_ref());
pass.draw( pass.draw(
&cmd_buffer, &cmd,
index, index,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
@ -423,7 +451,7 @@ impl FilterChainMetal {
)?; )?;
if target.max_miplevels > 1 && !self.disable_mipmaps { if target.max_miplevels > 1 && !self.disable_mipmaps {
target.generate_mipmaps(&cmd_buffer)?; target.generate_mipmaps(&cmd)?;
} }
source = self.common.output_textures[index] source = self.common.output_textures[index]
@ -448,7 +476,7 @@ impl FilterChainMetal {
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(
&cmd_buffer, &cmd,
passes_len - 1, passes_len - 1,
&self.common, &self.common,
pass.config.get_frame_count(frame_count), pass.config.get_frame_count(frame_count),
@ -461,7 +489,7 @@ impl FilterChainMetal {
)?; )?;
} }
self.push_history(&input, &cmd_buffer)?; self.push_history(&input, &cmd)?;
self.common.internal_frame_count = self.common.internal_frame_count.wrapping_add(1); self.common.internal_frame_count = self.common.internal_frame_count.wrapping_add(1);
Ok(()) Ok(())
} }

View file

@ -1,8 +1,9 @@
use crate::error::{FilterChainError, Result}; use crate::error::{FilterChainError, Result};
use crate::select_optimal_pixel_format; use crate::select_optimal_pixel_format;
use icrate::Metal::{ use icrate::Metal::{
MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLDevice, MTLPixelFormat, MTLBlitCommandEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLDevice,
MTLTexture, MTLTextureDescriptor, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead, MTLParallelRenderCommandEncoder, MTLPixelFormat, MTLRenderCommandEncoder, MTLTexture,
MTLTextureDescriptor, MTLTextureUsageRenderTarget, MTLTextureUsageShaderRead,
MTLTextureUsageShaderWrite, MTLTextureUsageShaderWrite,
}; };
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
@ -137,13 +138,6 @@ impl OwnedTexture {
Ok(()) Ok(())
} }
pub fn clear(&self, cmd: &ProtocolObject<dyn MTLCommandBuffer>) {
// let render = cmd.renderCommandEncoder()
// .ok_or(FilterChainError::FailedToCreateCommandBuffer)?;
// render.
// cmd.clear_texture(&self.image, &wgpu::ImageSubresourceRange::default());
}
pub fn generate_mipmaps(&self, cmd: &ProtocolObject<dyn MTLCommandBuffer>) -> Result<()> { pub fn generate_mipmaps(&self, cmd: &ProtocolObject<dyn MTLCommandBuffer>) -> Result<()> {
let mipmapper = cmd let mipmapper = cmd
.blitCommandEncoder() .blitCommandEncoder()