gpu

package
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2024 License: BSD-3-Clause Imports: 28 Imported by: 0

README

GPU for Graphics and Compute

The gpu package manages all the details of WebGPU to provide a higher-level interface where you can specify the data variables and values, shader pipelines, and other parameters that tell the GPU what to do, without having to worry about all the lower-level implementational details. It maps directly onto the underlying WebGPU structure, and does not decrease performance in any way. It supports both graphics and compute functionality.

The main gpu code is in the top-level gpu package, with the following sub-packages available:

  • phong is a Blinn-Phong lighting model implementation on top of gpu, which then serves as the basis for the higherlevel xyz 3D scenegraph system.

  • shape generates standard 3D shapes (sphere, cylinder, box, etc), with all the normals and texture coordinates. You can compose shape elements into more complex groups of shapes, programmatically. It separates the calculation of the number of vertex and index elements from actually setting those elements, so you can allocate everything in one pass, and then configure the shape data in a second pass, consistent with the most efficient memory model provided by gpu. It only has a dependency on the math32 package and could be used for anything.

  • gpudraw implements GPU-accelerated texture-based versions of the Go image/draw api. This is used for compositing images in the core GUI to construct the final rendered scene, and for drawing that scene on the actual hardware window.

  • gosl translates Go code into GPU shader language code for running compute shaders in gpu, playing the role of NVIDIA's "cuda" language in other frameworks.

Platforms

  • On desktop (mac, windows, linux), glfw is used for initializing the GPU.
  • Mobile (android, ios)...
    • When developing for Android on macOS, it is critical to set Emulated Performance -> Graphics to Software in the Android Virtual Device Manager (AVD); otherwise, the app will crash on startup. This is because macOS does not support direct access to the underlying hardware GPU in the Android Emulator. You can see more information how to do this in the Android developer documentation. Please note that this issue will not affect end-users of your app, only you while you develop it. Also, due to the typically bad performance of the emulated device GPU on macOS, it is recommended that you use a more modern emulated device than the default Pixel 3a. Finally, you should always test your app on a real mobile device if possible to see what it is actually like.

Selecting a GPU Device

For systems with multiple GPU devices, by default the discrete device is selected, and if multiple of those are present, the one with the most RAM is used. To see what is available and their properties, use:

$ go run cogentcore.org/core/gpu/cmd/webgpuinfo@latest

(you can install that tool for later use as well)

The following environment variables can be set to specifically select a particular device by device number or name (deviceName):

  • GPU_DEVICE_SELECT, for GUI and compute usage.

  • GPU_COMPUTE_DEVICE_SELECT, only used for compute, if present, will override above, so you can use different GPUs for graphics vs compute.

  • GPU represents the hardware Adapter and maintains global settings, info about the hardware.

  • Device is a logical device and associated Queue info. Each such device can function in parallel.

There are many distinct mechanisms for graphics vs. compute functionality, so we review the Graphics system first, then the Compute.

Graphics System

  • GraphicsSystem manages multiple GraphicsPipelines and associated variables (Var) and Values, to accomplish a complete overall rendering / computational job. The Vars and Values are shared across all pipelines within a System, which is more efficient and usually what you want. A given shader can simply ignore the variables it doesn't need.

    • GraphicsPipeline performs a specific chain of operations, using Shader program(s). In the graphics context, each pipeline typically handles a different type of material or other variation in rendering (textured vs. not, transparent vs. solid, etc).
    • Vars has up to 4 (hard limit imposed by WebGPU) VarGroups which are referenced with the @group(n) syntax in the WGSL shader, in addition to a special VertexGroup specifically for the special Vertex and Index variables. Each VarGroup can have a number of Var variables, which occupy sequential @binding(n) numbers within each group.
    • Values within Var manages the specific data values for each variable. For example, each Texture or vertex mesh is stored in its own separate Value, with its own wgpu.Buffer that is used to transfer data from the CPU to the GPU device. The SetCurrent method selects which Value is currently used, for the next BindPipeline call that sets all the values to use for a given pipeline run. Critically, all values must be uploaded to the GPU in advance of a given GPU pass. For large numbers of Uniform and Storage values, a DynamicOffset can be set so there is just a single Value but the specific data used is determined by the DynamicIndex within the one big value buffer.
  • Texture manages a WebGPU Texture and associated TextureView, along with an optional Sampler that defines how pixels are accessed in a shader. The Texture can manage any kind of texture object, with different Config methods for the different types.

  • Renderer is an interface for the final render target, implemented by two types:

    • Surface represents the full hardware-managed Textures associated with an actual on-screen Window.
    • RenderTexture is an offscreen render target that renders directly to a Texture, which can then be downloaded from the GPU or used directly as an input to a shader.
    • Render is a helper type that is used by both of the above to manage the additional depth texture and multisampling texture target.
  • Unlike most game-oriented GPU setups, gpu is designed to be used in an event-driven manner where render updates arise from user input or other events, instead of requiring a constant render loop taking place at all times (which can optionally be established too). The event-driven model is vastly more energy efficient for non-game applications.

Basic render pass

These are the basic steps for a render pass, using convenient methods on the sy = GraphicsSystem, which then manages the rest of the underlying steps. pl here is a GraphicsPipeline.

	rp, err := sy.BeginRenderPass()
	if err != nil { // error has already been logged, as all errors are.
		return
	}
	pl.BindPipeline(rp)
	pl.BindDrawIndexed(rp)
	rp.End() // note: could add stuff after End and before EndRenderPass
	sy.EndRenderPass(rp)

Note that all errors are logged in the gpu system, because in general GPU-level code should not create errors once it has been debugged.

Var and Value data

The single most important constraint in thinking about how the GPU works, is that all resources (data in buffers, textures) must be uploaded to the GPU at the start of the render pass.

Thus, you must configure all the vars and values prior to a render pass, and if anything changes, these need to be reconfigured.

Then, during the render pass, the BindPipeline calls BindAllGroups to select which of multiple possible Value instances of each Var is actually seen by the current GPU commands. After the initial BindPipeline call, you can more selectively call BindGroup on an individual group to update the bindings.

Furthermore if you change the DynamicOffset for a variable configured with that property, you need to call BindGroup to update the offset into a larger shared value buffer, to determine which value is processed.

The Var.Values.Current index determines which Value is used for the BindGroup call, and SetCurrent* methods set this for you at various levels of the variable hierarchy. Likewise, the Value.DynamicIndex determines the dynamic offset, and can be set with SetDynamicIndex* calls.

Vars variables define the Type and Role of data used in the shaders. There are 3 major categories of Var roles:

  • Vertex and Index represent mesh points etc that provide input to Vertex shader -- these are handled very differently from the others, and must be located in a VertexSet which has a set index of -2. The offsets into allocated Values are updated dynamically for each render Draw command, so you can Bind different Vertex Values as you iterate through objects within a single render pass (again, the underlying vals must be sync'd prior).

  • PushConst (not yet available in WebGPU) are push constants that can only be 128 bytes total that can be directly copied from CPU ram to the GPU via a command -- it is the most high-performance way to update dynamically changing content, such as view matricies or indexes into other data structures. Must be located in PushConstSet set (index -1).

  • Uniform (read-only "constants") and Storage (read-write) data that contain misc other data, e.g., transformation matricies. These are the only types that can optionally use the DynamicOffset mechanism, which should generally be reserved for cases where there is a large and variable number of values that need to be selected among during a render pass. The phong system stores the object-specific "model matrix" and other object-specific data using this dynamic offset mechanism.

  • Texture vars that provide the raw Texture data, the TextureView through which that is accessed, and a Sampler that parametrizes how the pixels are mapped onto coordinates in the Fragment shader. Each texture object is managed as a distinct item in device memory.

Coordinate System

The world and "normalized display coordinate" (NDC) system for gpu is the following right-handed framework:

    ^
 Y+ | 
    |
    +-------->
   /      X+
  / Z+
 v

Which is consistent with the standard cartesian coordinate system, where everything is rotated 90 degrees along the X axis, so that Y+ now points into the depth plane, and Z+ points upward:

    ^   ^
 Z+ |  / Y+
    | / 
    +-------->
   /      X+
  / Y-
 v

You can think of this as having vertical "stacks" of standard X-Y coordinates, stacked up along the Z axis, like a big book of graph paper. In some cases, e.g., neural network layers, where this "stack" analog is particularly relevant, it can be useful to adopt this version of the coordinate system.

However, the advantage of our "Y+ up" system is that the X-Y 2D cartesian plane then maps directly onto the actual 2D screen that the user is looking at, with Z being the "extra" depth axis. Given the primacy and universal standard way of understanding the 2D plane, this consistency seems like a nice advantage.

In this coordinate system, the standard front face winding order is clockwise (CW), so the default is set to: pl.SetFrontFace(wgpu.FrontFaceCW) in the GraphicsPipeline.

The above coordinate system is consistent with OpenGL, but other 3D rendering frameworks, including the default in WebGPU, have other systems, as documented here: https://github.com/gpuweb/gpuweb/issues/416. WebGPU is consistent with DirectX and Metal (by design), and is a left handed coordinate system (using FrontFaceCCW by default), which conflicts with the near-universal right-hand-rule used in physics and engineering. Vulkan has its own peculiar coordinate system, with the "up" Y direction being negative, which turns it into a right-handed system, but one that doesn't make a lot of intuitive sense.

For reference, this is the default WebGPU coordinate system:

    ^
 Y+ | 
    |
    +-------->
   /      X+
  / Z-
 v

Obviously every system can be converted into every other with the proper combination of camera projection matricies and winding order settings, so it isn't a problem that we use something different than WebGPU natively uses -- it just requires a different winding order setting.

Compute System

See examples/compute1 for a very simple compute shader, and compute.go for the ComputeSystem that manages compute-only use of the GPU.

See [gosl] for a tool that converts Go code into WGSL shader code, so you can effectively run Go on the GPU.

Here's how it works:

  • Each WebGPU Pipeline holds 1 compute shader program, which is equivalent to a kernel in CUDA. This is the basic unit of computation, accomplishing one parallel sweep of processing across some number of identical data structures.

  • You must organize at the outset your Vars and Values in the System to hold the data structures your shaders operate on. In general, you want to have a single static set of Vars that cover everything you'll need, and different shaders can operate on different subsets of these. You want to minimize the amount of memory transfer.

  • Because the Queue.Submit call is by far the most expensive call in WebGPU, you want to minimize those. This means you want to combine as much of your computation into one big Command sequence, with calls to various different Pipeline shaders (which can all be put in one command buffer) that gets submitted once, rather than submitting separate commands for each shader. Ideally this also involves combining memory transfers to / from the GPU in the same command buffer as well.

  • There are no explicit sync mechanisms in WebGPU, but it is designed so that shader compute is automatically properly synced with prior and subsequent memory transfer commands, so it automatically does the right thing for most use cases.

  • Compute is particularly taxing on memory transfer in general, and as far as I can tell, the best strategy is to rely on the optimized WriteBuffer command to transfer from CPU to GPU, and then use a staging buffer to read data back from the GPU. E.g., see this reddit post. Critically, the write commands are queued and any staging buffers are managed internally, so it shouldn't be much slower than manually doing all the staging. For reading, we have to implement everything ourselves, and here it is critical to batch the ReadSync calls for all relevant values, so they all happen at once. Use ad-hoc ValueGroups to organize these batched read operations efficiently for the different groups of values that need to be read back in the different compute stages.

Gamma Correction (sRGB vs Linear) and Headless / Offscreen Rendering

It is hard to find this info very clearly stated:

  • All internal computation in shaders is done in a linear color space.
  • Textures are assumed to be sRGB and are automatically converted to linear on upload.
  • Other colors that are passed in should be converted from sRGB to linear (the phong shader does this for the PerVertex case).
  • The Surface automatically converts from Linear to sRGB for actual rendering.
  • A RenderTexture for offscreen / headless rendering must use wgpu.TextureFormatRGBA8UnormSrgb for the format, in order to get back an image that is automatically converted back to sRGB format.

Naming conventions

  • New* returns a new object.
  • Config operates on an existing object and settings, and does everything to get it configured for use.
  • Release releases allocated WebGPU objects. The usual Go simplicity of not having to worry about freeing memory does not apply to these objects.

Limits

See https://web3dsurvey.com/webgpu for a browser of limits across different platforms, for the web platform. Note that the native version typically will have higher limits for many things across these same platforms, but because we want to maintain full interoperability across web and native, it is the lower web limits that constrain.

Documentation

Overview

Package gpu implements a convenient interface to the WebGPU graphics and compute framework, in Go, using the ... bindings

The Cogent Core GUI framework runs on top of this.

Index

Constants

View Source
const (
	// MaxTextureLayers is the maximum number of layers per image
	MaxTextureLayers = 128

	// VertexGroup is the group number for Vertex and Index variables,
	// which have special treatment.
	VertexGroup = -2

	// PushGroup is the group number for Push Constants, which
	// do not appear in the BindGroupLayout and are managed separately.
	PushGroup = -1
)

Variables

View Source
var (
	// Debug is whether to enable debug mode, getting
	// more diagnostic output about GPU configuration and rendering.
	// It should be set using [SetDebug].
	Debug = false

	// DebugAdapter provides detailed information about the selected
	// GPU adpater device (i.e., the type and limits of the hardware).
	DebugAdapter = false
)

RoleBufferUsages maps VarRoles into buffer usage flags

View Source
var TextureFormatNames = map[wgpu.TextureFormat]string{
	wgpu.TextureFormatRGBA8UnormSrgb: "RGBA 8bit sRGB colorspace",
	wgpu.TextureFormatRGBA8Unorm:     "RGBA 8bit unsigned linear colorspace",
}

TextureFormatNames translates image format into human-readable string for most commonly available formats

TextureFormatSizes gives size of known WebGPU TextureFormats in bytes

TypeSizes gives our data type sizes in bytes

TypeToVertexFormat maps gpu.Types to WebGPU VertexFormat

Functions

func BufferMapAsyncError added in v0.3.3

func BufferMapAsyncError(status wgpu.BufferMapAsyncStatus) error

BufferMapAsyncError returns an error message if the status is not success.

func BufferReadSync added in v0.3.3

func BufferReadSync(device *Device, size int, buffer *wgpu.Buffer) error

BufferReadSync does a MapAsync on given buffer, waiting on the device until the sync is complete, and returning error if any issues.

func GLFWCreateWindow

func GLFWCreateWindow(gp *GPU, size image.Point, title string, resize *func(size image.Point)) (surface *wgpu.Surface, terminate func(), pollEvents func() bool, actualSize image.Point, err error)

GLFWCreateWindow is a helper function intended only for use in simple examples that makes a new window with glfw on platforms that support it and is largely a no-op on other platforms.

func ImageToRGBA

func ImageToRGBA(img image.Image) *image.RGBA

ImageToRGBA returns image.RGBA version of given image either because it already is one, or by converting it.

func ImgCompToUint8

func ImgCompToUint8(val float32) uint8

func IncludeFS

func IncludeFS(fsys fs.FS, fpath, code string) string

IncludeFS processes #include "file" statements in the given code string, using the given file system and default path to locate the included files.

func Init

func Init() error

Init initializes WebGPU system for Display-enabled use, using glfw. Must call before doing any vgpu stuff. Calls glfw.Init and sets the Vulkan instance proc addr and calls Init. IMPORTANT: must be called on the main initial thread!

func MemSizeAlign

func MemSizeAlign(size, align int) int

MemSizeAlign returns the size aligned according to align byte increments e.g., if align = 16 and size = 12, it returns 16

func NoDisplayGPU

func NoDisplayGPU() (*GPU, *Device, error)

NoDisplayGPU Initializes WebGPU and returns that and a new GPU device, without using an existing surface window.

func ReadToBytes added in v0.3.3

func ReadToBytes[E any](vl *Value, dest []E) error

ReadToBytes copies value read buffer data into the memory bytes occupied by the given object. You must have called [ReadSync] on the value prior to calling this, so that the memory is mapped. This automatically calls Unmap() after copying, which is essential for being able to re-use the read buffer again.

func SRGBFromLinear

func SRGBFromLinear(rl, gl, bl float32) (r, g, b float32)

SRGBFromLinear converts set of sRGB components from linear values, adding gamma correction.

func SRGBFromLinearComp

func SRGBFromLinearComp(lin float32) float32

SRGBFromLinearComp converts an sRGB rgb linear component to non-linear (gamma corrected) sRGB value Used in converting from XYZ to sRGB.

func SRGBToLinear

func SRGBToLinear(r, g, b float32) (rl, gl, bl float32)

SRGBToLinear converts set of sRGB components to linear values, removing gamma correction.

func SRGBToLinearComp

func SRGBToLinearComp(srgb float32) float32

SRGBToLinearComp converts an sRGB rgb component to linear space (removes gamma). Used in converting from sRGB to XYZ colors.

func SetDebug

func SetDebug(debug bool)

SetDebug sets Debug (debug mode). If it is set to true, it calls wgpu.SetLogLevel(wgpu.LogLevelDebug). Otherwise, it calls wgpu.SetLogLevel(wgpu.LogLevelError). It is called automatically with false in init(). You can also manually set the log level with wgpu.SetLogLevel.

func SetDynamicValueFrom

func SetDynamicValueFrom[E any](vl *Value, idx int, from []E) error

SetDynamicValueFrom copies given values into a staging buffer at the given dynamic variable index, for dynamic offset Uniform or Storage variables, which have alignment constraints. Must call [WriteDynamicBuffer] after all such values have been updated, to actually copy the entire staging buffer data to the GPU device. Vertex variables must have separate values for each, and do not support dynamic indexing. It is essential that [DynamicN] is set properly before calling this. Existing values will be preserved with changes in DynamicN to the extent possible.

func SetTextureSRGBFromLinear

func SetTextureSRGBFromLinear(img *image.RGBA)

SetTextureSRGBFromLinear sets in place the pixel values to sRGB colorspace version of given linear colorspace image. This directly modifies the given image!

func SetTextureSRGBToLinear

func SetTextureSRGBToLinear(img *image.RGBA)

SetTextureSRGBToLinear sets in place the pixel values to linear colorspace version of sRGB colorspace image. This directly modifies the given image!

func SetValueFrom

func SetValueFrom[E any](vl *Value, from []E) error

SetValueFrom copies given values into value buffer memory, making the buffer if it has not yet been constructed. IMPORTANT: do not use this for dynamic offset Uniform or Storage variables, as the alignment will not be correct; See [SetDynamicFromBytes].

func Terminate

func Terminate()

Terminate shuts down the WebGPU system -- call as last thing before quitting. IMPORTANT: must be called on the main initial thread!

func TextureSRGBFromLinear

func TextureSRGBFromLinear(img *image.RGBA) *image.RGBA

TextureSRGBFromLinear returns a sRGB colorspace version of given linear colorspace image

func TextureSRGBToLinear

func TextureSRGBToLinear(img *image.RGBA) *image.RGBA

TextureSRGBToLinear returns a linear colorspace version of sRGB colorspace image

func ValueReadSync added in v0.3.3

func ValueReadSync(device *Device, values ...*Value) error

ValueReadSync does a MapAsync on given Values, waiting on the device until the sync is complete, and returning error if any issues. It is more efficient to get all relevant buffers at the same time.

func Warps

func Warps(n, threads int) int

Warps returns the number of warps (work goups of compute threads) that is sufficient to compute n elements, given specified number of threads per this dimension. It just rounds up to nearest even multiple of n divided by threads: Ceil(n / threads)

Types

type BorderColors

type BorderColors int32 //enums:enum -trim-prefix Border

Texture image sampler modes

const (
	// Repeat the texture when going beyond the image dimensions.
	BorderTrans BorderColors = iota
	BorderBlack
	BorderWhite
)
const BorderColorsN BorderColors = 3

BorderColorsN is the highest valid value for type BorderColors, plus one.

func BorderColorsValues

func BorderColorsValues() []BorderColors

BorderColorsValues returns all possible values for the type BorderColors.

func (BorderColors) Desc

func (i BorderColors) Desc() string

Desc returns the description of the BorderColors value.

func (BorderColors) Int64

func (i BorderColors) Int64() int64

Int64 returns the BorderColors value as an int64.

func (BorderColors) MarshalText

func (i BorderColors) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*BorderColors) SetInt64

func (i *BorderColors) SetInt64(in int64)

SetInt64 sets the BorderColors value from an int64.

func (*BorderColors) SetString

func (i *BorderColors) SetString(s string) error

SetString sets the BorderColors value from its string representation, and returns an error if the string is invalid.

func (BorderColors) String

func (i BorderColors) String() string

String returns the string representation of this BorderColors value.

func (*BorderColors) UnmarshalText

func (i *BorderColors) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (BorderColors) Values

func (i BorderColors) Values() []enums.Enum

Values returns all possible values for the type BorderColors.

type ComputePipeline

type ComputePipeline struct {
	Pipeline
	// contains filtered or unexported fields
}

ComputePipeline is a compute pipeline, which runs shader code on vars data.

func NewComputePipeline added in v0.3.3

func NewComputePipeline(name string, sy System) *ComputePipeline

NewComputePipeline returns a new ComputePipeline.

func NewComputePipelineShaderFS added in v0.3.3

func NewComputePipelineShaderFS(fsys fs.FS, fname string, sy *ComputeSystem) *ComputePipeline

NewComputePipelineShaderFS returns a new ComputePipeline, opening the given shader code file from given filesystem, and setting the name of the pipeline to the filename (without paths or extensions). The shader entry point is "main". This is a convenience method for standard case where there is one shader program per pipeline.

func (*ComputePipeline) BindAllGroups added in v0.3.3

func (pl *ComputePipeline) BindAllGroups(ce *wgpu.ComputePassEncoder)

BindAllGroups binds the Current Value for all variables across all variable groups, as the Value to use by shader. Automatically called in BindPipeline at start of render for pipeline. Be sure to set Current index to correct value before calling!

func (*ComputePipeline) BindGroup added in v0.3.3

func (pl *ComputePipeline) BindGroup(ce *wgpu.ComputePassEncoder, group int)

BindGroup binds the Current Value for all variables in given variable group, as the Value to use by shader. Be sure to set Current index to correct value before calling!

func (*ComputePipeline) BindPipeline added in v0.3.3

func (pl *ComputePipeline) BindPipeline(ce *wgpu.ComputePassEncoder) error

BindPipeline binds this pipeline as the one to use for next commands in the given compute pass. This also calls BindAllGroups, to bind the Current Value for all variables. Be sure to set the desired Current value prior to calling.

func (*ComputePipeline) Config added in v0.3.3

func (pl *ComputePipeline) Config(rebuild bool) error

Config is called once all the Config options have been set using Set* methods, and the shaders have been loaded. The parent ComputeSystem has already done what it can for its config. The rebuild flag indicates whether pipelines should rebuild

func (*ComputePipeline) Dispatch added in v0.3.3

func (pl *ComputePipeline) Dispatch(ce *wgpu.ComputePassEncoder, nx, ny, nz int) error

