@@ -8,6 +8,7 @@ pub fn all_tests(tests: &mut Vec<GpuTestInitializer>) {
88    tests. extend ( [ 
99        NV12_TEXTURE_CREATION_SAMPLING , 
1010        P010_TEXTURE_CREATION_SAMPLING , 
11+         NV12_TEXTURE_RENDERING , 
1112    ] ) ; 
1213} 
1314
@@ -21,7 +22,7 @@ fn test_planar_texture_creation_sampling(
2122
2223    let  shader = ctx
2324        . device 
24-         . create_shader_module ( wgpu:: include_wgsl!( "planar_texture .wgsl" ) ) ; 
25+         . create_shader_module ( wgpu:: include_wgsl!( "planar_texture_sampling .wgsl" ) ) ; 
2526    let  pipeline = ctx
2627        . device 
2728        . create_render_pipeline ( & wgpu:: RenderPipelineDescriptor  { 
@@ -105,7 +106,112 @@ fn test_planar_texture_creation_sampling(
105106    rpass. set_bind_group ( 0 ,  & bind_group,  & [ ] ) ; 
106107    rpass. draw ( 0 ..4 ,  0 ..1 ) ; 
107108    drop ( rpass) ; 
108-     ctx. queue . submit ( Some ( encoder. finish ( ) ) ) ; 
109+     ctx. queue . submit ( [ encoder. finish ( ) ] ) ; 
110+ } 
111+ 
112+ // Helper function to test rendering onto planar texture. 
113+ fn  test_planar_texture_rendering ( 
114+     ctx :  & TestingContext , 
115+     ( y_view,  y_format) :  ( & wgpu:: TextureView ,  wgpu:: TextureFormat ) , 
116+     ( uv_view,  uv_format) :  ( & wgpu:: TextureView ,  wgpu:: TextureFormat ) , 
117+ )  { 
118+     let  shader = ctx
119+         . device 
120+         . create_shader_module ( wgpu:: include_wgsl!( "planar_texture_rendering.wgsl" ) ) ; 
121+     let  y_pipeline = ctx
122+         . device 
123+         . create_render_pipeline ( & wgpu:: RenderPipelineDescriptor  { 
124+             label :  Some ( "y plane pipeline" ) , 
125+             layout :  None , 
126+             vertex :  wgpu:: VertexState  { 
127+                 module :  & shader, 
128+                 entry_point :  Some ( "vs_main" ) , 
129+                 compilation_options :  Default :: default ( ) , 
130+                 buffers :  & [ ] , 
131+             } , 
132+             fragment :  Some ( wgpu:: FragmentState  { 
133+                 module :  & shader, 
134+                 entry_point :  Some ( "fs_y_main" ) , 
135+                 compilation_options :  Default :: default ( ) , 
136+                 targets :  & [ Some ( y_format. into ( ) ) ] , 
137+             } ) , 
138+             primitive :  wgpu:: PrimitiveState  { 
139+                 topology :  wgpu:: PrimitiveTopology :: TriangleStrip , 
140+                 strip_index_format :  Some ( wgpu:: IndexFormat :: Uint32 ) , 
141+                 ..Default :: default ( ) 
142+             } , 
143+             depth_stencil :  None , 
144+             multisample :  wgpu:: MultisampleState :: default ( ) , 
145+             multiview :  None , 
146+             cache :  None , 
147+         } ) ; 
148+ 
149+     let  uv_pipeline = ctx
150+         . device 
151+         . create_render_pipeline ( & wgpu:: RenderPipelineDescriptor  { 
152+             label :  Some ( "uv plane pipeline" ) , 
153+             layout :  None , 
154+             vertex :  wgpu:: VertexState  { 
155+                 module :  & shader, 
156+                 entry_point :  Some ( "vs_main" ) , 
157+                 compilation_options :  Default :: default ( ) , 
158+                 buffers :  & [ ] , 
159+             } , 
160+             fragment :  Some ( wgpu:: FragmentState  { 
161+                 module :  & shader, 
162+                 entry_point :  Some ( "fs_uv_main" ) , 
163+                 compilation_options :  Default :: default ( ) , 
164+                 targets :  & [ Some ( uv_format. into ( ) ) ] , 
165+             } ) , 
166+             primitive :  wgpu:: PrimitiveState  { 
167+                 topology :  wgpu:: PrimitiveTopology :: TriangleStrip , 
168+                 strip_index_format :  Some ( wgpu:: IndexFormat :: Uint32 ) , 
169+                 ..Default :: default ( ) 
170+             } , 
171+             depth_stencil :  None , 
172+             multisample :  wgpu:: MultisampleState :: default ( ) , 
173+             multiview :  None , 
174+             cache :  None , 
175+         } ) ; 
176+ 
177+     let  mut  encoder = ctx
178+         . device 
179+         . create_command_encoder ( & wgpu:: CommandEncoderDescriptor :: default ( ) ) ; 
180+ 
181+     { 
182+         let  mut  rpass = encoder. begin_render_pass ( & wgpu:: RenderPassDescriptor  { 
183+             label :  None , 
184+             color_attachments :  & [ Some ( wgpu:: RenderPassColorAttachment  { 
185+                 ops :  wgpu:: Operations :: default ( ) , 
186+                 resolve_target :  None , 
187+                 view :  y_view, 
188+                 depth_slice :  None , 
189+             } ) ] , 
190+             depth_stencil_attachment :  None , 
191+             timestamp_writes :  None , 
192+             occlusion_query_set :  None , 
193+         } ) ; 
194+         rpass. set_pipeline ( & y_pipeline) ; 
195+         rpass. draw ( 0 ..3 ,  0 ..1 ) ; 
196+     } 
197+     { 
198+         let  mut  rpass = encoder. begin_render_pass ( & wgpu:: RenderPassDescriptor  { 
199+             label :  None , 
200+             color_attachments :  & [ Some ( wgpu:: RenderPassColorAttachment  { 
201+                 ops :  wgpu:: Operations :: default ( ) , 
202+                 resolve_target :  None , 
203+                 view :  uv_view, 
204+                 depth_slice :  None , 
205+             } ) ] , 
206+             depth_stencil_attachment :  None , 
207+             timestamp_writes :  None , 
208+             occlusion_query_set :  None , 
209+         } ) ; 
210+         rpass. set_pipeline ( & uv_pipeline) ; 
211+         rpass. draw ( 0 ..3 ,  0 ..1 ) ; 
212+     } 
213+ 
214+     ctx. queue . submit ( [ encoder. finish ( ) ] ) ; 
109215} 
110216
111217/// Ensures that creation and sampling of an NV12 format texture works as 
@@ -187,3 +293,45 @@ static P010_TEXTURE_CREATION_SAMPLING: GpuTestConfiguration = GpuTestConfigurati
187293
188294        test_planar_texture_creation_sampling ( & ctx,  & y_view,  & uv_view) ; 
189295    } ) ; 
296+ 
297+ /// Ensures that rendering on to NV12 format texture works as expected. 
298+ #[ gpu_test]  
299+ static  NV12_TEXTURE_RENDERING :  GpuTestConfiguration  = GpuTestConfiguration :: new ( ) 
300+     . parameters ( 
301+         TestParameters :: default ( ) 
302+             . features ( wgpu:: Features :: TEXTURE_FORMAT_NV12 ) 
303+             . enable_noop ( ) , 
304+     ) 
305+     . run_sync ( |ctx| { 
306+         let  size = wgpu:: Extent3d  { 
307+             width :  256 , 
308+             height :  256 , 
309+             depth_or_array_layers :  1 , 
310+         } ; 
311+         let  tex = ctx. device . create_texture ( & wgpu:: TextureDescriptor  { 
312+             label :  None , 
313+             dimension :  wgpu:: TextureDimension :: D2 , 
314+             size, 
315+             format :  wgpu:: TextureFormat :: NV12 , 
316+             usage :  wgpu:: TextureUsages :: RENDER_ATTACHMENT , 
317+             mip_level_count :  1 , 
318+             sample_count :  1 , 
319+             view_formats :  & [ ] , 
320+         } ) ; 
321+         let  y_view = tex. create_view ( & wgpu:: TextureViewDescriptor  { 
322+             format :  Some ( wgpu:: TextureFormat :: R8Unorm ) , 
323+             aspect :  wgpu:: TextureAspect :: Plane0 , 
324+             ..Default :: default ( ) 
325+         } ) ; 
326+         let  uv_view = tex. create_view ( & wgpu:: TextureViewDescriptor  { 
327+             format :  Some ( wgpu:: TextureFormat :: Rg8Unorm ) , 
328+             aspect :  wgpu:: TextureAspect :: Plane1 , 
329+             ..Default :: default ( ) 
330+         } ) ; 
331+ 
332+         test_planar_texture_rendering ( 
333+             & ctx, 
334+             ( & y_view,  wgpu:: TextureFormat :: R8Unorm ) , 
335+             ( & uv_view,  wgpu:: TextureFormat :: Rg8Unorm ) , 
336+         ) ; 
337+     } ) ; 
0 commit comments