Skip to content

Commit

Permalink
Render triangle without buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
sketchpunk committed Oct 13, 2023
1 parent 3dbe1db commit 974de34
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions prototypes/001_draw_tri.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<!DOCTYPE html><html><head><title></title>
</head><body><script type="module">

// https://codelabs.developers.google.com/your-first-webgpu-app#2
window.addEventListener( 'load', async ()=>{
const canvas = document.querySelector( 'canvas' );
wgpuInit( canvas )
.then( ref=>{
console.log( 'ready', ref );
setCanvasSize( ref.canvas, 512, 512 );

const sh = createShader( ref );

renderScene( ref, sh );
}).catch( e=>console.error( 'MEH', e ) );
});

async function wgpuInit( canvas ){
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if( !navigator.gpu ) throw new Error( 'WebGPU not available' );

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// https://developer.mozilla.org/en-US/docs/Web/API/GPU/requestAdapter
const optAdapter = {
powerPreference : 'low-power', // 'high-performance', //
forceFallbackAdapter : false, // Fallback Adapters are currently not supported in browsers
};

const adapter = await navigator.gpu.requestAdapter( optAdapter );
if( !adapter ) throw new Error( 'WebGPU adapter not found' );

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const optDevice = {
label : 'MyDevice',
defaultQueue : { label : 'MyQueue' },
requiredFeatures : [],
requiredLimits : {
maxBindGroups : 4,
},
};

const device = await adapter.requestDevice( optDevice );
if( !device ) throw new Error( 'WebGPU device not found' );

device.lost.then( e=>console.log( 'WebGPU Device is lost', e.message, e.reason ) );

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext/configure
const context = canvas.getContext( 'webgpu' );
const format = navigator.gpu.getPreferredCanvasFormat();

context.configure({
device,
format,
alphaMode : 'opaque', // premultiplied
colorSpace : 'srgb', // display-p3
});

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return { device, adapter, format, context, canvas };
}

function setCanvasSize( c, w, h ){
const dpr = window.devicePixelRatio || 1;

// Internally set with the size
// Need to round, you can't have a fraction of a pixel, can you?
c.width = Math.round( w * dpr );
c.height = Math.round( h * dpr );

// Externally set with the size
c.style.width = w + 'px';
c.style.height = h + 'px';
}

function renderScene( ref, pipe ){
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const encoder = ref.device.createCommandEncoder();

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const pass = encoder.beginRenderPass({
label : 'MainPass',
colorAttachments : [{
view : ref.context.getCurrentTexture().createView({ aspect: 'all' }), // Set next frame buffer
clearValue : [ 0.2, 0.2, 0.2, 1.0 ],
loadOp : 'clear', // Clear texture on start
storeOp : 'store', // Save results of draw calls to texture
}]
});

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pass.setPipeline( pipe );
pass.draw( 3 );

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pass.end();
ref.device.queue.submit( [ encoder.finish() ] );
}

function createShader( ref ){
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/createShaderModule
const mod = ref.device.createShaderModule({
label : 'MyShader',
code : `
const verts: array<vec2f, 3> = array<vec2f,3>(
vec2f( -0.8, -0.8 ),
vec2f( 0.8, -0.8 ),
vec2f( 0.8, 0.8 ),
);
@vertex
fn vMain( @builtin( vertex_index ) vIdx: u32 ) -> @builtin( position ) vec4f{
return vec4f( verts[ vIdx ], 0, 1 );
}
@fragment
fn fMain() -> @location(0) vec4f{
return vec4f( 1, 0, 0, 1 );
}
`,
});

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/createRenderPipeline
const pipe = ref.device.createRenderPipeline({
label : 'MyPipeline',
layout : 'auto', // If auto, the bindgroup is locked to this popeline

primitive : {
topology : 'triangle-list',
},

vertex : {
module : mod,
entryPoint : 'vMain',
buffers : [],
},

fragment : {
module : mod,
entryPoint : 'fMain',
targets : [ { format: ref.format } ],
},
});

return pipe;
}

</script>
<style>
canvas { border:1px solid #505050; }
html, body{ margin:0px; padding:0px; width:100%; height:100%; }
body{ background-color: #1E1E1E;
display:flex; flex-direction:column;
align-items:center; justify-content: center;
}
</style>
<canvas id='pgCanvas' width="512" height="512"></canvas>
</body></html>

0 comments on commit 974de34

Please sign in to comment.