Dispatch adds commands to given compute encoder to run this pipeline for given number of *warps* (work groups of compute threads) along 3 dimensions, which then generate indexes passed into the shader. Calls BindPipeline and then DispatchWorkgroups. In WGSL, the @workgroup_size(x, y, z) directive specifies the number of threads allocated per warp -- the actual number of elements processed is threads * warps per each dimension. See Warps function. The hardware typically has 32 (NVIDIA, M1, M2) or 64 (AMD) hardware threads per warp, and so 64 is typically used as a default sum of threads per warp across all of the dimensions. Can use subsets of dimensions by using 1 for the other dimensions, and see [Dispatch1D] for a convenience method that automatically computes the number of warps for a 1D compute shader (everthing in x).

func (*ComputePipeline) Dispatch1D added in v0.3.3

func (pl *ComputePipeline) Dispatch1D(ce *wgpu.ComputePassEncoder, n, threads int) error

Dispatch1D adds commands to given compute encoder to run this pipeline for given number of computational elements along the first (X) dimension, for given number *elements* (threads) per warp (typically 64). See [Dispatch] for full info. This is just a convenience method for common 1D case that calls the Warps method for you.

func (*ComputePipeline) Release added in v0.3.3

func (pl *ComputePipeline) Release()

type ComputeSystem added in v0.3.3

type ComputeSystem struct {
	// optional name of this ComputeSystem
	Name string

	// ComputePipelines by name
	ComputePipelines map[string]*ComputePipeline

	// CommandEncoder is the command encoder created in
	// [BeginComputePass], and released in [EndComputePass].
	CommandEncoder *wgpu.CommandEncoder
	// contains filtered or unexported fields
}

ComputeSystem manages a system of ComputePipelines that all share a common collection of Vars and Values.

func NewComputeSystem added in v0.3.3

func NewComputeSystem(gp *GPU, name string) *ComputeSystem

NewComputeSystem returns a new ComputeSystem, initialized with its own new device that is owned by the system.

func (*ComputeSystem) AddComputePipeline added in v0.3.3

func (sy *ComputeSystem) AddComputePipeline(name string) *ComputePipeline

AddComputePipeline adds a new ComputePipeline to the system

func (*ComputeSystem) BeginComputePass added in v0.3.3

func (sy *ComputeSystem) BeginComputePass() (*wgpu.ComputePassEncoder, error)

BeginComputePass adds commands to the given command buffer to start the compute pass, returning the encoder object to which further compute commands should be added. Call [EndComputePass] when done.

func (*ComputeSystem) Config added in v0.3.3

func (sy *ComputeSystem) Config()

Config configures the entire system, after Pipelines and Vars have been initialized. After this point, just need to set values for the vars, and then do compute passes. This should not need to be called more than once.

func (*ComputeSystem) Device added in v0.3.3

func (sy *ComputeSystem) Device() *Device

func (*ComputeSystem) EndComputePass added in v0.3.3

func (sy *ComputeSystem) EndComputePass(ce *wgpu.ComputePassEncoder) error

EndComputePass submits the current compute commands to the device Queue and releases the [CommandEncoder] and the given ComputePassEncoder. You must call ce.End prior to calling this. Can insert other commands after ce.End, e.g., to copy data back from the GPU, prior to calling EndComputePass.

func (*ComputeSystem) GPU added in v0.3.3

func (sy *ComputeSystem) GPU() *GPU

func (*ComputeSystem) NewCommandEncoder added in v0.3.3

func (sy *ComputeSystem) NewCommandEncoder() (*wgpu.CommandEncoder, error)

NewCommandEncoder returns a new CommandEncoder for encoding compute commands. This is automatically called by BeginRenderPass and the result maintained in [CommandEncoder].

func (*ComputeSystem) Release added in v0.3.3

func (sy *ComputeSystem) Release()

func (*ComputeSystem) Render added in v0.3.3

func (sy *ComputeSystem) Render() *Render

func (*ComputeSystem) Vars added in v0.3.3

func (sy *ComputeSystem) Vars() *Vars

func (*ComputeSystem) WaitDone added in v0.3.3

func (sy *ComputeSystem) WaitDone()

WaitDone waits until device is done with current processing steps

type Device

type Device struct {
	// logical device
	Device *wgpu.Device

	// queue for device
	Queue *wgpu.Queue
}

Device holds Device and associated Queue info. A Device is a usable instance of the GPU Adapter hardware. Each device has one Queue.

func NewDevice

func NewDevice(gpu *GPU) (*Device, error)

NewDevice returns a new device for given GPU. It gets the Queue for this device.

func (*Device) Release

func (dv *Device) Release()

func (*Device) WaitDone

func (dv *Device) WaitDone()

WaitDone does a blocking wait until the device is done with current work.

func (*Device) WaitDoneFunc

func (dv *Device) WaitDoneFunc(fun func())

WaitDoneFunc waits until the device is idle and then calls given function, if the device is ready. If it is in some other bad state, that generates a panic.

type GPU

type GPU struct {
	// Instance represents the WebGPU system overall
	Instance *wgpu.Instance

	// GPU represents the specific GPU hardware device used.
	// You can call GetInfo() to get info.
	GPU *wgpu.Adapter

	// name of the physical GPU device
	DeviceName string

	// Properties are the general properties of the GPU adapter.
	Properties wgpu.AdapterInfo

	// Limits are the limits of the current GPU adapter.
	Limits wgpu.SupportedLimits

	// ComputeOnly indicates if this GPU is only used for compute,
	// which determines if it listens to WEBGPU_COMPUTE_DEVICE_SELECT
	// environment variable, allowing different compute devices to be
	// selected vs. graphics devices.
	ComputeOnly bool

	// maximum number of compute threads per compute shader invocation,
	// for a 1D number of threads per Warp, which is generally greater
	// than MaxComputeWorkGroup, which allows for the maxima as well.
	// This is not defined anywhere in the formal spec, unfortunately,
	// but has been determined empirically for Mac and NVIDIA which are
	// two of the most relevant use-cases.  If not a known case,
	// the MaxComputeWorkGroupvalue is used, which can significantly
	// slow down compute processing if more could actually be used.
	// Please file an issue or PR for other GPUs with known larger values.
	MaxComputeWorkGroupCount1D int
}

GPU represents the GPU hardware

func NewComputeGPU

func NewComputeGPU() *GPU

NewComputeGPU returns a new GPU, configured and ready to use, for purely compute use, which causes it to listen to use the WEBGPU_COMPUTE_DEVICE_SELECT variable for which GPU device to use.

func NewGPU

func NewGPU() *GPU

NewGPU returns a new GPU, configured and ready to use. If only doing compute, use NewComputeGPU.

func (*GPU) NewDevice

func (gp *GPU) NewDevice() (*Device, error)

NewDevice returns a new device for given GPU. It gets the Queue for this device.

func (*GPU) PropertiesString

func (gp *GPU) PropertiesString() string

PropertiesString returns a human-readable summary of the GPU properties.

func (*GPU) Release

func (gp *GPU) Release()

Release releases GPU resources -- call after everything else has been destroyed

func (*GPU) SelectGPU

func (gp *GPU) SelectGPU(gpus []*wgpu.Adapter) int

type GraphicsPipeline

type GraphicsPipeline struct {
	Pipeline

	// Primitive has various settings for graphics primitives,
	// e.g., TriangleList
	Primitive wgpu.PrimitiveState

	Multisample wgpu.MultisampleState

	// AlphaBlend determines whether to do alpha blending or not.
	AlphaBlend bool
	// contains filtered or unexported fields
}

GraphicsPipeline is a Pipeline specifically for the Graphics stack. In this context, each pipeline could handle a different class of materials (textures, Phong lighting, etc). There must be two shader-names

func NewGraphicsPipeline

func NewGraphicsPipeline(name string, sy *GraphicsSystem) *GraphicsPipeline

NewGraphicsPipeline returns a new GraphicsPipeline.

func (*GraphicsPipeline) BindAllGroups

func (pl *GraphicsPipeline) BindAllGroups(rp *wgpu.RenderPassEncoder)

BindAllGroups binds the Current Value for all variables across all variable groups, as the Value to use by shader. Automatically called in BindPipeline at start of render for pipeline. Be sure to set Current index to correct value before calling!

func (*GraphicsPipeline) BindDrawIndexed

func (pl *GraphicsPipeline) BindDrawIndexed(rp *wgpu.RenderPassEncoder)

BindDrawIndexed binds the Current Value for all VertexGroup variables, as the vertex data, and then does a DrawIndexed call.

func (*GraphicsPipeline) BindGroup

func (pl *GraphicsPipeline) BindGroup(rp *wgpu.RenderPassEncoder, group int)

BindGroup binds the Current Value for all variables in given variable group, as the Value to use by shader. Be sure to set Current index to correct value before calling!

func (*GraphicsPipeline) BindPipeline

func (pl *GraphicsPipeline) BindPipeline(rp *wgpu.RenderPassEncoder) error

BindPipeline binds this pipeline as the one to use for next commands in the given render pass. This also calls BindAllGroups, to bind the Current Value for all variables, excluding Vertex level variables: use BindVertex for that. Be sure to set the desired Current value prior to calling.

func (*GraphicsPipeline) BindVertex

func (pl *GraphicsPipeline) BindVertex(rp *wgpu.RenderPassEncoder)

BindVertex binds the Current Value for all VertexGroup variables, as the vertex data to use for next DrawIndexed call.

func (*GraphicsPipeline) Config

func (pl *GraphicsPipeline) Config(rebuild bool) error

Config is called once all the Config options have been set using Set* methods, and the shaders have been loaded. The parent GraphicsSystem has already done what it can for its config. The rebuild flag indicates whether pipelines should rebuild

func (*GraphicsPipeline) DrawIndexed

func (pl *GraphicsPipeline) DrawIndexed(rp *wgpu.RenderPassEncoder)

DrawVertex adds commands to the given command encoder to Draw based on current Index and Vertex values.

func (*GraphicsPipeline) FragmentEntry

func (pl *GraphicsPipeline) FragmentEntry() *ShaderEntry

FragmentEntry returns the ShaderEntry for FragmentShader. Can be nil if no vertex shader defined.

func (*GraphicsPipeline) Release

func (pl *GraphicsPipeline) Release()

func (*GraphicsPipeline) SetAlphaBlend

func (pl *GraphicsPipeline) SetAlphaBlend(alphaBlend bool)

SetAlphaBlend determines the alpha (transparency) blending function: either 1-source alpha (alphaBlend) or no blending: new color overwrites old. Default is alphaBlend = true

func (*GraphicsPipeline) SetCullMode

func (pl *GraphicsPipeline) SetCullMode(mode wgpu.CullMode) *GraphicsPipeline

SetCullMode sets the face culling mode.

func (*GraphicsPipeline) SetFrontFace

func (pl *GraphicsPipeline) SetFrontFace(face wgpu.FrontFace) *GraphicsPipeline

SetFrontFace sets the winding order for what counts as a front face. Default is CW.

func (*GraphicsPipeline) SetGraphicsDefaults

func (pl *GraphicsPipeline) SetGraphicsDefaults() *GraphicsPipeline

SetGraphicsDefaults configures all the default settings for a graphics rendering pipeline (not for a compute pipeline)

func (*GraphicsPipeline) SetLineWidth

func (pl *GraphicsPipeline) SetLineWidth(lineWidth float32)

SetLineWidth sets the rendering line width -- 1 is default.

func (*GraphicsPipeline) SetTopology

func (pl *GraphicsPipeline) SetTopology(topo Topologies, restartEnable bool) *GraphicsPipeline

SetTopology sets the topology of vertex position data. TriangleList is the default. Also for Strip modes, restartEnable allows restarting a new strip by inserting a ??

