Created
October 29, 2023 11:50
-
-
Save smallshen/d6cd88b825e232ba39b6a78c8ae17a70 to your computer and use it in GitHub Desktop.
custom jextract example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.mojang.webgpu | |
import webgpu.kotlin.* | |
import webgpu.webgpu_h.* | |
import java.lang.foreign.Arena | |
import java.lang.foreign.MemorySegment | |
private val shaderSrc = """ | |
@vertex | |
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4f { | |
var pos = array( | |
vec2f( 0.0, 0.5), | |
vec2f(-0.5, -0.5), | |
vec2f( 0.5, -0.5) | |
); | |
return vec4f(pos[in_vertex_index], 0.0, 1.0); | |
} | |
@fragment | |
fn fs_main() -> @location(0) vec4f { | |
return vec4f(1.0, 1.0, 0.0, 1.0); | |
} | |
""".trimIndent() | |
class TriangleExample : ApplicationWindow() { | |
var canStartRender = false | |
var shaderModule: MemorySegment = MemorySegment.NULL | |
var pipeline: MemorySegment = MemorySegment.NULL | |
fun initTriangleShaderModule() { | |
shaderModule = wgpuInstance.createShaderModule(shaderSrc) | |
} | |
fun initPipeline() { | |
val pipelineDesc = WGPURenderPipelineDescriptor(Arena.ofAuto()) | |
pipelineDesc.nextInChain = MemorySegment.NULL | |
pipelineDesc.vertex.bufferCount = 0L | |
pipelineDesc.vertex.buffers = MemorySegment.NULL | |
pipelineDesc.vertex.module = shaderModule | |
pipelineDesc.vertex.entryPoint = Arena.ofAuto().allocateUtf8String("vs_main") | |
pipelineDesc.primitive.topology = WGPUPrimitiveTopology.WGPUPrimitiveTopology_TriangleList.v | |
pipelineDesc.primitive.stripIndexFormat = WGPUIndexFormat.WGPUIndexFormat_Undefined.v | |
pipelineDesc.primitive.frontFace = WGPUFrontFace.WGPUFrontFace_CCW.v | |
pipelineDesc.primitive.cullMode = WGPUCullMode.WGPUCullMode_None.v | |
val fragmentState = WGPUFragmentState(Arena.ofAuto()) | |
pipelineDesc.fragment = fragmentState.native() | |
fragmentState.module = shaderModule | |
fragmentState.entryPoint = Arena.ofAuto().allocateUtf8String("fs_main") | |
fragmentState.constantCount = 0L | |
fragmentState.constants = MemorySegment.NULL | |
val blendState = WGPUBlendState(Arena.ofAuto()) | |
blendState.color.srcFactor = WGPUBlendFactor.WGPUBlendFactor_SrcAlpha.v | |
blendState.color.dstFactor = WGPUBlendFactor.WGPUBlendFactor_OneMinusSrcAlpha.v | |
blendState.color.operation = WGPUBlendOperation.WGPUBlendOperation_Add.v | |
blendState.alpha.srcFactor = WGPUBlendFactor.WGPUBlendFactor_Zero.v | |
blendState.alpha.dstFactor = WGPUBlendFactor.WGPUBlendFactor_One.v | |
blendState.alpha.operation = WGPUBlendOperation.WGPUBlendOperation_Add.v | |
val colorTarget = WGPUColorTargetState(Arena.ofAuto()) | |
colorTarget.nextInChain = MemorySegment.NULL | |
colorTarget.format = wgpuInstance.getSwapChainFormat() | |
colorTarget.blend = blendState.native() | |
colorTarget.writeMask = WGPUColorWriteMask.WGPUColorWriteMask_All.v | |
fragmentState.targetCount = 1L | |
fragmentState.targets = colorTarget.native() | |
pipelineDesc.depthStencil = MemorySegment.NULL | |
pipelineDesc.multisample.count = 1 | |
pipelineDesc.multisample.mask = 0xFFFF | |
pipelineDesc.multisample.alphaToCoverageEnabled = 0 | |
pipeline = wgpuDeviceCreateRenderPipeline(wgpuInstance.devicePtr, pipelineDesc.native()) | |
assert(pipeline != MemorySegment.NULL) | |
wgpuShaderModuleRelease(shaderModule) | |
} | |
override fun frame(arena: Arena) { | |
if (!canStartRender) return | |
val nextTexture = wgpuSwapChainGetCurrentTextureView(wgpuInstance.swapChainPtr) | |
assert(nextTexture != MemorySegment.NULL) { | |
"Failed to acquire next swap chain texture" | |
} | |
val renderPassDesc = WGPURenderPassDescriptor(arena) | |
renderPassDesc.nextInChain = MemorySegment.NULL | |
val colorAttachment = WGPURenderPassColorAttachment(arena) | |
colorAttachment.view = nextTexture | |
colorAttachment.resolveTarget = MemorySegment.NULL | |
colorAttachment.loadOp = WGPULoadOp.WGPULoadOp_Clear.v | |
colorAttachment.storeOp = WGPUStoreOp.WGPUStoreOp_Store.v | |
colorAttachment.clearValue.r = 0.0 | |
colorAttachment.clearValue.g = 0.0 | |
colorAttachment.clearValue.b = 1.0 | |
colorAttachment.clearValue.a = 1.0 | |
renderPassDesc.colorAttachmentCount = 1 | |
renderPassDesc.colorAttachments = colorAttachment.native() | |
renderPassDesc.depthStencilAttachment = MemorySegment.NULL | |
val encoder = wgpuDeviceCreateCommandEncoder(wgpuInstance.devicePtr, MemorySegment.NULL) | |
val pass = wgpuCommandEncoderBeginRenderPass(encoder, renderPassDesc.native()) | |
wgpuRenderPassEncoderSetPipeline(pass, pipeline) | |
wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0) | |
wgpuRenderPassEncoderEnd(pass) | |
val command = wgpuCommandEncoderFinish(encoder, MemorySegment.NULL) | |
assert(command != MemorySegment.NULL) | |
wgpuQueueSubmit(wgpuInstance.queue, 1, command.ptr()) | |
wgpuSwapChainPresent(wgpuInstance.swapChainPtr) | |
wgpuCommandBufferRelease(command) | |
wgpuCommandEncoderRelease(encoder) | |
wgpuTextureViewRelease(nextTexture) | |
wgpuRenderPassEncoderRelease(pass) | |
} | |
override fun close() { | |
wgpuRenderPipelineRelease(pipeline) | |
wgpuShaderModuleRelease(shaderModule) | |
super.close() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment