@@ -2,7 +2,9 @@ import { GUI } from 'dat.gui';
22
33import showMultisampleTextureWGSL from './showMultisampleTexture.wgsl' ;
44import renderWithAlphaToCoverageWGSL from './renderWithAlphaToCoverage.wgsl' ;
5+ import renderWithEmulatedAlphaToCoverageWGSL from './renderWithEmulatedAlphaToCoverage.wgsl' ;
56import { quitIfWebGPUNotAvailable } from '../util' ;
7+ import { kEmulatedAlphaToCoverage } from './emulatedAlphaToCoverage' ;
68
79const canvas = document . querySelector ( 'canvas' ) as HTMLCanvasElement ;
810const adapter = await navigator . gpu ?. requestAdapter ( ) ;
@@ -14,6 +16,8 @@ quitIfWebGPUNotAvailable(adapter, device);
1416//
1517
1618const kInitConfig = {
19+ scene : 'solid_colors' ,
20+ emulatedDevice : 'none' ,
1721 sizeLog2 : 3 ,
1822 showResolvedColor : true ,
1923 color1 : 0x0000ff ,
@@ -34,17 +38,23 @@ gui.width = 300;
3438 } ,
3539 } ;
3640
41+ gui . add ( config , 'scene' , [ 'solid_colors' ] ) ;
42+ gui . add ( config , 'emulatedDevice' , [
43+ 'none' ,
44+ ...Object . keys ( kEmulatedAlphaToCoverage ) ,
45+ ] ) ;
46+
3747 const settings = gui . addFolder ( 'Settings' ) ;
3848 settings . open ( ) ;
3949 settings . add ( config , 'sizeLog2' , 0 , 8 , 1 ) . name ( 'size = 2**' ) ;
4050 settings . add ( config , 'showResolvedColor' , true ) ;
4151
42- const draw1Panel = gui . addFolder ( 'Draw 1' ) ;
52+ const draw1Panel = gui . addFolder ( 'solid_colors Draw 1' ) ;
4353 draw1Panel . open ( ) ;
4454 draw1Panel . addColor ( config , 'color1' ) . name ( 'color' ) ;
4555 draw1Panel . add ( config , 'alpha1' , 0 , 255 ) . name ( 'alpha' ) ;
4656
47- const draw2Panel = gui . addFolder ( 'Draw 2' ) ;
57+ const draw2Panel = gui . addFolder ( 'solid_colors Draw 2' ) ;
4858 draw2Panel . open ( ) ;
4959 draw2Panel . addColor ( config , 'color2' ) . name ( 'color' ) ;
5060 draw2Panel . add ( config , 'alpha2' , 0 , 255 ) . name ( 'alpha' ) ;
@@ -80,23 +90,32 @@ const bufInstanceColors = device.createBuffer({
8090 size : 8 ,
8191} ) ;
8292
83- let multisampleTexture : GPUTexture , multisampleTextureView : GPUTextureView ;
93+ let actualMSTexture : GPUTexture , actualMSTextureView : GPUTextureView ;
94+ let emulatedMSTexture : GPUTexture , emulatedMSTextureView : GPUTextureView ;
8495let resolveTexture : GPUTexture , resolveTextureView : GPUTextureView ;
8596let lastSize = 0 ;
86- function resetMultisampleTexture ( ) {
97+ let renderWithEmulatedAlphaToCoveragePipeline : GPURenderPipeline | null ;
98+ let lastEmulatedDevice = 'none' ;
99+ function resetConfiguredObjects ( ) {
87100 const size = 2 ** config . sizeLog2 ;
88101 if ( lastSize !== size ) {
89- if ( multisampleTexture ) {
90- multisampleTexture . destroy ( ) ;
102+ if ( actualMSTexture ) {
103+ actualMSTexture . destroy ( ) ;
91104 }
92- multisampleTexture = device . createTexture ( {
93- format : 'rgba8unorm' ,
105+ if ( emulatedMSTexture ) {
106+ emulatedMSTexture . destroy ( ) ;
107+ }
108+ const msTextureDesc = {
109+ format : 'rgba8unorm' as const ,
94110 usage :
95111 GPUTextureUsage . RENDER_ATTACHMENT | GPUTextureUsage . TEXTURE_BINDING ,
96112 size : [ size , size ] ,
97113 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 ( ) ;
100119
101120 if ( resolveTexture ) {
102121 resolveTexture . destroy ( ) ;
@@ -111,6 +130,40 @@ function resetMultisampleTexture() {
111130
112131 lastSize = size ;
113132 }
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+ }
114167}
115168
116169function applyConfig ( ) {
@@ -129,7 +182,7 @@ function applyConfig() {
129182 ] ) ;
130183 device . queue . writeBuffer ( bufInstanceColors , 0 , data ) ;
131184
132- resetMultisampleTexture ( ) ;
185+ resetConfiguredObjects ( ) ;
133186}
134187
135188//
@@ -170,7 +223,16 @@ const showMultisampleTextureModule = device.createShaderModule({
170223const showMultisampleTexturePipeline = device . createRenderPipeline ( {
171224 label : 'showMultisampleTexturePipeline' ,
172225 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+ } ,
174236 fragment : {
175237 module : showMultisampleTextureModule ,
176238 targets : [ { format : presentationFormat } ] ,
@@ -186,8 +248,15 @@ function render() {
186248 const showMultisampleTextureBG = device . createBindGroup ( {
187249 layout : showMultisampleTextureBGL ,
188250 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 } ,
191260 ] ,
192261 } ) ;
193262
@@ -212,7 +281,7 @@ function render() {
212281 label : 'renderWithAlphaToCoverage pass' ,
213282 colorAttachments : [
214283 {
215- view : multisampleTextureView ,
284+ view : actualMSTextureView ,
216285 resolveTarget : config . showResolvedColor
217286 ? resolveTextureView
218287 : undefined ,
@@ -227,6 +296,24 @@ function render() {
227296 pass . draw ( 6 , 2 ) ;
228297 pass . end ( ) ;
229298 }
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+ }
230317 // showMultisampleTexture pass
231318 {
232319 const pass = commandEncoder . beginRenderPass ( {
@@ -242,6 +329,7 @@ function render() {
242329 } ) ;
243330 pass . setPipeline ( showMultisampleTexturePipeline ) ;
244331 pass . setBindGroup ( 0 , showMultisampleTextureBG ) ;
332+ pass . setVertexBuffer ( 0 , bufInstanceColors ) ;
245333 pass . draw ( 6 ) ;
246334 pass . end ( ) ;
247335 }
0 commit comments