func (*GraphicsPipeline) VertexEntry

func (pl *GraphicsPipeline) VertexEntry() *ShaderEntry

VertexEntry returns the ShaderEntry for VertexShader. Can be nil if no vertex shader defined.

type GraphicsSystem

type GraphicsSystem struct {
	// optional name of this GraphicsSystem
	Name string

	// GraphicsPipelines by name
	GraphicsPipelines map[string]*GraphicsPipeline

	// Renderer is the rendering target for this system,
	// It is either a Surface or a RenderTexture.
	Renderer Renderer

	// CurrentCommandEncoder is the command encoder created in
	// [GraphicsSystem.BeginRenderPass], and released in [GraphicsSystem.EndRenderPass].
	CommandEncoder *wgpu.CommandEncoder
	// contains filtered or unexported fields
}

GraphicsSystem manages a system of Pipelines that all share a common collection of Vars and Values. For example, this could be a collection of different pipelines for different material types. The System provides a simple top-level API for the whole render process.

func NewGraphicsSystem

func NewGraphicsSystem(gp *GPU, name string, rd Renderer) *GraphicsSystem

NewGraphicsSystem returns a new GraphicsSystem, using the given Renderer as the render target.

func (*GraphicsSystem) AddGraphicsPipeline

func (sy *GraphicsSystem) AddGraphicsPipeline(name string) *GraphicsPipeline

AddGraphicsPipeline adds a new GraphicsPipeline to the system

func (*GraphicsSystem) BeginRenderPass

func (sy *GraphicsSystem) BeginRenderPass() (*wgpu.RenderPassEncoder, error)

BeginRenderPass adds commands to the given command buffer to start the render pass using the Renderer configured for this system, and returns the encoder object to which further rendering commands should be added. Call [EndRenderPass] when done. This version Clears the target texture first, using ClearValues.

func (*GraphicsSystem) BeginRenderPassNoClear

func (sy *GraphicsSystem) BeginRenderPassNoClear() (*wgpu.RenderPassEncoder, error)

BeginRenderPassNoClear adds commands to the given command buffer to start the render pass using the Renderer configured for this system, and returns the encoder object to which further rendering commands should be added. Call [EndRenderPass] when done. This version does NOT clear the target texture first, so the prior render output is carried over.

func (*GraphicsSystem) Config

func (sy *GraphicsSystem) Config()

Config configures the entire system, after Pipelines and Vars have been initialized. After this point, just need to set values for the vars, and then do render passes. This should not need to be called more than once.

func (*GraphicsSystem) Device

func (sy *GraphicsSystem) Device() *Device

func (*GraphicsSystem) EndRenderPass

func (sy *GraphicsSystem) EndRenderPass(rp *wgpu.RenderPassEncoder)

EndRenderPass ends the render pass started by [BeginRenderPass], by calling [SubmitRender] to submit the rendering commands to the device, and calling Present() on the Renderer to show results.

func (*GraphicsSystem) GPU

func (sy *GraphicsSystem) GPU() *GPU

func (*GraphicsSystem) NewCommandEncoder

func (sy *GraphicsSystem) NewCommandEncoder() (*wgpu.CommandEncoder, error)

NewCommandEncoder returns a new CommandEncoder for encoding rendering commands. This is automatically called by BeginRenderPass and the result maintained in CurrentCommandEncoder.

func (*GraphicsSystem) Release

func (sy *GraphicsSystem) Release()

func (*GraphicsSystem) Render

func (sy *GraphicsSystem) Render() *Render

func (*GraphicsSystem) SetAlphaBlend

func (sy *GraphicsSystem) SetAlphaBlend(alphaBlend bool) *GraphicsSystem

SetAlphaBlend determines the alpha (transparency) blending function: either 1-source alpha (alphaBlend) or no blending: new color overwrites old. Default is alphaBlend = true For all pipelines, to keep graphics settings consistent.

func (*GraphicsSystem) SetClearColor

func (sy *GraphicsSystem) SetClearColor(c color.Color) *GraphicsSystem

SetClearColor sets the RGBA colors to set when starting new render For all pipelines, to keep graphics settings consistent.

func (*GraphicsSystem) SetClearDepthStencil

func (sy *GraphicsSystem) SetClearDepthStencil(depth float32, stencil uint32) *GraphicsSystem

SetClearDepthStencil sets the depth and stencil values when starting new render For all pipelines, to keep graphics settings consistent.

func (*GraphicsSystem) SetCullMode

func (sy *GraphicsSystem) SetCullMode(mode wgpu.CullMode) *GraphicsSystem

SetCullMode sets the face culling mode.

func (*GraphicsSystem) SetFrontFace

func (sy *GraphicsSystem) SetFrontFace(face wgpu.FrontFace) *GraphicsSystem

SetFrontFace sets the winding order for what counts as a front face.

func (*GraphicsSystem) SetGraphicsDefaults

func (sy *GraphicsSystem) SetGraphicsDefaults() *GraphicsSystem

SetGraphicsDefaults configures all the default settings for all graphics rendering pipelines (not for a compute pipeline)

func (*GraphicsSystem) SetLineWidth

func (sy *GraphicsSystem) SetLineWidth(lineWidth float32) *GraphicsSystem

SetLineWidth sets the rendering line width -- 1 is default.

func (*GraphicsSystem) SetSize

func (sy *GraphicsSystem) SetSize(size image.Point)

When the render surface (e.g., window) is resized, call this function. WebGPU does not have any internal mechanism for tracking this, so we need to drive it from external events.

func (*GraphicsSystem) SetTopology

func (sy *GraphicsSystem) SetTopology(topo Topologies, restartEnable bool) *GraphicsSystem

SetTopology sets the topology of vertex position data. TriangleList is the default. Also for Strip modes, restartEnable allows restarting a new strip by inserting a ?? For all pipelines, to keep graphics settings consistent.

func (*GraphicsSystem) SubmitRender

func (sy *GraphicsSystem) SubmitRender(rp *wgpu.RenderPassEncoder) error

SubmitRender submits the current render commands to the device Queue and releases the [CurrentCommandEncoder] and the given RenderPassEncoder. You must call rp.End prior to calling this. Can insert other commands after rp.End, e.g., to copy the rendered image, prior to calling SubmitRender.

func (*GraphicsSystem) Vars

func (sy *GraphicsSystem) Vars() *Vars

func (*GraphicsSystem) WaitDone

func (sy *GraphicsSystem) WaitDone()

WaitDone waits until device is done with current processing steps

type Pipeline

type Pipeline struct {
	// unique name of this pipeline
	Name string

	// System that we belong to and manages shared resources:
	// Vars, Values, etc
	System System

	// Shaders contains actual shader code loaded for this pipeline.
	// A single shader can have multiple entry points: see Entries.
	Shaders map[string]*Shader

	// Entries contains the entry points into shader code,
	// which are what is actually called.
	Entries map[string]*ShaderEntry
}

Pipeline is the shared Base for Graphics and Compute Pipelines. It manages Shader program(s) that accomplish a specific type of rendering or compute function, using Vars / Values defined by the overall GraphicsSystem. In the graphics context, each pipeline could handle a different class of materials (textures, Phong lighting, etc).

func (*Pipeline) AddEntry

func (pl *Pipeline) AddEntry(sh *Shader, typ ShaderTypes, entry string) *ShaderEntry

AddEntry adds ShaderEntry for given shader, ShaderTypes, and entry function name.

func (*Pipeline) AddShader

func (pl *Pipeline) AddShader(name string) *Shader

AddShader adds Shader with given name to the pipeline

func (*Pipeline) EntryByName

func (pl *Pipeline) EntryByName(name string) *ShaderEntry

EntryByName returns ShaderEntry by name, which is Shader:Entry. Returns nil if not found (error auto logged).

func (*Pipeline) EntryByType

func (pl *Pipeline) EntryByType(typ ShaderTypes) *ShaderEntry

EntryByType returns ShaderEntry by ShaderType. Returns nil if not found.

func (*Pipeline) ShaderByName

func (pl *Pipeline) ShaderByName(name string) *Shader

ShaderByName returns Shader by name. Returns nil if not found (error auto logged).

func (*Pipeline) Vars

func (pl *Pipeline) Vars() *Vars

Vars returns a pointer to the vars for this pipeline, which has Values within it.

type Render

type Render struct {
	// texture format information for the texture target we render to.
	// critically, this can be different from the surface actual format
	// in the case when that format is non-srgb, as is the case in web browsers.
	Format TextureFormat

	// the associated depth buffer, if set
	Depth Texture

	// if this is not UndefinedType, depth format is used
	DepthFormat Types

	// for multisampling, this is the multisampled image that is the actual render target
	Multi Texture

	// is true if multsampled image configured
	HasMulti bool

	// host-accessible image that is used to transfer back
	// from a render color attachment to host memory.
	// Requires a different format than color attachment
	Grab Texture

	// values for clearing image when starting render pass
	ClearColor color.Color

	ClearDepth float32

	ClearStencil uint32
	// contains filtered or unexported fields
}

Render manages various elements needed for rendering, including a function to get a WebGPU RenderPass object, which specifies parameters for rendering to a Texture. It holds the Depth buffer if one is used, and a multisampling image too. The Render object is owned by a Renderer (Surface or RenderTexture).

func (*Render) BeginRenderPass

func (rd *Render) BeginRenderPass(cmd *wgpu.CommandEncoder, view *wgpu.TextureView) *wgpu.RenderPassEncoder

BeginRenderPass adds commands to the given command buffer to start the render pass on given framebuffer. Clears the frame first, according to the ClearValues See BeginRenderPassNoClear for non-clearing version.

func (*Render) BeginRenderPassNoClear

func (rd *Render) BeginRenderPassNoClear(cmd *wgpu.CommandEncoder, view *wgpu.TextureView) *wgpu.RenderPassEncoder

BeginRenderPassNoClear adds commands to the given command buffer to start the render pass on given framebuffer. does NOT clear the frame first -- loads prior state.

func (*Render) ClearRenderPass

func (rd *Render) ClearRenderPass(view *wgpu.TextureView) *wgpu.RenderPassDescriptor

ClearRenderPass returns a render pass descriptor that clears the framebuffer

func (*Render) Config

func (rd *Render) Config(dev *Device, imgFmt *TextureFormat, depthFmt Types)

Config configures the render pass for given device, Using standard parameters for graphics rendering, based on the given image format and depth image format (pass UndefinedType for no depth buffer, or Depth32).

func (*Render) ConfigGrab

func (rd *Render) ConfigGrab(dev *Device)

ConfigGrab configures the Grab for copying rendered image back to host memory. Uses format of current Texture.

func (*Render) ConfigGrabDepth

func (rd *Render) ConfigGrabDepth(dev *Device)

ConfigGrabDepth configures the GrabDepth for copying depth image back to host memory. Uses format of current Depth image.

func (*Render) DepthTextureArray

func (rd *Render) DepthTextureArray() ([]float32, error)

DepthTextureArray returns the float values from the last GrabDepthTexture call automatically handles down-sampling from multisampling.

func (*Render) GrabDepthTexture

func (rd *Render) GrabDepthTexture(dev *Device, cmd *wgpu.CommandEncoder) error

GrabDepthTexture grabs the current render depth image, using given command buffer which must have the cmdBegin called already. Uses the GrabDepth Storage Buffer. call this after: sys.MemCmdEndSubmitWaitFree()

func (*Render) LoadRenderPass

func (rd *Render) LoadRenderPass(view *wgpu.TextureView) *wgpu.RenderPassDescriptor

LoadRenderPass returns a render pass descriptor that loads previous framebuffer

func (*Render) Release

