@@ -2,7 +2,9 @@ import { GUI } from 'dat.gui';
2
2
3
3
import showMultisampleTextureWGSL from './showMultisampleTexture.wgsl' ;
4
4
import renderWithAlphaToCoverageWGSL from './renderWithAlphaToCoverage.wgsl' ;
5
+ import renderWithEmulatedAlphaToCoverageWGSL from './renderWithEmulatedAlphaToCoverage.wgsl' ;
5
6
import { quitIfWebGPUNotAvailable } from '../util' ;
7
+ import { kEmulatedAlphaToCoverage } from './emulatedAlphaToCoverage' ;
6
8
7
9
const canvas = document . querySelector ( 'canvas' ) as HTMLCanvasElement ;
8
10
const adapter = await navigator . gpu ?. requestAdapter ( ) ;
@@ -14,6 +16,8 @@ quitIfWebGPUNotAvailable(adapter, device);
14
16
//
15
17
16
18
const kInitConfig = {
19
+ scene : 'solid_colors' ,
20
+ emulatedDevice : 'none' ,
17
21
sizeLog2 : 3 ,
18
22
showResolvedColor : true ,
19
23
color1 : 0x0000ff ,
@@ -34,17 +38,23 @@ gui.width = 300;
34
38
} ,
35
39
} ;
36
40
41
+ gui . add ( config , 'scene' , [ 'solid_colors' ] ) ;
42
+ gui . add ( config , 'emulatedDevice' , [
43
+ 'none' ,
44
+ ...Object . keys ( kEmulatedAlphaToCoverage ) ,
45
+ ] ) ;
46
+
37
47
const settings = gui . addFolder ( 'Settings' ) ;
38
48
settings . open ( ) ;
39
49
settings . add ( config , 'sizeLog2' , 0 , 8 , 1 ) . name ( 'size = 2**' ) ;
40
50
settings . add ( config , 'showResolvedColor' , true ) ;
41
51
42
- const draw1Panel = gui . addFolder ( 'Draw 1' ) ;
52
+ const draw1Panel = gui . addFolder ( 'solid_colors Draw 1' ) ;
43
53
draw1Panel . open ( ) ;
44
54
draw1Panel . addColor ( config , 'color1' ) . name ( 'color' ) ;
45
55
draw1Panel . add ( config , 'alpha1' , 0 , 255 ) . name ( 'alpha' ) ;
46
56
47
- const draw2Panel = gui . addFolder ( 'Draw 2' ) ;
57
+ const draw2Panel = gui . addFolder ( 'solid_colors Draw 2' ) ;
48
58
draw2Panel . open ( ) ;
49
59
draw2Panel . addColor ( config , 'color2' ) . name ( 'color' ) ;
50
60
draw2Panel . add ( config , 'alpha2' , 0 , 255 ) . name ( 'alpha' ) ;
@@ -80,23 +90,32 @@ const bufInstanceColors = device.createBuffer({
80
90
size : 8 ,
81
91
} ) ;
82
92
83
- let multisampleTexture : GPUTexture , multisampleTextureView : GPUTextureView ;
93
+ let actualMSTexture : GPUTexture , actualMSTextureView : GPUTextureView ;
94
+ let emulatedMSTexture : GPUTexture , emulatedMSTextureView : GPUTextureView ;
84
95
let resolveTexture : GPUTexture , resolveTextureView : GPUTextureView ;
85
96
let lastSize = 0 ;
86
- function resetMultisampleTexture ( ) {
97
+ let renderWithEmulatedAlphaToCoveragePipeline : GPURenderPipeline | null ;
98
+ let lastEmulatedDevice = 'none' ;
99
+ function resetConfiguredObjects ( ) {
87
100
const size = 2 ** config . sizeLog2 ;
88
101
if ( lastSize !== size ) {
89
- if ( multisampleTexture ) {
90
- multisampleTexture . destroy ( ) ;
102
+ if ( actualMSTexture ) {
103
+ actualMSTexture . destroy ( ) ;
91
104
}
92
- multisampleTexture = device . createTexture ( {
93
- format : 'rgba8unorm' ,
105
+ if ( emulatedMSTexture ) {
106
+ emulatedMSTexture . destroy ( ) ;
107
+ }
108
+ const msTextureDesc = {
109
+ format : 'rgba8unorm' as const ,
94
110
usage :
95
111
GPUTextureUsage . RENDER_ATTACHMENT | GPUTextureUsage . TEXTURE_BINDING ,
96
112
size : [ size , size ] ,
97
113
sampleCount : 4 ,
98
- } ) ;
99
- multisampleTextureView = multisampleTexture . createView ( ) ;
114
+ } ;
115
+ actualMSTexture = device . createTexture ( msTextureDesc ) ;
116
+ actualMSTextureView = actualMSTexture . createView ( ) ;
117
+ emulatedMSTexture = device . createTexture ( msTextureDesc ) ;
118
+ emulatedMSTextureView = emulatedMSTexture . createView ( ) ;
100
119
101
120
if ( resolveTexture ) {
102
121
resolveTexture . destroy ( ) ;
@@ -111,6 +130,40 @@ function resetMultisampleTexture() {
111
130
112
131
lastSize = size ;
113
132
}
133
+
134
+ if (
135
+ config . emulatedDevice !== 'none' &&
136
+ lastEmulatedDevice !== config . emulatedDevice
137
+ ) {
138
+ // Pipeline to render to a multisampled texture using *emulated* alpha-to-coverage
139
+ const renderWithEmulatedAlphaToCoverageModule = device . createShaderModule ( {
140
+ code :
141
+ renderWithEmulatedAlphaToCoverageWGSL +
142
+ kEmulatedAlphaToCoverage [ config . emulatedDevice ] ,
143
+ } ) ;
144
+ renderWithEmulatedAlphaToCoveragePipeline = device . createRenderPipeline ( {
145
+ label : 'renderWithEmulatedAlphaToCoveragePipeline' ,
146
+ layout : 'auto' ,
147
+ vertex : {
148
+ module : renderWithEmulatedAlphaToCoverageModule ,
149
+ buffers : [
150
+ {
151
+ stepMode : 'instance' ,
152
+ arrayStride : 4 ,
153
+ attributes : [ { shaderLocation : 0 , format : 'unorm8x4' , offset : 0 } ] ,
154
+ } ,
155
+ ] ,
156
+ } ,
157
+ fragment : {
158
+ module : renderWithEmulatedAlphaToCoverageModule ,
159
+ targets : [ { format : 'rgba8unorm' } ] ,
160
+ } ,
161
+ multisample : { count : 4 , alphaToCoverageEnabled : false } ,
162
+ primitive : { topology : 'triangle-list' } ,
163
+ } ) ;
164
+ } else {
165
+ renderWithEmulatedAlphaToCoveragePipeline = null ;
166
+ }
114
167
}
115
168
116
169
function applyConfig ( ) {
@@ -129,7 +182,7 @@ function applyConfig() {
129
182
] ) ;
130
183
device . queue . writeBuffer ( bufInstanceColors , 0 , data ) ;
131
184
132
- resetMultisampleTexture ( ) ;
185
+ resetConfiguredObjects ( ) ;
133
186
}
134
187
135
188
//
@@ -170,7 +223,16 @@ const showMultisampleTextureModule = device.createShaderModule({
170
223
const showMultisampleTexturePipeline = device . createRenderPipeline ( {
171
224
label : 'showMultisampleTexturePipeline' ,
172
225
layout : 'auto' ,
173
- vertex : { module : showMultisampleTextureModule } ,
226
+ vertex : {
227
+ module : showMultisampleTextureModule ,
228
+ buffers : [
229
+ {
230
+ stepMode : 'instance' ,
231
+ arrayStride : 4 ,
232
+ attributes : [ { shaderLocation : 0 , format : 'unorm8x4' , offset : 0 } ] ,
233
+ } ,
234
+ ] ,
235
+ } ,
174
236
fragment : {
175
237
module : showMultisampleTextureModule ,
176
238
targets : [ { format : presentationFormat } ] ,
@@ -186,8 +248,15 @@ function render() {
186
248
const showMultisampleTextureBG = device . createBindGroup ( {
187
249
layout : showMultisampleTextureBGL ,
188
250
entries : [
189
- { binding : 0 , resource : multisampleTextureView } ,
190
- { binding : 1 , resource : resolveTextureView } ,
251
+ { binding : 0 , resource : actualMSTextureView } ,
252
+ {
253
+ binding : 1 ,
254
+ resource :
255
+ config . emulatedDevice === 'none'
256
+ ? actualMSTextureView
257
+ : emulatedMSTextureView ,
258
+ } ,
259
+ { binding : 2 , resource : resolveTextureView } ,
191
260
] ,
192
261
} ) ;
193
262
@@ -212,7 +281,7 @@ function render() {
212
281
label : 'renderWithAlphaToCoverage pass' ,
213
282
colorAttachments : [
214
283
{
215
- view : multisampleTextureView ,
284
+ view : actualMSTextureView ,
216
285
resolveTarget : config . showResolvedColor
217
286
? resolveTextureView
218
287
: undefined ,
@@ -227,6 +296,24 @@ function render() {
227
296
pass . draw ( 6 , 2 ) ;
228
297
pass . end ( ) ;
229
298
}
299
+ // renderWithEmulatedAlphaToCoverage pass
300
+ if ( renderWithEmulatedAlphaToCoveragePipeline ) {
301
+ const pass = commandEncoder . beginRenderPass ( {
302
+ label : 'renderWithEmulatedAlphaToCoverage pass' ,
303
+ colorAttachments : [
304
+ {
305
+ view : emulatedMSTextureView ,
306
+ clearValue : [ 0 , 0 , 0 , 1 ] , // black background
307
+ loadOp : 'clear' ,
308
+ storeOp : 'store' ,
309
+ } ,
310
+ ] ,
311
+ } ) ;
312
+ pass . setPipeline ( renderWithEmulatedAlphaToCoveragePipeline ) ;
313
+ pass . setVertexBuffer ( 0 , bufInstanceColors ) ;
314
+ pass . draw ( 6 , 2 ) ;
315
+ pass . end ( ) ;
316
+ }
230
317
// showMultisampleTexture pass
231
318
{
232
319
const pass = commandEncoder . beginRenderPass ( {
@@ -242,6 +329,7 @@ function render() {
242
329
} ) ;
243
330
pass . setPipeline ( showMultisampleTexturePipeline ) ;
244
331
pass . setBindGroup ( 0 , showMultisampleTextureBG ) ;
332
+ pass . setVertexBuffer ( 0 , bufInstanceColors ) ;
245
333
pass . draw ( 6 ) ;
246
334
pass . end ( ) ;
247
335
}
0 commit comments