1
1
use crate :: Context ;
2
- use crate :: shader_runtime:: { FULLSCREEN_VERTEX_SHADER_NAME , ShaderRuntime , Shaders } ;
2
+ use crate :: shader_runtime:: { FULLSCREEN_VERTEX_SHADER_NAME , ShaderRuntime } ;
3
3
use bytemuck:: NoUninit ;
4
4
use futures:: lock:: Mutex ;
5
5
use graphene_core:: raster_types:: { GPU , Raster } ;
@@ -27,24 +27,33 @@ impl PerPixelAdjustShaderRuntime {
27
27
}
28
28
29
29
impl ShaderRuntime {
30
- pub async fn run_per_pixel_adjust < T : NoUninit > ( & self , shaders : & Shaders < ' _ > , textures : Table < Raster < GPU > > , args : & T ) -> Table < Raster < GPU > > {
30
+ pub async fn run_per_pixel_adjust < T : NoUninit > ( & self , shaders : & Shaders < ' _ > , textures : Table < Raster < GPU > > , args : Option < & T > ) -> Table < Raster < GPU > > {
31
31
let mut cache = self . per_pixel_adjust . pipeline_cache . lock ( ) . await ;
32
32
let pipeline = cache
33
33
. entry ( shaders. fragment_shader_name . to_owned ( ) )
34
34
. or_insert_with ( || PerPixelAdjustGraphicsPipeline :: new ( & self . context , & shaders) ) ;
35
35
36
- let device = & self . context . device ;
37
- let arg_buffer = device. create_buffer_init ( & BufferInitDescriptor {
38
- label : Some ( & format ! ( "{} arg buffer" , pipeline. name. as_str( ) ) ) ,
39
- usage : BufferUsages :: STORAGE ,
40
- contents : bytemuck:: bytes_of ( args) ,
36
+ let arg_buffer = args. map ( |args| {
37
+ let device = & self . context . device ;
38
+ device. create_buffer_init ( & BufferInitDescriptor {
39
+ label : Some ( & format ! ( "{} arg buffer" , pipeline. name. as_str( ) ) ) ,
40
+ usage : BufferUsages :: STORAGE ,
41
+ contents : bytemuck:: bytes_of ( args) ,
42
+ } )
41
43
} ) ;
42
- pipeline. dispatch ( & self . context , textures, & arg_buffer)
44
+ pipeline. dispatch ( & self . context , textures, arg_buffer)
43
45
}
44
46
}
45
47
48
+ pub struct Shaders < ' a > {
49
+ pub wgsl_shader : & ' a str ,
50
+ pub fragment_shader_name : & ' a str ,
51
+ pub has_uniform : bool ,
52
+ }
53
+
46
54
pub struct PerPixelAdjustGraphicsPipeline {
47
55
name : String ,
56
+ has_uniform : bool ,
48
57
pipeline : wgpu:: RenderPipeline ,
49
58
}
50
59
@@ -62,32 +71,46 @@ impl PerPixelAdjustGraphicsPipeline {
62
71
source : ShaderSource :: Wgsl ( Cow :: Borrowed ( info. wgsl_shader ) ) ,
63
72
} ) ;
64
73
74
+ let entries: & [ _ ] = if info. has_uniform {
75
+ & [
76
+ BindGroupLayoutEntry {
77
+ binding : 0 ,
78
+ visibility : ShaderStages :: FRAGMENT ,
79
+ ty : BindingType :: Buffer {
80
+ ty : BufferBindingType :: Storage { read_only : true } ,
81
+ has_dynamic_offset : false ,
82
+ min_binding_size : None ,
83
+ } ,
84
+ count : None ,
85
+ } ,
86
+ BindGroupLayoutEntry {
87
+ binding : 1 ,
88
+ visibility : ShaderStages :: FRAGMENT ,
89
+ ty : BindingType :: Texture {
90
+ sample_type : TextureSampleType :: Float { filterable : false } ,
91
+ view_dimension : TextureViewDimension :: D2 ,
92
+ multisampled : false ,
93
+ } ,
94
+ count : None ,
95
+ } ,
96
+ ]
97
+ } else {
98
+ & [ BindGroupLayoutEntry {
99
+ binding : 0 ,
100
+ visibility : ShaderStages :: FRAGMENT ,
101
+ ty : BindingType :: Texture {
102
+ sample_type : TextureSampleType :: Float { filterable : false } ,
103
+ view_dimension : TextureViewDimension :: D2 ,
104
+ multisampled : false ,
105
+ } ,
106
+ count : None ,
107
+ } ]
108
+ } ;
65
109
let pipeline_layout = device. create_pipeline_layout ( & PipelineLayoutDescriptor {
66
110
label : Some ( & format ! ( "PerPixelAdjust {} PipelineLayout" , name) ) ,
67
111
bind_group_layouts : & [ & device. create_bind_group_layout ( & BindGroupLayoutDescriptor {
68
112
label : Some ( & format ! ( "PerPixelAdjust {} BindGroupLayout 0" , name) ) ,
69
- entries : & [
70
- BindGroupLayoutEntry {
71
- binding : 0 ,
72
- visibility : ShaderStages :: FRAGMENT ,
73
- ty : BindingType :: Buffer {
74
- ty : BufferBindingType :: Storage { read_only : true } ,
75
- has_dynamic_offset : false ,
76
- min_binding_size : None ,
77
- } ,
78
- count : None ,
79
- } ,
80
- BindGroupLayoutEntry {
81
- binding : 1 ,
82
- visibility : ShaderStages :: FRAGMENT ,
83
- ty : BindingType :: Texture {
84
- sample_type : TextureSampleType :: Float { filterable : false } ,
85
- view_dimension : TextureViewDimension :: D2 ,
86
- multisampled : false ,
87
- } ,
88
- count : None ,
89
- } ,
90
- ] ,
113
+ entries,
91
114
} ) ] ,
92
115
push_constant_ranges : & [ ] ,
93
116
} ) ;
@@ -125,10 +148,15 @@ impl PerPixelAdjustGraphicsPipeline {
125
148
multiview : None ,
126
149
cache : None ,
127
150
} ) ;
128
- Self { pipeline, name }
151
+ Self {
152
+ pipeline,
153
+ name,
154
+ has_uniform : info. has_uniform ,
155
+ }
129
156
}
130
157
131
- pub fn dispatch ( & self , context : & Context , textures : Table < Raster < GPU > > , arg_buffer : & Buffer ) -> Table < Raster < GPU > > {
158
+ pub fn dispatch ( & self , context : & Context , textures : Table < Raster < GPU > > , arg_buffer : Option < Buffer > ) -> Table < Raster < GPU > > {
159
+ assert_eq ! ( self . has_uniform, arg_buffer. is_some( ) ) ;
132
160
let device = & context. device ;
133
161
let name = self . name . as_str ( ) ;
134
162
@@ -140,11 +168,8 @@ impl PerPixelAdjustGraphicsPipeline {
140
168
let view_in = tex_in. create_view ( & TextureViewDescriptor :: default ( ) ) ;
141
169
let format = tex_in. format ( ) ;
142
170
143
- let bind_group = device. create_bind_group ( & BindGroupDescriptor {
144
- label : Some ( & format ! ( "{name} bind group" ) ) ,
145
- // `get_bind_group_layout` allocates unnecessary memory, we could create it manually to not do that
146
- layout : & self . pipeline . get_bind_group_layout ( 0 ) ,
147
- entries : & [
171
+ let entries: & [ _ ] = if let Some ( arg_buffer) = arg_buffer. as_ref ( ) {
172
+ & [
148
173
BindGroupEntry {
149
174
binding : 0 ,
150
175
resource : BindingResource :: Buffer ( BufferBinding {
@@ -157,7 +182,18 @@ impl PerPixelAdjustGraphicsPipeline {
157
182
binding : 1 ,
158
183
resource : BindingResource :: TextureView ( & view_in) ,
159
184
} ,
160
- ] ,
185
+ ]
186
+ } else {
187
+ & [ BindGroupEntry {
188
+ binding : 0 ,
189
+ resource : BindingResource :: TextureView ( & view_in) ,
190
+ } ]
191
+ } ;
192
+ let bind_group = device. create_bind_group ( & BindGroupDescriptor {
193
+ label : Some ( & format ! ( "{name} bind group" ) ) ,
194
+ // `get_bind_group_layout` allocates unnecessary memory, we could create it manually to not do that
195
+ layout : & self . pipeline . get_bind_group_layout ( 0 ) ,
196
+ entries,
161
197
} ) ;
162
198
163
199
let tex_out = device. create_texture ( & TextureDescriptor {
0 commit comments