func (rd *Render) Release()

func (*Render) SetDepthDescriptor

func (rd *Render) SetDepthDescriptor(rpd *wgpu.RenderPassDescriptor)

func (*Render) SetSize

func (rd *Render) SetSize(sz image.Point)

type RenderTexture

type RenderTexture struct {

	// Format has the current image format and dimensions.
	// The Samples here are the desired value, whereas our Frames
	// always have Samples = 1, and use render for multisampling.
	Format TextureFormat

	// number of frames to maintain in the simulated swapchain.
	// e.g., 2 = double-buffering, 3 = triple-buffering.
	NFrames int

	// Textures that we iterate through in rendering subsequent frames.
	Frames []*Texture

	// pointer to gpu device, for convenience
	GPU *GPU
	// contains filtered or unexported fields
}

RenderTexture is an offscreen, non-window-backed rendering target, functioning like a Surface.

func NewRenderTexture

func NewRenderTexture(gp *GPU, dev *Device, size image.Point, samples int, depthFmt Types) *RenderTexture

NewRenderTexture returns a new standalone texture render target for given GPU and device, suitable for offscreen rendering or intermediate use of the render output for other purposes.

  • device should be from a Surface if one is being used, otherwise can be created anew for offscreen rendering, and released at end.
  • size should reflect the actual size of the surface, and can be updated with SetSize method.
  • samples is the multisampling anti-aliasing parameter: 1 = none 4 = typical default value for smooth "no jaggy" edges.
  • depthFmt is the depth buffer format. use UndefinedType for none or Depth32 recommended for best performance.

func (*RenderTexture) ConfigFrames

func (rt *RenderTexture) ConfigFrames()

ConfigFrames configures the frames, calling ReleaseFrames so it is safe for re-use.

func (*RenderTexture) Defaults

func (rt *RenderTexture) Defaults()

func (*RenderTexture) Device

func (rt *RenderTexture) Device() *Device

func (*RenderTexture) GetCurrentTexture

func (rt *RenderTexture) GetCurrentTexture() (*wgpu.TextureView, error)

GetCurrentTexture returns a TextureView that is the current target for rendering.

func (*RenderTexture) GrabDepthTexture

func (rt *RenderTexture) GrabDepthTexture(cmd *wgpu.CommandEncoder)

GrabDepthTexture grabs rendered depth image from the Render, must have waited for render already.

func (*RenderTexture) GrabTexture

func (rt *RenderTexture) GrabTexture(cmd *wgpu.CommandEncoder, idx int)

GrabTexture grabs rendered image of given index to RenderTexture.TextureGrab. must have waited for render already.

func (*RenderTexture) Present

func (rt *RenderTexture) Present()

func (*RenderTexture) Release

func (rt *RenderTexture) Release()

func (*RenderTexture) ReleaseFrames

func (rt *RenderTexture) ReleaseFrames()

func (*RenderTexture) Render

func (rt *RenderTexture) Render() *Render

func (*RenderTexture) SetSize

func (rt *RenderTexture) SetSize(size image.Point)

SetSize sets the size for the render frame, doesn't do anything if already that size.

type Renderer

type Renderer interface {
	// GetCurrentTexture returns a TextureView that is the current
	// target for rendering.
	GetCurrentTexture() (*wgpu.TextureView, error)

	// Present presents the rendered texture to the window
	// and finalizes the current render pass.
	Present()

	// Device returns the device for this renderer,
	// which serves as the source device for the GraphicsSystem
	// and all of its components.
	Device() *Device

	// Render returns the Render object for this renderer,
	// which supports Multisampling and Depth buffers,
	// and handles all the render pass logic and state.
	Render() *Render

	// When the render surface (e.g., window) is resized, call this function.
	// WebGPU does not have any internal mechanism for tracking this, so we
	// need to drive it from external events.
	SetSize(size image.Point)
}

Renderer is an interface for something that can actually be rendered to. It returns a TextureView to render into, and then Presents the result. Surface and RenderTexture are the two main implementers of this interface.

type Sampler

type Sampler struct {
	Name string

	// for U (horizontal) axis -- what to do when going off the edge
	UMode SamplerModes

	// for V (vertical) axis -- what to do when going off the edge
	VMode SamplerModes

	// for W (horizontal) axis -- what to do when going off the edge
	WMode SamplerModes

	// border color for Clamp modes
	Border BorderColors
	// contains filtered or unexported fields
}

Sampler represents a WebGPU image sampler

func (*Sampler) Config

func (sm *Sampler) Config(dev *Device) error

Config configures sampler on device. If the sampler already exists, then it is not reconfigured. Use Release first to force a reconfigure.

func (*Sampler) Defaults

func (sm *Sampler) Defaults()

func (*Sampler) Release

func (sm *Sampler) Release()

type SamplerModes

type SamplerModes int32 //enums:enum

Texture image sampler modes

const (
	// Repeat the texture when going beyond the image dimensions.
	Repeat SamplerModes = iota

	// Like repeat, but inverts the coordinates to mirror the image when going beyond the dimensions.
	MirrorRepeat

	// Take the color of the edge closest to the coordinate beyond the image dimensions.
	ClampToEdge
)
const SamplerModesN SamplerModes = 3

SamplerModesN is the highest valid value for type SamplerModes, plus one.

func SamplerModesValues

func SamplerModesValues() []SamplerModes

SamplerModesValues returns all possible values for the type SamplerModes.

func (SamplerModes) Desc

func (i SamplerModes) Desc() string

Desc returns the description of the SamplerModes value.

func (SamplerModes) Int64

func (i SamplerModes) Int64() int64

Int64 returns the SamplerModes value as an int64.

func (SamplerModes) MarshalText

func (i SamplerModes) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (SamplerModes) Mode

func (sm SamplerModes) Mode() wgpu.AddressMode

func (*SamplerModes) SetInt64

func (i *SamplerModes) SetInt64(in int64)

SetInt64 sets the SamplerModes value from an int64.

func (*SamplerModes) SetString

func (i *SamplerModes) SetString(s string) error

SetString sets the SamplerModes value from its string representation, and returns an error if the string is invalid.

func (SamplerModes) String

func (i SamplerModes) String() string

String returns the string representation of this SamplerModes value.

func (*SamplerModes) UnmarshalText

func (i *SamplerModes) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (SamplerModes) Values

func (i SamplerModes) Values() []enums.Enum

Values returns all possible values for the type SamplerModes.

type Shader

type Shader struct {
	Name string
	// contains filtered or unexported fields
}

Shader manages a single Shader program, which can have multiple entry points. See ShaderEntry for entry points into Shaders.

func NewShader

func NewShader(name string, dev *Device) *Shader

func (*Shader) OpenCode

func (sh *Shader) OpenCode(code string) error

OpenCode loads given WGSL ".wgl" code for the Shader.

func (*Shader) OpenFile

func (sh *Shader) OpenFile(fname string) error

OpenFile loads given WGSL ".wgl" code from file for the Shader.

func (*Shader) OpenFileFS

func (sh *Shader) OpenFileFS(fsys fs.FS, fname string) error

OpenFileFS loads given WGSL ".wgl" code from file for the Shader.

func (*Shader) Release

func (sh *Shader) Release()

Release destroys the shader

type ShaderEntry

type ShaderEntry struct {
	// Shader has the code
	Shader *Shader

	// Type of shader entry point.
	Type ShaderTypes

	// Entry is the name of the function to call for this Entry.
	// Conventionally, it is some variant on "main"
	Entry string
}

ShaderEntry is an entry point into a Shader. There can be multiple entry points per shader.

func NewShaderEntry

func NewShaderEntry(sh *Shader, typ ShaderTypes, entry string) *ShaderEntry

NewShaderEntry returns a new ShaderEntry with given settings

type ShaderTypes

type ShaderTypes int32

ShaderTypes is a list of GPU shader types

const (
	UnknownShader ShaderTypes = iota
	VertexShader
	FragmentShader
	ComputeShader
)

type Surface

type Surface struct {

	// Format has the current rendering surface size and
	// rendering texture format.  This format may be different
	// from the actual physical swapchain format, in case there
	// is a different view (e.g., srgb)
	Format TextureFormat

	// pointer to gpu device, needed for properties.
	GPU *GPU

	sync.Mutex
	// contains filtered or unexported fields
}

Surface manages the physical device for the visible image of a window surface, and the swapchain for presenting images. It provides an encapsulated source of TextureView textures for the rendering process to draw on. It implements the Renderer interface, which defines the primary API (GetCurrentTexture() -> Present()).

func NewSurface

func NewSurface(gp *GPU, wsurf *wgpu.Surface, size image.Point, samples int, depthFmt Types) *Surface

NewSurface returns a new surface initialized for given GPU and WebGPU Surface handle, obtained from a valid window.

  • size should reflect the actual size of the surface, and can be updated with SetSize method.
  • samples is the multisampling anti-aliasing parameter: 1 = none 4 = typical default value for smooth "no jaggy" edges.
  • depthFmt is the depth buffer format. use UndefinedType for none or Depth32 recommended for best performance.

func (*Surface) Config

func (sf *Surface) Config()

Config configures the surface based on the surface configuration.

func (*Surface) Defaults

func (sf *Surface) Defaults()

func (*Surface) Device

func (sf *Surface) Device() *Device

func (*Surface) GetCurrentTexture

func (sf *Surface) GetCurrentTexture() (*wgpu.TextureView, error)

GetCurrentTexture returns a TextureView that is the current target for rendering.

func (*Surface) InitConfig

func (sf *Surface) InitConfig() error

InitConfig does the initial configuration of the surface. This assumes that all existing items have been destroyed.

func (*Surface) Present

func (sf *Surface) Present()

Present is the final step for showing the rendered texture to the window. The current texture is automatically Released and Unlock() is called.

func (*Surface) Reconfig

func (sf *Surface) Reconfig() bool

Reconfig reconfigures the surface. This must be called when the window is resized. Must update the swapChainConfig parameters prior to calling! It returns false if the swapchain size is zero.

func (*Surface) Release

func (sf *Surface) Release()

func (*Surface) Render

func (sf *Surface) Render() *Render

func (*Surface) SetSize

func (sf *Surface) SetSize(sz image.Point)

When the render surface (e.g., window) is resized, call this function. WebGPU does not have any internal mechanism for tracking this, so we need to drive it from external events.

type System

type System interface {
	// vars represents all the data variables used by the system,
	// with one Var for each resource that is made visible to the shader,
	// indexed by Group (@group) and Binding (@binding).
	// Each Var has Value(s) containing specific instance values.
	Vars() *Vars

	//	Device is the logical device for this system, typically from
	// the Renderer (Surface) or owned by a ComputeSystem.
	Device() *Device

	// GPU is our GPU device, which has properties
	// and alignment factors.
	GPU() *GPU

	// Render returns the Render object, for a GraphicsSystem
	// (nil for a ComputeSystem).
	Render() *Render
}

System provides the general interface for [GraphicSystem] and ComputeSystem.

type Texture

type Texture struct {
	// Name of the texture, e.g., same as Value name if used that way.
	// This is helpful for debugging. Is auto-set to filename if loaded from
	// a file and otherwise empty.
	Name string

	// Format & size of texture
	Format TextureFormat

	// Sampler defines how the texture is sampled on the GPU.
	// Needed for textures used as fragment shader inputs.
	Sampler Sampler

	// current size of the readBuffer
	ReadBufferDims TextureBufferDims
	// contains filtered or unexported fields
}

Texture represents a WebGPU Texture with an associated TextureView. The WebGPU Texture is in device memory, in an optimized format.

func NewTexture

func NewTexture(dev *Device) *Texture

func (*Texture) ConfigDepth

