From 8f0239c9862c0465164210eb51158a274f60c93b Mon Sep 17 00:00:00 2001 From: mitchmindtree Date: Mon, 2 Mar 2020 18:56:08 +0100 Subject: [PATCH] Add manual msaa resolve to TextureReshaper. Solves validation error. Previously a validation error was occurring due to passing a sampled texture to the bind group without declaring that the texture was multisampled in the fragment shader. This adds some new multisampled shaders that correctly declare the texture and do the multisampling resolve manually. Dedicated shaders have been added for common sample counts with unrolled loops to avoid having the shader deal with conditions based on uniform data. A fallback shader is provided for all other sample counts. Closes #462. --- examples/capture_hi_res.rs | 3 +- src/frame/mod.rs | 4 +- src/wgpu/texture/capturer.rs | 33 +----- src/wgpu/texture/reshaper/mod.rs | 108 +++++++++++++++--- .../texture/reshaper/shaders/frag_msaa.spv | Bin 0 -> 2228 bytes .../texture/reshaper/shaders/frag_msaa16.spv | Bin 0 -> 4296 bytes .../texture/reshaper/shaders/frag_msaa2.spv | Bin 0 -> 1832 bytes .../texture/reshaper/shaders/frag_msaa4.spv | Bin 0 -> 2184 bytes .../texture/reshaper/shaders/frag_msaa8.spv | Bin 0 -> 2888 bytes .../texture/reshaper/shaders/shader_msaa.frag | 34 ++++++ .../reshaper/shaders/shader_msaa16.frag | 45 ++++++++ .../reshaper/shaders/shader_msaa2.frag | 30 +++++ .../reshaper/shaders/shader_msaa4.frag | 32 ++++++ .../reshaper/shaders/shader_msaa8.frag | 36 ++++++ 14 files changed, 274 insertions(+), 51 deletions(-) create mode 100644 src/wgpu/texture/reshaper/shaders/frag_msaa.spv create mode 100644 src/wgpu/texture/reshaper/shaders/frag_msaa16.spv create mode 100644 src/wgpu/texture/reshaper/shaders/frag_msaa2.spv create mode 100644 src/wgpu/texture/reshaper/shaders/frag_msaa4.spv create mode 100644 src/wgpu/texture/reshaper/shaders/frag_msaa8.spv create mode 100644 src/wgpu/texture/reshaper/shaders/shader_msaa.frag create mode 100644 src/wgpu/texture/reshaper/shaders/shader_msaa16.frag create mode 100644 src/wgpu/texture/reshaper/shaders/shader_msaa2.frag create mode 100644 src/wgpu/texture/reshaper/shaders/shader_msaa4.frag create mode 100644 src/wgpu/texture/reshaper/shaders/shader_msaa8.frag diff --git a/examples/capture_hi_res.rs b/examples/capture_hi_res.rs index ef670543a..596aea3b0 100644 --- a/examples/capture_hi_res.rs +++ b/examples/capture_hi_res.rs @@ -62,12 +62,11 @@ fn model(app: &App) -> Model { // Create the texture reshaper. let texture_view = texture.create_default_view(); - let src_multisampled = texture.sample_count() > 1; let dst_format = Frame::TEXTURE_FORMAT; let texture_reshaper = wgpu::TextureReshaper::new( device, &texture_view, - src_multisampled, + sample_count, sample_count, dst_format, ); diff --git a/src/frame/mod.rs b/src/frame/mod.rs index 5cd8775a2..35f021727 100644 --- a/src/frame/mod.rs +++ b/src/frame/mod.rs @@ -278,12 +278,12 @@ impl RenderData { ) -> Self { let intermediary_lin_srgba = create_intermediary_lin_srgba(device, swap_chain_dims, msaa_samples); + let src_sample_count = 1; let swap_chain_sample_count = 1; - let src_multisampled = false; let texture_reshaper = wgpu::TextureReshaper::new( device, &intermediary_lin_srgba.texture_view, - src_multisampled, + src_sample_count, swap_chain_sample_count, swap_chain_format, ); diff --git a/src/wgpu/texture/capturer.rs b/src/wgpu/texture/capturer.rs index 7731f3314..a6fd35106 100644 --- a/src/wgpu/texture/capturer.rs +++ b/src/wgpu/texture/capturer.rs @@ -41,7 +41,6 @@ pub struct Rgba8AsyncMapping<'a> { struct ConverterDataPair { src_descriptor: wgpu::TextureDescriptor, reshaper: wgpu::TextureReshaper, - resolved_src_texture: Option, dst_texture: wgpu::Texture, } @@ -103,13 +102,6 @@ impl Capturer { *converter_data_pair = create_converter_data_pair(device, src_texture); } - // If the src is multisampled, add the resolve command. - if let Some(ref resolved_src_texture) = converter_data_pair.resolved_src_texture { - let src_view = src_texture.create_default_view(); - let resolved_view = resolved_src_texture.create_default_view(); - wgpu::resolve_texture(&src_view, &resolved_view, encoder); - } - // Encode the texture format conversion. let dst_view = converter_data_pair.dst_texture.create_default_view(); converter_data_pair @@ -252,17 +244,6 @@ fn create_converter_data_pair( device: &wgpu::Device, src_texture: &wgpu::Texture, ) -> ConverterDataPair { - // If the src is multisampled, it must be resolved first. - let resolved_src_texture = if src_texture.sample_count() > 1 { - let texture = wgpu::TextureBuilder::from(src_texture.descriptor_cloned()) - .sample_count(1) - .usage(wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED) - .build(device); - Some(texture) - } else { - None - }; - // Create the destination format texture. let dst_texture = wgpu::TextureBuilder::from(src_texture.descriptor_cloned()) .sample_count(1) @@ -270,20 +251,15 @@ fn create_converter_data_pair( .usage(wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::COPY_SRC) .build(device); - // If we have a resolved texture, use it as the conversion src. Otherwise use `src_texture`. - let src_view = resolved_src_texture - .as_ref() - .map(|tex| tex.create_default_view()) - .unwrap_or_else(|| src_texture.create_default_view()); - // Create the converter. - let dst_format = dst_texture.format(); - let src_multisampled = src_texture.sample_count() > 1; + let src_sample_count = src_texture.sample_count(); + let src_view = src_texture.create_default_view(); let dst_sample_count = 1; + let dst_format = dst_texture.format(); let reshaper = wgpu::TextureReshaper::new( device, &src_view, - src_multisampled, + src_sample_count, dst_sample_count, dst_format, ); @@ -294,7 +270,6 @@ fn create_converter_data_pair( ConverterDataPair { src_descriptor, reshaper, - resolved_src_texture, dst_texture, } } diff --git a/src/wgpu/texture/reshaper/mod.rs b/src/wgpu/texture/reshaper/mod.rs index 160094f5f..ec682688a 100644 --- a/src/wgpu/texture/reshaper/mod.rs +++ b/src/wgpu/texture/reshaper/mod.rs @@ -14,15 +14,28 @@ pub struct Reshaper { bind_group: wgpu::BindGroup, render_pipeline: wgpu::RenderPipeline, sampler: wgpu::Sampler, + uniform_buffer: Option, vertex_buffer: wgpu::Buffer, } +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] +struct Vertex { + pub position: [f32; 2], +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct Uniforms { + sample_count: u32, +} + impl Reshaper { /// Construct a new `Reshaper`. pub fn new( device: &wgpu::Device, src_texture: &wgpu::TextureView, - src_multisampled: bool, + src_sample_count: u32, dst_sample_count: u32, dst_format: wgpu::TextureFormat, ) -> Self { @@ -31,16 +44,23 @@ impl Reshaper { let vs_spirv = wgpu::read_spirv(std::io::Cursor::new(&vs[..])) .expect("failed to read hard-coded SPIRV"); let vs_mod = device.create_shader_module(&vs_spirv); - let fs = include_bytes!("shaders/frag.spv"); - let fs_spirv = wgpu::read_spirv(std::io::Cursor::new(&fs[..])) - .expect("failed to read hard-coded SPIRV"); + let fs = match src_sample_count { + 1 => &include_bytes!("shaders/frag.spv")[..], + 2 => &include_bytes!("shaders/frag_msaa2.spv")[..], + 4 => &include_bytes!("shaders/frag_msaa4.spv")[..], + 8 => &include_bytes!("shaders/frag_msaa8.spv")[..], + 16 => &include_bytes!("shaders/frag_msaa16.spv")[..], + _ => &include_bytes!("shaders/frag_msaa.spv")[..], + }; + let fs_spirv = + wgpu::read_spirv(std::io::Cursor::new(fs)).expect("failed to read hard-coded SPIRV"); let fs_mod = device.create_shader_module(&fs_spirv); // Create the sampler for sampling from the source texture. let sampler = wgpu::SamplerBuilder::new().build(device); // Create the render pipeline. - let bind_group_layout = bind_group_layout(device, src_multisampled); + let bind_group_layout = bind_group_layout(device, src_sample_count); let pipeline_layout = pipeline_layout(device, &bind_group_layout); let render_pipeline = render_pipeline( device, @@ -51,8 +71,29 @@ impl Reshaper { dst_format, ); + // Create the uniform buffer to pass the sample count if we don't have an unrolled resolve + // fragment shader for it. + let uniform_buffer = match unrolled_sample_count(src_sample_count) { + true => None, + false => { + let uniforms = Uniforms { + sample_count: src_sample_count, + }; + let buffer = device + .create_buffer_mapped(1, wgpu::BufferUsage::UNIFORM) + .fill_from_slice(&[uniforms]); + Some(buffer) + } + }; + // Create the bind group. - let bind_group = bind_group(device, &bind_group_layout, src_texture, &sampler); + let bind_group = bind_group( + device, + &bind_group_layout, + src_texture, + &sampler, + uniform_buffer.as_ref(), + ); // Create the vertex buffer. let vertex_buffer = device @@ -66,6 +107,7 @@ impl Reshaper { bind_group, render_pipeline, sampler, + uniform_buffer, vertex_buffer, } } @@ -79,6 +121,7 @@ impl Reshaper { ) { let vertex_range = 0..VERTICES.len() as u32; let instance_range = 0..1; + let render_pass_desc = wgpu::RenderPassDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { attachment: dst_texture, @@ -97,12 +140,6 @@ impl Reshaper { } } -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] -struct Vertex { - pub position: [f32; 2], -} - const VERTICES: [Vertex; 4] = [ Vertex { position: [-1.0, -1.0], @@ -118,6 +155,14 @@ const VERTICES: [Vertex; 4] = [ }, ]; +// We provide pre-prepared fragment shaders with unrolled resolves for common sample counts. +fn unrolled_sample_count(sample_count: u32) -> bool { + match sample_count { + 1 | 2 | 4 | 8 | 16 => true, + _ => false, + } +} + fn vertex_attrs() -> [wgpu::VertexAttributeDescriptor; 1] { [wgpu::VertexAttributeDescriptor { format: wgpu::VertexFormat::Float2, @@ -126,12 +171,12 @@ fn vertex_attrs() -> [wgpu::VertexAttributeDescriptor; 1] { }] } -fn bind_group_layout(device: &wgpu::Device, src_multisampled: bool) -> wgpu::BindGroupLayout { +fn bind_group_layout(device: &wgpu::Device, src_sample_count: u32) -> wgpu::BindGroupLayout { let texture_binding = wgpu::BindGroupLayoutBinding { binding: 0, visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::SampledTexture { - multisampled: src_multisampled, + multisampled: src_sample_count > 1, dimension: wgpu::TextureViewDimension::D2, }, }; @@ -140,8 +185,21 @@ fn bind_group_layout(device: &wgpu::Device, src_multisampled: bool) -> wgpu::Bin visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler, }; - let bindings = &[texture_binding, sampler_binding]; - let desc = wgpu::BindGroupLayoutDescriptor { bindings }; + let uniforms_binding = match unrolled_sample_count(src_sample_count) { + true => None, + false => Some(wgpu::BindGroupLayoutBinding { + binding: 2, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + }), + }; + let bindings = match uniforms_binding { + None => vec![texture_binding, sampler_binding], + Some(uniforms_binding) => vec![texture_binding, sampler_binding, uniforms_binding], + }; + let desc = wgpu::BindGroupLayoutDescriptor { + bindings: &bindings, + }; device.create_bind_group_layout(&desc) } @@ -150,6 +208,7 @@ fn bind_group( layout: &wgpu::BindGroupLayout, texture: &wgpu::TextureView, sampler: &wgpu::Sampler, + uniform_buffer: Option<&wgpu::Buffer>, ) -> wgpu::BindGroup { let texture_binding = wgpu::Binding { binding: 0, @@ -159,8 +218,21 @@ fn bind_group( binding: 1, resource: wgpu::BindingResource::Sampler(&sampler), }; - let bindings = &[texture_binding, sampler_binding]; - let desc = wgpu::BindGroupDescriptor { layout, bindings }; + let uniforms_binding = uniform_buffer.map(|buffer| wgpu::Binding { + binding: 2, + resource: wgpu::BindingResource::Buffer { + buffer, + range: 0..std::mem::size_of::() as wgpu::BufferAddress, + }, + }); + let bindings = match uniforms_binding { + None => vec![texture_binding, sampler_binding], + Some(uniforms_binding) => vec![texture_binding, sampler_binding, uniforms_binding], + }; + let desc = wgpu::BindGroupDescriptor { + layout, + bindings: &bindings, + }; device.create_bind_group(&desc) } diff --git a/src/wgpu/texture/reshaper/shaders/frag_msaa.spv b/src/wgpu/texture/reshaper/shaders/frag_msaa.spv new file mode 100644 index 0000000000000000000000000000000000000000..157e2e6c7a1dd2cf547219190ba38d4415a6eb1c GIT binary patch literal 2228 zcmZ9NXHQf?6ov9IsOKJlu;8C zpXc704j+`wxnP&iQvN_jW z%zR4WtUj6E8b*;<>&tZn(`e6Z^`)#2O1*0=Yun=$Un+VFoT=fYt-^g zd)#CtyPBJs?KzA4+U~ai{VT{G;JQK0(OeC^QP!B7oU_*7o{IUjtA&00OZmEpGOn84 zR-R)sIojYVpapbed!KUpR{+jBEJlQXc-bf(?t_9$;H?Fx`H ze>LjHqCm)tLyGE!gf-|yG+X*+wr z&7$phm~8$14wLO{{05V4yx*Yq5c#~*4&a;6_C0I_-u+{`=t6D+`p8ekn9Y%Yi*2qg zKyH{5*st~|@z&b`aOOLKd=uOI+7&rts_1(_1*8~#dV%~`e6;rh} zhjY?SeH=u$j{_j}aR^;L^>G+oF7od-|oTdLC^pQ8-`;=4nE`7`D-lK2#H}B;<(s!f$$t*4+hk(odVWj)YRQD3P zIX>a<8y*32p53>74O{`%Fh-y2K>j;EHRKI20_6YTqkREb-+JoC`p#~G;yb&AU3_P^ zqmR5X&SDIB{?zjwbbC(k@GiP>Z}9f}x(DQp8v*(o>)tqUeqZQa`+nq%Nwbx6Ue3<` zm8tdvbZdVmz76>h$W4HBA9BU}a1LpnkI?_0=VLhe1$y*tJppp5=cnlQJRZ;Y3|*fh ezQyxAhu2@9bRM~s>lM1W+!h_S?~`PqKjPs literal 0 HcmV?d00001 diff --git a/src/wgpu/texture/reshaper/shaders/frag_msaa16.spv b/src/wgpu/texture/reshaper/shaders/frag_msaa16.spv new file mode 100644 index 0000000000000000000000000000000000000000..51f53f3803621b650fa0dc836deb40ba0f65b34c GIT binary patch literal 4296 zcmYk9`Ik?19L8_PpcG07EngHBsf3j1sx&Qh!JHmvI)87LLm?mT?O|rq@IoH<9!94hS%dK$Bk(>$GrJA^0QP3iaMm7FX#_U>}^`!^kS<54MT5AJuEC zd-55`8TWJyT1IoPrEf51o_|cOT@&Yc}KqGbs`A1!PK!^q}PTqJ8fk_q_X#MaGZ!X3yz8C1`}(%?j*)MI8H*l z&OA6Kqs`^;edyzw{>3j__*2n#7I0ra%PEWqm!UJ?<#;pK1fN;(EktL&EAW}`O1vHO;9G>wd{^V`1>ZGjGkYcD z-?hPaEjsgEhc|Og@RVm(WICAOTY=7eEAeKo2|lynTZPVi zo%qbR8gIuu_-;dIzHYp|;9G+>vsW@*Oz_=~&U|;^&0G_FX2EwSI`j45Gv8Xg9rNH@ zht7O=;q3+A-Dop=C9|FhzI)J_Zv)=UHNj^Vd>hf3ZxcTA-HW$l9(?zqGv5}xz2Lha zZDy}zHZ#HZ06OzMh&OXh@RhX0K$nGQsya zI`ch&H*-z!nFZgI=*;&NKJz_|w__fB&!98kvv_;K_Z-^HUde1{g70~B=6eBe=9=I$ z3%(c8neQch=6e}$$2|C6L1(^K@%Do6HME(%lG(uo-|Ohi_Xgg~HNj^Vd~c#N-&^?1 z_cq>+dGNi1&V29U?FHX^Xft~yvy%zF_tBZ}1H74Qg3m1YK164}kMNoAW4s;n;QIuf z`98(l3%<|LX7);E7ZZG+qch(Zcr(`opIPvIiOzgq;WOXYcsu67_YFGpeT%mjeBYtX z?3K)JCiuQbXTBfsX08c7v*7y?o%w#kXTG2DcFcos4?6Sxg0~lZzoO0TmCRly_LJXzpeiF*q>;#eN6PtqW?GAzQ^{n*Z;@=#AY!61Mgfod;kCd literal 0 HcmV?d00001 diff --git a/src/wgpu/texture/reshaper/shaders/frag_msaa2.spv b/src/wgpu/texture/reshaper/shaders/frag_msaa2.spv new file mode 100644 index 0000000000000000000000000000000000000000..9e47519b5f1e7fb58fa8df4f29f7a725f0c9b6a7 GIT binary patch literal 1832 zcmYk6%T8256h%v#1{4Jp0Rfc;R8$aOfGG0vg(4z}iBm!VBMHz37@#u;PW>pq%87|< z-L8||N>10=yY{Kt^|)PW8f{JKOlnPSX(Kh-#nc3olKmt4_S90~m9FxHE15ej^wnZr=h&{-k9Lk5>)gtk?^$!7ey=2Qo@u!4`hNYW z&@>m`zc7o;3gh}1A#8z%8?eB7E02pEXRF0{js7}ev);1_+|8+YF2ltMr6TV^(*jo` zoTCry8Oo`xf!pZij9zNb6?{tloMbz>*xG33fvrEE2h`4G>^^M+tkOxZuB%{Dfz^rK zpKXwJyXl=nZ6AI3bPxRn&kt=pSGlXq|5&0*CTshQw*3SuB;Me4OiMduCOli@zK9KlTIH%sl-m}~c zuhl*3%O>|1rb@5YyY&6*RqQ$Xw#(Re99X^YII#Ql4U6Zg_dYrZ?^EnuULw4=&#c-_ zf0`3UZ!4ugM^&-=^CEbRYJZF_N=dE&KmD-gs2fwqh^$l z|Aj_;gRoBiFwc84^ZM{y#Np#Mxjx2-@NtJ+K78CImkS@`6`3|l1?q-Sd-8}`D@9tUF$Xnz5 zbA)roUCxuM+ho)?xj@LNTOxeh);hLG=;0?`#Y=>oHQ`S#{4JB0{k;H}{k;UMkq>{b z$jkoTfYpV+6>>RsON8HA_NQ;L=?qYK*30Yv;h|AN*8YZQT{47CVt=R zcay5*cHML8+^SPUzozxQEh()_EvYqqNR75Vt%pg;{v7@0w4uPGW0PY8E30z@7Y5I$ z+?JZ`im^6kXeKwl%q}d+SBV*-9i2Q2ku@=EN`F|O0-NhAFdG?LonM==lEE!FVC$s);U^gzLlEO^b48Dc?RJ=))(u` zg{Hai{)t&+Mj6*f4`B=3-GBwwTRtv!oUIn)Rr-U3&H5Soz#W{5=h9uAP%83WXg0uA z3Fp`i_6+6JR>7_Gaz-b$n+iUqy`1D`a4Or~SGtg)3=@7Xds|Z*a4%xd*|(o#-+5s5zVpDIgKu1XoqF$U z8{vJ6z3Ux>_d3O@9rQa1HS%+1&90LF40f(gLT(tx`V)^(ufKhSocHY-p67l-z7F<$ z4wRfV-fa(2C89=6FCqU6jrcHOo%~Wc?~#(%hvy;=AIHe`(MN=j@}_&7;k zC8EZ4`w98*af;kJ`S3A7F0T*oLmX@R;nZ8;v*cSHxp(I~wbr}4 zMC5mO8JyqUl~N;bjq_h6oHOq7I=Q-OMtzgRgq*q>;oG;?u^WUQe&SVJBjl_Je{$h( zggp0m6P)|I1y&;;{%(`!{_cX+g}+g9IdwI{|6=&NN1pq;50UHUnmqUS1}tYy_>&9$J972E%lGh}T+Z)Z=;cB`ORnCr8G7+Q IzND9k|NFjr*Z=?k literal 0 HcmV?d00001 diff --git a/src/wgpu/texture/reshaper/shaders/frag_msaa8.spv b/src/wgpu/texture/reshaper/shaders/frag_msaa8.spv new file mode 100644 index 0000000000000000000000000000000000000000..035053bff3cec03d70fc3d1e6adb3c6cd4d511ab GIT binary patch literal 2888 zcmYk8YjYJv6h&K-%R>~<@CNk;6i^^20wPElM2wG!2#UNzNP=8QaxsY-UJ3|)07dWSt+lSWo3E!r}VBj$`X`P9QQM>EK6%XGJ0-w zXntXG=)l1bb*?IX4)xq>R_F&?Gvl3E^)~g4T7yrWjX-^@TFSp{&_d1r7Rn0d7N!=* z<~#SNfGB#>wWq(%ev?&HMwmCpHp(mbV2{?^YOB~$(*P02vM;q>adTnNx z)r|Vq)JmzjKDqbjwS|2L7+pi}2FA$gJ#4CV{&4MX_~st1@5wVTXWY{}U^A+_m%L4> zx&B~-?TPhvHkxPjG1xiZE&T@=&7-d0xkHrK9%j@(q11Be^{hXmyn>$snGt`>wo6`Cgo7*8#@0lpgiTre|HF z--5f=dP;4W#O9Nqpx=C3C^g>~_wbyyQtDl}=kr#h+2gyhjcQZTqh~v%{v40|UCKW7 z*=F7M8r>Y8i#&4d0-Iwe6*=Aqt4EFxz-p0WH@HnjkNfVS)Fa1Uuzl*0V+gEn4xfiS z_VkC>Y{5SQ>p8=Hd6xSrJ?i%R{M5ugJKuAAeRhYb{Omr3=Vy1M@u=J5`bR0(jAwZa ztZ$52-^pQ0O^$oCaE=ldG2W>4f(i+taJbG~okIo~K;k9y?$4xICS57!s@&VbeQRn%!J z^8EnL`Od=C?1_A8k?$Nh=lcQB3MmdMfqD7`7VKTzRPem zdm^7&XB~@ob!#t^+moLU^RUeb)AZQ6X2Y060T-X&zyhwF=c3t%;U6*WgizTdz(-|uiWdm^7&XGk0IOlr^*BAL7 zfz|X?)B`H={Rz(b{(`I76ZzD_{{*c6Me}>~6s-1`3cp(TpM&)~_l!~glK%t_Q~v|& CYp+@W literal 0 HcmV?d00001 diff --git a/src/wgpu/texture/reshaper/shaders/shader_msaa.frag b/src/wgpu/texture/reshaper/shaders/shader_msaa.frag new file mode 100644 index 000000000..c2dc0d4f9 --- /dev/null +++ b/src/wgpu/texture/reshaper/shaders/shader_msaa.frag @@ -0,0 +1,34 @@ +// NOTE: This shader requires being manually compiled to SPIR-V in order to +// avoid having downstream users require building shaderc and compiling the +// shader themselves. If you update this shader, be sure to also re-compile it +// and update `frag_msaa.spv`. You can do so using `glslangValidator` with the +// following command: `glslangValidator -V -o frag_msaa.spv shader_msaa.frag` + +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform texture2DMS tex; +layout(set = 0, binding = 1) uniform sampler tex_sampler; +layout(set = 0, binding = 2) uniform Data { + uint sample_count; +} uniforms; + +void main() { + // Get the integer tex coordinates. + ivec2 tex_size = textureSize(sampler2DMS(tex, tex_sampler)); + int tex_x = int(tex_size.x * tex_coords.x); + int tex_y = int(tex_size.y * tex_coords.y); + ivec2 itex_coords = ivec2(tex_x, tex_y); + + // Perform the resolve. + vec4 color = vec4(0); + for (int i = 0; i < uniforms.sample_count; i++) { + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, i); + } + color /= float(uniforms.sample_count); + + // Assign the resolved color to the output. + f_color = color; +} diff --git a/src/wgpu/texture/reshaper/shaders/shader_msaa16.frag b/src/wgpu/texture/reshaper/shaders/shader_msaa16.frag new file mode 100644 index 000000000..6991e39d1 --- /dev/null +++ b/src/wgpu/texture/reshaper/shaders/shader_msaa16.frag @@ -0,0 +1,45 @@ +// NOTE: This shader requires being manually compiled to SPIR-V in order to +// avoid having downstream users require building shaderc and compiling the +// shader themselves. If you update this shader, be sure to also re-compile it +// and update `frag_msaa16.spv`. You can do so using `glslangValidator` with +// the following command: +// `glslangValidator -V -o frag_msaa16.spv shader_msaa16.frag` + +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform texture2DMS tex; +layout(set = 0, binding = 1) uniform sampler tex_sampler; + +void main() { + // Get the integer tex coordinates. + ivec2 tex_size = textureSize(sampler2DMS(tex, tex_sampler)); + int tex_x = int(tex_size.x * tex_coords.x); + int tex_y = int(tex_size.y * tex_coords.y); + ivec2 itex_coords = ivec2(tex_x, tex_y); + + // Manually unroll the resolve. The less conditions the better! + vec4 color = vec4(0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 1); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 2); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 3); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 4); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 5); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 6); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 7); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 8); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 9); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 10); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 11); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 12); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 13); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 14); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 15); + color *= 0.0625; + + // Assign the resolved color to the output. + f_color = color; +} diff --git a/src/wgpu/texture/reshaper/shaders/shader_msaa2.frag b/src/wgpu/texture/reshaper/shaders/shader_msaa2.frag new file mode 100644 index 000000000..130b62df6 --- /dev/null +++ b/src/wgpu/texture/reshaper/shaders/shader_msaa2.frag @@ -0,0 +1,30 @@ +// NOTE: This shader requires being manually compiled to SPIR-V in order to +// avoid having downstream users require building shaderc and compiling the +// shader themselves. If you update this shader, be sure to also re-compile it +// and update `frag_msaa2.spv`. You can do so using `glslangValidator` with the +// following command: `glslangValidator -V -o frag_msaa2.spv shader_msaa2.frag` + +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform texture2DMS tex; +layout(set = 0, binding = 1) uniform sampler tex_sampler; + +void main() { + // Get the integer tex coordinates. + ivec2 tex_size = textureSize(sampler2DMS(tex, tex_sampler)); + int tex_x = int(tex_size.x * tex_coords.x); + int tex_y = int(tex_size.y * tex_coords.y); + ivec2 itex_coords = ivec2(tex_x, tex_y); + + // Manually unroll the resolve. The less conditions the better! + vec4 color = vec4(0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 1); + color *= 0.5; + + // Assign the resolved color to the output. + f_color = color; +} diff --git a/src/wgpu/texture/reshaper/shaders/shader_msaa4.frag b/src/wgpu/texture/reshaper/shaders/shader_msaa4.frag new file mode 100644 index 000000000..f1f8204a9 --- /dev/null +++ b/src/wgpu/texture/reshaper/shaders/shader_msaa4.frag @@ -0,0 +1,32 @@ +// NOTE: This shader requires being manually compiled to SPIR-V in order to +// avoid having downstream users require building shaderc and compiling the +// shader themselves. If you update this shader, be sure to also re-compile it +// and update `frag_msaa4.spv`. You can do so using `glslangValidator` with the +// following command: `glslangValidator -V -o frag_msaa4.spv shader_msaa4.frag` + +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform texture2DMS tex; +layout(set = 0, binding = 1) uniform sampler tex_sampler; + +void main() { + // Get the integer tex coordinates. + ivec2 tex_size = textureSize(sampler2DMS(tex, tex_sampler)); + int tex_x = int(tex_size.x * tex_coords.x); + int tex_y = int(tex_size.y * tex_coords.y); + ivec2 itex_coords = ivec2(tex_x, tex_y); + + // Manually unroll the resolve. The less conditions the better! + vec4 color = vec4(0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 1); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 2); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 3); + color *= 0.25; + + // Assign the resolved color to the output. + f_color = color; +} diff --git a/src/wgpu/texture/reshaper/shaders/shader_msaa8.frag b/src/wgpu/texture/reshaper/shaders/shader_msaa8.frag new file mode 100644 index 000000000..7f81c0b11 --- /dev/null +++ b/src/wgpu/texture/reshaper/shaders/shader_msaa8.frag @@ -0,0 +1,36 @@ +// NOTE: This shader requires being manually compiled to SPIR-V in order to +// avoid having downstream users require building shaderc and compiling the +// shader themselves. If you update this shader, be sure to also re-compile it +// and update `frag_msaa8.spv`. You can do so using `glslangValidator` with the +// following command: `glslangValidator -V -o frag_msaa8.spv shader_msaa8.frag` + +#version 450 + +layout(location = 0) in vec2 tex_coords; +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform texture2DMS tex; +layout(set = 0, binding = 1) uniform sampler tex_sampler; + +void main() { + // Get the integer tex coordinates. + ivec2 tex_size = textureSize(sampler2DMS(tex, tex_sampler)); + int tex_x = int(tex_size.x * tex_coords.x); + int tex_y = int(tex_size.y * tex_coords.y); + ivec2 itex_coords = ivec2(tex_x, tex_y); + + // Manually unroll the resolve. The less conditions the better! + vec4 color = vec4(0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 0); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 1); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 2); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 3); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 4); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 5); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 6); + color += texelFetch(sampler2DMS(tex, tex_sampler), itex_coords, 7); + color *= 0.125; + + // Assign the resolved color to the output. + f_color = color; +}