func (tx *Texture) ConfigDepth(dev *Device, depthType Types, imgFmt *TextureFormat) error

ConfigDepth configures this texture as a depth texture using given depth texture format, and other format information from the given render texture format. If current texture is identical format, does not recreate.

func (*Texture) ConfigGoImage

func (tx *Texture) ConfigGoImage(sz image.Point, layers int)

ConfigGoImage configures the texture for storing an texture of the given size. Texture format will be set to default unless format is already set. Layers is number of separate textures of given size allocated in a texture array.

func (*Texture) ConfigMulti

func (tx *Texture) ConfigMulti(dev *Device, imgFmt *TextureFormat) error

ConfigMulti configures this texture as a mutisampling texture using format.

func (*Texture) ConfigReadBuffer

func (tx *Texture) ConfigReadBuffer() error

ConfigReadBuffer configures the [readBuffer] for this Texture. Must have this in place prior to render pass with a [CopyToReadBuffer] command added to it.

func (*Texture) ConfigRenderTexture

func (tx *Texture) ConfigRenderTexture(dev *Device, imgFmt *TextureFormat) error

ConfigRenderTexture configures this texture as a render texture using format. Sets multisampling to 1, layers to 1.

func (*Texture) CopyToReadBuffer

func (tx *Texture) CopyToReadBuffer(cmd *wgpu.CommandEncoder) error

CopyToReadBuffer adds a command to the given command encoder to copy this texture to its [readBuffer]. Must have called [ConfigReadBuffer] prior to start of render pass for this to work.

func (*Texture) CreateTexture

func (tx *Texture) CreateTexture(usage wgpu.TextureUsage) error

CreateTexture creates the texture based on current settings, and a view of that texture. Calls release first.

func (*Texture) ReadData

func (tx *Texture) ReadData(data *[]byte, removePadding bool) error

ReadData reads the data from a GPU-resident Texture, setting the given data bytes, which will be resized to fit the data. If removePadding is true, then extra padding will be removed, if present.

func (*Texture) ReadDataMapped

func (tx *Texture) ReadDataMapped() ([]byte, error)

ReadDataMapped reads the data from a GPU-resident Texture, returning the bytes as mapped from the readBuffer, so they must be used immediately, followed by an [UnmapReadData] call to unmap the data. See [ReadData] for a version that copies the data into a bytes slice, which is safe for indefinite use. There is alignment padding as reflected in the [ReadBufferDims] data.

func (*Texture) ReadGoImage

func (tx *Texture) ReadGoImage() (*image.NRGBA, error)

ReadGoImage reads the GPU-resident Texture and returns a Go image.NRGBA image of the texture.

func (*Texture) Release

func (tx *Texture) Release()

Release destroys any existing view, nils fields

func (*Texture) ReleaseTexture

func (tx *Texture) ReleaseTexture()

ReleaseTexture frees device memory version of texture that we own

func (*Texture) ReleaseView

func (tx *Texture) ReleaseView()

ReleaseView destroys any existing view

func (*Texture) SetFromGoImage

func (tx *Texture) SetFromGoImage(img image.Image, layer int) error

SetFromGoImage sets texture data from a standard Go texture at given layer. This is most efficiently done using an texture.RGBA, but other formats will be converted as necessary. This starts the full WriteTexture call to upload to device.

func (*Texture) SetShared

func (tx *Texture) SetShared(ot *Texture)

SetShared sets this texture to point to the given Texture's underlying GPU texture, with the shared flag set so that it will not be released.

func (*Texture) UnmapReadData

func (tx *Texture) UnmapReadData() error

UnmapReadData unmaps the data from a prior ReadDataMapped call.

type TextureBufferDims

type TextureBufferDims struct {
	Width           uint64
	Height          uint64
	UnpaddedRowSize uint64
	PaddedRowSize   uint64
}

TextureBufferDims represents the sizes required in Buffer to represent a texture of a given size.

func NewTextureBufferDims

func NewTextureBufferDims(size image.Point) *TextureBufferDims

func (*TextureBufferDims) HasNoPadding

func (td *TextureBufferDims) HasNoPadding() bool

HasNoPadding returns true if the Unpadded and Padded row sizes are the same.

func (*TextureBufferDims) PaddedSize

func (td *TextureBufferDims) PaddedSize() uint64

PaddedSize returns the total padded size of data

func (*TextureBufferDims) Set

func (td *TextureBufferDims) Set(size image.Point)

func (*TextureBufferDims) UnpaddedSize

func (td *TextureBufferDims) UnpaddedSize() uint64

UnpaddedSize returns the total unpadded size of data

type TextureFormat

type TextureFormat struct {
	// Size of image
	Size image.Point

	// Texture format: RGBA8UnormSrgb is default
	Format wgpu.TextureFormat

	// number of samples. set higher for RenderTexture rendering
	// but otherwise default of 1
	Samples int

	// number of layers for texture arrays
	Layers int
}

TextureFormat describes the size and WebGPU format of a Texture. If Layers > 1, all must be the same size.

func NewTextureFormat

func NewTextureFormat(width, height, layers int) *TextureFormat

NewTextureFormat returns a new TextureFormat with default format and given size and number of layers

func (*TextureFormat) Aspect

func (im *TextureFormat) Aspect() float32

Aspect returns the aspect ratio X / Y

func (*TextureFormat) Bounds

func (im *TextureFormat) Bounds() image.Rectangle

Bounds returns the rectangle defining this image: 0,0,w,h

func (*TextureFormat) BytesPerPixel

func (im *TextureFormat) BytesPerPixel() int

BytesPerPixel returns number of bytes required to represent one Pixel (in Host memory at least). TODO only works for known formats -- need to add more as needed.

func (*TextureFormat) Defaults

func (im *TextureFormat) Defaults()

func (*TextureFormat) Extent3D

func (im *TextureFormat) Extent3D() wgpu.Extent3D

func (*TextureFormat) IsRGBAUnorm

func (im *TextureFormat) IsRGBAUnorm() bool

IsRGBAUnorm returns true if image format is the wgpu.TextureFormatRGBA8Unorm format which is compatible with go image.RGBA format with colorspace conversion.

func (*TextureFormat) IsStdRGBA

func (im *TextureFormat) IsStdRGBA() bool

IsStdRGBA returns true if image format is the standard wgpu.TextureFormatRGBA8UnormSrgb which is compatible with go image.RGBA format.

func (*TextureFormat) LayerByteSize

func (im *TextureFormat) LayerByteSize() int

LayerByteSize returns number of bytes required to represent one layer of image in Host memory. TODO only works for known formats -- need to add more as needed.

func (*TextureFormat) Set

func (im *TextureFormat) Set(w, h int, ft wgpu.TextureFormat)

Set sets width, height and format

func (*TextureFormat) SetFormat

func (im *TextureFormat) SetFormat(ft Types)

SetFormat sets the format using vgpu standard Types

func (*TextureFormat) SetMultisample

func (im *TextureFormat) SetMultisample(nsamp int)

SetMultisample sets the number of multisampling to decrease aliasing 4 is typically sufficient. Values must be power of 2.

func (*TextureFormat) SetSize

func (im *TextureFormat) SetSize(w, h int)

SetSize sets the width, height

func (*TextureFormat) Size32

func (im *TextureFormat) Size32() (width, height uint32)

Size32 returns size as uint32 values

func (*TextureFormat) Stride

func (im *TextureFormat) Stride() int

Stride returns number of bytes per image row. TODO only works for known formats -- need to add more as needed.

func (*TextureFormat) String

func (im *TextureFormat) String() string

String returns human-readable version of format

func (*TextureFormat) TotalByteSize

func (im *TextureFormat) TotalByteSize() int

TotalByteSize returns total number of bytes required to represent all layers of images in Host memory. TODO only works for known formats -- need to add more as needed.

type Topologies

type Topologies int32 //enum:enum

Topologies are the different vertex topology

const (
	PointList Topologies = iota
	LineList
	LineStrip
	TriangleList
	TriangleStrip
)

func (Topologies) Primitive

func (tp Topologies) Primitive() wgpu.PrimitiveTopology

type Types

type Types int32 //enums:enum

Types is a list of supported GPU data types, which can be stored properly aligned in device memory, and used by the shader code. Note that a Vector3 or arrays of single scalar values such as Float32 are not well supported outside of Vertex due to the std410 convention: http://www.opengl.org/registry/doc/glspec45.core.pdf#page=159 The Struct type is particularly challenging as each member must be aligned in general on a 16 byte boundary (i.e., vector4) (unless all elements are exactly 4 bytes, which might work?). Go automatically aligns members to 8 bytes on 64 bit machines, but that doesn't quite cut it.

const (
	UndefinedType Types = iota
	Bool32

	Int16
	Uint16

	Int32
	Int32Vector2
	Int32Vector4

	Uint32
	Uint32Vector2
	Uint32Vector4

	Float32
	Float32Vector2
	Float32Vector3 // note: only use for vertex data -- not properly aligned for uniforms
	Float32Vector4

	Float32Matrix4 // std transform matrix: math32.Matrix4 works directly
	Float32Matrix3 // std transform matrix: math32.Matrix3 works directly

	TextureRGBA32 // 32 bits with 8 bits per component of R,G,B,A -- std image format
	TextureBGRA32

	Depth32         // standard float32 depth buffer
	Depth24Stencil8 // standard 24 bit float with 8 bit stencil

	Struct
)
const TypesN Types = 21

TypesN is the highest valid value for type Types, plus one.

func TypesValues

func TypesValues() []Types

TypesValues returns all possible values for the type Types.

func (Types) Bytes

func (tp Types) Bytes() int

Bytes returns number of bytes for this type

func (Types) Desc

func (i Types) Desc() string

Desc returns the description of the Types value.

func (Types) IndexType

func (tp Types) IndexType() wgpu.IndexFormat

IndexType returns the WebGPU VertexFormat for Index var. must be either Uint16 or Uint32.

func (Types) Int64

func (i Types) Int64() int64

Int64 returns the Types value as an int64.

func (Types) MarshalText

func (i Types) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*Types) SetInt64

func (i *Types) SetInt64(in int64)

SetInt64 sets the Types value from an int64.

func (*Types) SetString

func (i *Types) SetString(s string) error

SetString sets the Types value from its string representation, and returns an error if the string is invalid.

func (Types) String

func (i Types) String() string

String returns the string representation of this Types value.

func (Types) TextureFormat

func (tp Types) TextureFormat() wgpu.TextureFormat

TextureFormat returns the WebGPU TextureFormat for given type.

func (*Types) UnmarshalText

func (i *Types) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (Types) Values

func (i Types) Values() []enums.Enum

Values returns all possible values for the type Types.

func (Types) VertexFormat

func (tp Types) VertexFormat() wgpu.VertexFormat

VertexFormat returns the WebGPU VertexFormat for given type.

type Value

type Value struct {
	// name of this value, named by default as the variable name_idx
	Name string

	// index of this value within the Var list of values
	Index int

	// VarSize is the size of each Var element, which includes any fixed ArrayN
	// array size specified on the Var.
	VarSize int

	// DynamicIndex is the current index into a DynamicOffset variable
	// to use for the SetBindGroup call.  Note that this is an index,
	// not an offset, so it indexes the DynamicN Vars in the Value,
	// using the AlignVarSize to compute the dynamicOffset, which
	// is what is actually used.
	DynamicIndex int

	// AlignVarSize is VarSize subject to memory alignment constraints,
	// for DynamicN case.
	AlignVarSize int

	// AllocSize is total memory size of this value in bytes,
	// as allocated in the buffer.  For non-dynamic case, it is just VarSize.
	// For dynamic, it is dynamicN * AlignVarSize.
	AllocSize int

	// for SampledTexture Var roles, this is the Texture.
	// Can set Sampler parameters directly on this.
	Texture *Texture
	// contains filtered or unexported fields
}

Value represents a specific value of a Var variable, with its own WebGPU Buffer or Texture associated with it. The Current active Value index can be set in the corresponding Var.Values. The Buffer for a Uniform or Storage value is created on the first SetValueFrom call, or explicitly in [CreateBuffer]. To read memory back from the GPU, you must do [CreateReadBuffer] and use the steps oulined in [GPUToRead]. Use ad-hoc [ValueGroup]s to organize these batched read operations efficiently for the different groups of values that need to be read back in the different compute stages.

func NewValue

func NewValue(vr *Var, dev *Device, idx int) *Value

func (*Value) CreateBuffer

func (vl *Value) CreateBuffer() error

CreateBuffer creates the GPU buffer for this value if it does not yet exist or is not the right size.

func (*Value) CreateReadBuffer added in v0.3.3

func (vl *Value) CreateReadBuffer() error

CreateReadBuffer creates a read buffer for this value, if it does not yet exist or is not the right size. Read buffer is needed for reading values back from the GPU. Only for Storage role variables.

func (*Value) DynamicN

func (vl *Value) DynamicN() int

DynamicN returns the number of dynamic values currently configured.

func (*Value) GPUToRead added in v0.3.3

func (vl *Value) GPUToRead(cmd *wgpu.CommandEncoder) error

GPUToRead adds commands to the given command encoder to copy given value from its GPU buffer to the read buffer, which must have already been created. This is the first step for reading values back from the GPU, which starts with this command to be executed in the compute pass, and then requires ReadSync to actually read the data into the CPU side of the read buffer from the GPU, and ends with a final ReadToBytes call to copy the raw read bytes into a target data structure.

func (*Value) MemSize

func (vl *Value) MemSize() int

MemSize returns the memory allocation size for this value, in bytes.

func (*Value) NilBufferCheck

func (vl *Value) NilBufferCheck() error

NilBufferCheckCheck checks if buffer is nil, returning error if so

func (*Value) ReadSync added in v0.3.3

func (vl *Value) ReadSync() error

ReadSync reads data from GPU to CPU side of the read buffer. It is much more efficient to call ValueReadSync with _all_ values that need to be sync'd at the same time, so only use this when copying one value. See [GPUToRead] for overview of the process.

func (*Value) ReadToBytes added in v0.3.3

func (vl *Value) ReadToBytes(to []byte) error

ReadToBytes copies data from read buffer into given byte slice which is enforced to be the correct size if not already.

func (*Value) Release

func (vl *Value) Release()

Release releases the buffer / texture for this value

func (*Value) ReleaseRead added in v0.3.3

func (vl *Value) ReleaseRead()

ReleaseRead releases the read buffer

func (*Value) SetDynamicFromBytes

func (vl *Value) SetDynamicFromBytes(idx int, from []byte) error

SetDynamicFromBytes copies given values into a staging buffer at the given dynamic variable index, for dynamic offset Uniform or Storage variables, which have alignment constraints. See SetDynamicValueFrom, which should generally be used, for further info.

func (*Value) SetDynamicIndex

func (vl *Value) SetDynamicIndex(idx int) *Value

SetDynamicIndex sets the dynamic index to use for the current value, returning the value or nil if if the index was out of range (logs an error too).

func (*Value) SetDynamicN

func (vl *Value) SetDynamicN(n int)

SetDynamicN sets the number of dynamic values for this Value. If different, a new bindgroup must be generated.

func (*Value) SetFromBytes

func (vl *Value) SetFromBytes(from []byte) error

SetFromBytes copies given bytes into value buffer memory, making the buffer if it has not yet been constructed. IMPORTANT: do not use this for dynamic offset Uniform or Storage variables, as the alignment will not be correct; See [SetDynamicFromBytes].

func (*Value) SetFromGoImage

func (vl *Value) SetFromGoImage(img image.Image, layer int) *Texture

SetFromGoImage sets Texture image data from an image.Image standard Go image, at given layer. This is most efficiently done using an image.RGBA, but other formats will be converted as necessary. The Sampler is also configured at this point, with the current settings, so set those before making this call. It will not be re-configured without manually releasing it.

func (*Value) SetFromTexture

func (vl *Value) SetFromTexture(tx *Texture) *Texture

SetFromTexture sets Texture from an existing gpu Texture. The Sampler is also ensured configured at this point, with the current settings, so set those before making this call. It will not be re-configured without manually releasing it.

func (*Value) WriteDynamicBuffer

func (vl *Value) WriteDynamicBuffer() error

WriteDynamicBuffer writes the staging buffer up to the GPU device, after calling SetDynamicValueFrom for all the individual dynamic index cases that need to be updated. If this is not called, then the data will not be used!

type ValueGroups added in v0.3.3

type ValueGroups map[string][]*Value

ValueGroups provides named lists of value groups that can be used to simplify the calling of the multiple Read functions needed to read data back from the GPU.

func (*ValueGroups) Add added in v0.3.3

func (vg *ValueGroups) Add(name string, vals ...*Value)

Add Adds named group of values

func (ValueGroups) GPUToRead added in v0.3.3

func (vg ValueGroups) GPUToRead(name string, cmd *wgpu.CommandEncoder) error

GPUToRead adds commands to given command encoder to read values from the GPU to its read buffer. Next step is ReadSync after command has been submitted (EndComputePass).

func (ValueGroups) ReadSync added in v0.3.3

func (vg ValueGroups) ReadSync(name string) error

ReadSync does a MapAsync on values.

func (ValueGroups) ValuesByName added in v0.3.3

func (vg ValueGroups) ValuesByName(name string) ([]*Value, error)

type Values

type Values struct {
	// values in indexed order.
	Values []*Value

	// map of vals by name, only for specifically named vals
	// vs. generically allocated ones. Names must be unique.
	NameMap map[string]*Value
	// contains filtered or unexported fields
}

Values is a list container of Value values, accessed by index or name.

func (*Values) Add

func (vs *Values) Add(vr *Var, dev *Device, name ...string) *Value

Add adds a new Value for given variable.

func (*Values) CreateReadBuffers added in v0.3.3

func (vs *Values) CreateReadBuffers() error

CreateReadBuffers creates read buffers for all values.

func (*Values) CurrentValue

func (vs *Values) CurrentValue() *Value

CurrentValue returns the current Value according to Current index.

func (*Values) MemSize

func (vs *Values) MemSize() int

MemSize returns size in bytes across all Values in list

func (*Values) Release

func (vs *Values) Release()

Release frees all the value buffers / textures

func (*Values) SetCurrentValue

func (vs *Values) SetCurrentValue(idx int) (*Value, error)

SetCurrentValue sets the Current value to given index, returning the value or nil if if the index was out of range (logs an error too).

func (*Values) SetDynamicIndex

func (vs *Values) SetDynamicIndex(idx int) *Value

SetDynamicIndex sets the dynamic index to use for the current value, returning the value or nil if if the index was out of range (logs an error too).

func (*Values) SetN

func (vs *Values) SetN(vr *Var, dev *Device, nvals int) bool

SetN sets specific number of values, returning true if changed.

func (*Values) SetName

func (vs *Values) SetName(idx int, name string) (*Value, error)

SetName sets name of given Value, by index, adds name to map, checking that it is not already there yet. Returns val.

func (*Values) ValueByIndex added in v0.3.3

func (vs *Values) ValueByIndex(idx int) (*Value, error)

ValueByIndexTry returns Value at given index with range checking error message.

func (*Values) ValueByName added in v0.3.3

func (vs *Values) ValueByName(name string) (*Value, error)

ValueByNameTry returns value by name, returning error if not found

type Var

type Var struct {
	// variable name
	Name string

	// Type of data in variable.  Note that there are strict contraints
	// on the alignment of fields within structs.  If you can keep all fields
	// at 4 byte increments, that works, but otherwise larger fields trigger
	// a 16 byte alignment constraint.  Textures do not have such alignment
	// constraints, and are stored separately or in arrays organized by size.
	// Use Float32Matrix4 for model matricies in Vertex role, which will
	// automatically be sent as 4 interleaved Float32Vector4 chuncks.
	Type Types

	// number of elements, which is 1 for a single element, or a constant
	// number for a fixed array of elements.  For Vertex variables, the
	// number is dynamic and does not need to be specified in advance,
	// so you can leave it at 1. There can be alignment issues with arrays
	// so make sure your elemental types are compatible.
	// Note that DynamicOffset variables can have Value buffers with multiple
	// instances of the variable (with proper alignment stride), which is
	// which goes on top of any array value for the variable itself.
	ArrayN int

	// Role of variable: Vertex is configured separately, and everything else
	// is configured in a BindGroup.  This is inherited from the VarGroup
	// and all Vars in a Group must have the same Role, except Index is also
	// included in the VertexGroup (-2).
	// Note: Push is not yet supported.
	Role VarRoles

	// VertexInstance is whether this Vertex role variable is specified
	// per instance (true) or per vertex (false, default).
	// Instance variables can be used for sending per-object data like
	// the model matrix (as Float32Matrix4 which is serialized as 4
	// Float32Vector4 values).  Can also send texture indexes,
	// per object color, etc.
	VertexInstance bool

	// Group binding for this variable, indicated by @group in WGSL shader.
	// In general, put data that is updated at the same point in time in the same
	// group, as everything within a group is updated together.
	Group int

	// binding number for this variable, indicated by @binding in WGSL shader.
	// These are automatically assigned sequentially within Group.
	Binding int `edit:"-"`

	// size in bytes of one element (exclusive of array size).
	// Note that arrays in Uniform require 16 byte alignment for each element,
	// so if using arrays, it is best to work within that constraint.
	// In Storage, 4 byte (e.g., float32 or int32) works fine as an array type.
	// For Push role, SizeOf must be set exactly, as no vals are created.
	SizeOf int

	// DynamicOffset indicates whether the specific Value to use
	// is specified using a dynamic offset specified in the Value
	// via DynamicIndex.  There are limits on the number of dynamic
	// variables within each group (as few as 4).
	// Only for Uniform and Storage variables.
	DynamicOffset bool

	// Values is the the array of Values allocated for this variable.
	// Each value has its own corresponding Buffer or Texture.
	// The currently-active Value is specified by the Current index,
	// and this is what will be used for Binding.
	Values Values

	//	var group we are in
	VarGroup *VarGroup
	// contains filtered or unexported fields
}

Var specifies a variable used in a pipeline, accessed in shader programs at a specific @group (from VarGroup owner) and @binding location. There must be a different Var for each type of input or output into the GPU program, including things like Vertex arrays, transformation matricies (Uniforms), Textures, and arbitrary Storage data (Structs) for Compute shaders. There are one or more corresponding Value items for each Var, which represent the actual value of the variable: Var only represents the type-level info. Each Var belongs to a VarGroup, and its Binding location is sequential within that. The entire Group is updated at the same time from the hardware perspective, and less-frequently-updated items should be in the lower-numbered groups. The Role

func NewVar

func NewVar(vg *VarGroup, name string, typ Types, arrayN int, shaders ...ShaderTypes) *Var

NewVar returns a new Var in given var group

func (*Var) MemSize

func (vr *Var) MemSize() int

MemSize returns the memory allocation size for this value, in bytes

func (*Var) Release

func (vr *Var) Release()

Release resets the MemPtr for values, resets any self-owned resources (Textures)

func (*Var) SetCurrentValue

func (vr *Var) SetCurrentValue(i int)

SetCurrentValue sets the Current Value index, which is the Value that will be used in rendering, via BindGroup

func (*Var) SetNValues

func (vr *Var) SetNValues(dev *Device, nvals int) bool

SetNValues sets specified number of Values for this var. returns true if changed.

func (*Var) String

func (vr *Var) String() string

type VarGroup

type VarGroup struct {
	// name is optional, for user reference, documentation
	Name string

	// variables in order
	Vars []*Var

	// map of vars by name; names must be unique
	VarMap map[string]*Var

	// Group index is assigned sequentially, with special VertexGroup and
	// PushGroup having negative numbers, not accessed via @group in shader.
	Group int

	// Role is default Role of variables within this group.
	// Vertex is configured separately, and everything else
	// is configured in a BindGroup.
	// Note: Push is not yet supported.
	Role VarRoles

	// map of vars by different roles, within this group.
	// Updated in Config(), after all vars added
	RoleMap map[VarRoles][]*Var
	// contains filtered or unexported fields
}

VarGroup contains a group of Var variables, accessed via @group number in shader code, with @binding allocated sequentially within group (or @location in the case of VertexGroup).

func (*VarGroup) Add

func (vg *VarGroup) Add(name string, typ Types, arrayN int, shaders ...ShaderTypes) *Var

Add adds a new variable of given type, role, arrayN, and shaders where used

func (*VarGroup) AddStruct

func (vg *VarGroup) AddStruct(name string, size int, arrayN int, shaders ...ShaderTypes) *Var

AddStruct adds a new struct variable of given total number of bytes in size, type, role, set, and shaders where used

func (*VarGroup) Config

func (vg *VarGroup) Config(dev *Device) error

Config must be called after all variables have been added. Configures binding / location for all vars based on sequential order. also does validation and returns error message.

func (*VarGroup) CreateReadBuffers added in v0.3.3

func (vg *VarGroup) CreateReadBuffers() error

CreateReadBuffers creates read buffers for all values.

func (*VarGroup) IndexVar

func (vg *VarGroup) IndexVar() *Var

IndexVar returns the Index variable within this VertexGroup. returns nil if not found.

func (*VarGroup) Release

func (vg *VarGroup) Release()

Release destroys infrastructure for Group, Vars and Values.

func (*VarGroup) SetAllCurrentValue

func (vg *VarGroup) SetAllCurrentValue(i int)

SetAllCurrentValue sets the Current Value index, which is the Value that will be used in rendering, via BindGroup, for all vars in group.

func (*VarGroup) SetCurrentValue

func (vg *VarGroup) SetCurrentValue(name string, valueIndex int) (*Var, error)

SetCurrentValue sets the index of the Current Value to use for given variable name.

func (*VarGroup) SetDynamicIndex

func (vg *VarGroup) SetDynamicIndex(name string, dynamicIndex int) (*Var, error)

SetDynamicIndex sets the dynamic offset index for Value to use for given variable name.

func (*VarGroup) SetNValues

func (vg *VarGroup) SetNValues(nvals int)

SetNValues sets all vars in this group to have specified number of Values.

func (*VarGroup) ValueByIndex

func (vg *VarGroup) ValueByIndex(varName string, valIndex int) (*Value, error)

ValueByIndex returns value by first looking up variable name, then value index, returning error if not found.

func (*VarGroup) ValueByName added in v0.3.3

func (vg *VarGroup) ValueByName(varName, valName string) (*Value, error)

ValueByName returns value by first looking up variable name, then value name, returning error if not found.

func (*VarGroup) VarByName

func (vg *VarGroup) VarByName(name string) (*Var, error)

VarByName returns Var by name, returning error if not found

type VarRoles

type VarRoles int32 //enums:enum

VarRoles are the functional roles of variables,

const (
	UndefVarRole VarRoles = iota

	// Vertex is vertex shader input data: mesh geometry points, normals, etc.
	// These are automatically located in a separate Set, VertexSet (-2),
	// and managed separately.
	Vertex

	// Index is for indexes to access to Vertex data, also located in VertexSet (-2).
	// Only one such Var per VarGroup should be present, and will
	// automatically be used if a value is set.
	Index

	// Push is push constants, NOT CURRENTLY SUPPORTED in WebGPU.
	// They have a minimum of 128 bytes and are
	// stored directly in the command buffer. They do not require any
	// host-device synchronization or buffering, and are fully dynamic.
	// They are ideal for transformation matricies or indexes for accessing data.
	// They are stored in a special PushSet (-1) and managed separately.
	Push

	// Uniform is read-only general purpose data, with a more limited capacity.
	// Compared to Storage, Uniform items can be put in local cache for each
	// shader and thus can be much faster to access. Use for a smaller number
	// of parameters such as transformation matricies.
	Uniform

	// Storage is read-write general purpose data.  This is a larger but slower
	// pool of memory, with more flexible alignment constraints, used primarily
	// for compute data.
	Storage

	// StorageTexture is read-write storage-based texture data, for compute shaders
	// that operate on image data, not for standard use of textures in fragment
	// shader to texturize objects (which is SampledTexture).
	StorageTexture

	// SampledTexture is a Texture + Sampler that is used to texturize objects
	// in the fragment shader.  The variable for this specifies the role for
	// the texture (typically there is just one main such texture), and
	// the different Values of the variable hold each instance, with
	// binding used to switch which texture to use.
	// The Texture takes the first Binding position, and the Sampler is +1.
	SampledTexture
)
const VarRolesN VarRoles = 8

VarRolesN is the highest valid value for type VarRoles, plus one.

func VarRolesValues

func VarRolesValues() []VarRoles

VarRolesValues returns all possible values for the type VarRoles.

func (VarRoles) BindingType

func (vr VarRoles) BindingType() wgpu.BufferBindingType

func (VarRoles) BufferUsages

func (vr VarRoles) BufferUsages() wgpu.BufferUsage

func (VarRoles) Desc

func (i VarRoles) Desc() string

Desc returns the description of the VarRoles value.

func (VarRoles) Int64

func (i VarRoles) Int64() int64

Int64 returns the VarRoles value as an int64.

func (VarRoles) IsDynamic

func (vr VarRoles) IsDynamic() bool

IsDynamic returns true if role has dynamic offset binding

func (VarRoles) MarshalText

func (i VarRoles) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*VarRoles) SetInt64

func (i *VarRoles) SetInt64(in int64)

SetInt64 sets the VarRoles value from an int64.

func (*VarRoles) SetString

func (i *VarRoles) SetString(s string) error

SetString sets the VarRoles value from its string representation, and returns an error if the string is invalid.

func (VarRoles) String

func (i VarRoles) String() string

String returns the string representation of this VarRoles value.

func (*VarRoles) UnmarshalText

func (i *VarRoles) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (VarRoles) Values

func (i VarRoles) Values() []enums.Enum

Values returns all possible values for the type VarRoles.

type Vars

type Vars struct {
	// map of Groups, by group number: VertexGroup is -2, PushGroup is -1,
	// rest are added incrementally.
	Groups map[int]*VarGroup

	// map of vars by different roles across all Groups, updated in Config(),
	// after all vars added.
	RoleMap map[VarRoles][]*Var
	// contains filtered or unexported fields
}

Vars are all the variables that are used by a pipeline, organized into Groups (optionally including the special VertexGroup or PushGroup). Vars are allocated to bindings sequentially in the order added.

func (*Vars) AddGroup

func (vs *Vars) AddGroup(role VarRoles, name ...string) *VarGroup

AddGroup adds a new non-Vertex Group for holding data for given Role (Uniform, Storage, etc). Groups are automatically numbered sequentially in order added. Name is optional and just provides documentation. Important limit: there can only be a maximum of 4 Groups!

func (*Vars) AddPushGroup

func (vs *Vars) AddPushGroup() *VarGroup

AddPushGroup adds a new push constant Group -- this is a special Group holding values sent directly in the command buffer.

func (*Vars) AddVertexGroup

func (vs *Vars) AddVertexGroup() *VarGroup

AddVertexGroup adds a new Vertex Group. This is a special Group holding Vertex, Index vars

func (*Vars) Config

func (vs *Vars) Config(dev *Device) error

Config must be called after all variables have been added. Configures all Groups and also does validation, returning error does DescLayout too, so all ready for Pipeline config.

func (*Vars) CreateReadBuffers added in v0.3.3

func (vs *Vars) CreateReadBuffers() error

CreateReadBuffers creates read buffers for all Storage variables. This is needed to be able to read values back from GPU (e.g., for Compute).

func (*Vars) Group added in v0.3.3

func (vs *Vars) Group(group int) (*VarGroup, error)

Group returns group by index, returning nil and error if not found

func (*Vars) NGroups

func (vs *Vars) NGroups() int

NGroups returns the number of regular non-VertexGroup groups

func (*Vars) PushGroup

func (vs *Vars) PushGroup() *VarGroup

PushGroup returns the Push Group -- a special Group holding push constants

func (*Vars) Release

func (vs *Vars) Release()

func (*Vars) SetCurrentValue

func (vs *Vars) SetCurrentValue(group int, name string, valueIndex int) (*Var, error)

SetCurrentValue sets the index of the current Value to use for given variable name, in given group number.

func (*Vars) SetDynamicIndex

func (vs *Vars) SetDynamicIndex(group int, name string, dynamicIndex int) *Var

SetDynamicIndex sets the dynamic offset index for Value to use for given variable name, in given group number.

func (*Vars) StartGroup

func (vs *Vars) StartGroup() int

StartGroup returns the starting group to use for iterating groups

func (*Vars) StringDoc

func (vs *Vars) StringDoc() string

StringDoc returns info on variables

func (*Vars) ValueByIndex

func (vs *Vars) ValueByIndex(group int, varName string, valIndex int) (*Value, error)

ValueByIndex returns value by first looking up variable name, then value index, returning error if not found

func (*Vars) ValueByName added in v0.3.3

func (vs *Vars) ValueByName(group int, varName, valName string) (*Value, error)

ValueByName returns value by first looking up variable name, then value name, within given group number, returning error if not found

func (*Vars) VarByName

func (vs *Vars) VarByName(group int, name string) (*Var, error)

VarByName returns Var by name in given group number, returning error if not found

func (*Vars) VertexGroup

func (vs *Vars) VertexGroup() *VarGroup

VertexGroup returns the Vertex Group -- a special Group holding Vertex, Index vars

func (*Vars) VertexLayout

func (vs *Vars) VertexLayout() []wgpu.VertexBufferLayout

VertexLayout returns WebGPU vertex layout, for VertexGroup only!

Directories

Path Synopsis
cmd
webgpuinfo
This tool prints out information about your available WebGPU devices.
This tool prints out information about your available WebGPU devices.
examples
gosl translates Go source code into WGSL compatible shader code.
gosl translates Go source code into WGSL compatible shader code.
alignsl
package alignsl performs 16-byte alignment checking of struct fields and total size modulus checking of struct types to ensure WGSL (and GSL) compatibility.
package alignsl performs 16-byte alignment checking of struct fields and total size modulus checking of struct types to ensure WGSL (and GSL) compatibility.
examples/basic
This example just does some basic calculations on data structures and reports the time difference between the CPU and GPU.
This example just does some basic calculations on data structures and reports the time difference between the CPU and GPU.
slbool
package slbool defines a WGSL friendly int32 Bool type.
package slbool defines a WGSL friendly int32 Bool type.
threading
Package threading provides a simple parallel run function.
Package threading provides a simple parallel run function.
Package shape provides a library of 3D shapes, built from indexed triangle meshes, which can be added together in `ShapeGroup` lists.
Package shape provides a library of 3D shapes, built from indexed triangle meshes, which can be added together in `ShapeGroup` lists.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL