Files
gio/gpu/internal/driver/driver.go
T
Elias Naur 23e0c898ef gpu/internal/driver: use strings for generated DXIL assembly
Literal strings are a more compact than literal byte slices. A future
change will switch to go:embed to save even more space.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00

271 lines
5.4 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package driver
import (
"errors"
"image"
"time"
)
// Device represents the abstraction of underlying GPU
// APIs such as OpenGL, Direct3D useful for rendering Gio
// operations.
type Device interface {
BeginFrame() Framebuffer
EndFrame()
Caps() Caps
NewTimer() Timer
// IsContinuousTime reports whether all timer measurements
// are valid at the point of call.
IsTimeContinuous() bool
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
NewBuffer(typ BufferBinding, size int) (Buffer, error)
NewComputeProgram(shader ShaderSources) (Program, error)
NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
DepthFunc(f DepthFunc)
ClearDepth(d float32)
Clear(r, g, b, a float32)
Viewport(x, y, width, height int)
DrawArrays(mode DrawMode, off, count int)
DrawElements(mode DrawMode, off, count int)
SetBlend(enable bool)
SetDepthTest(enable bool)
DepthMask(mask bool)
BlendFunc(sfactor, dfactor BlendFactor)
BindInputLayout(i InputLayout)
BindProgram(p Program)
BindFramebuffer(f Framebuffer)
BindTexture(unit int, t Texture)
BindVertexBuffer(b Buffer, stride, offset int)
BindIndexBuffer(b Buffer)
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
MemoryBarrier()
DispatchCompute(x, y, z int)
Release()
}
type ShaderSources struct {
Name string
GLSL100ES string
GLSL300ES string
GLSL310ES string
GLSL130 string
GLSL150 string
HLSL string
Uniforms UniformsReflection
Inputs []InputLocation
Textures []TextureBinding
}
type UniformsReflection struct {
Blocks []UniformBlock
Locations []UniformLocation
Size int
}
type TextureBinding struct {
Name string
Binding int
}
type UniformBlock struct {
Name string
Binding int
}
type UniformLocation struct {
Name string
Type DataType
Size int
Offset int
}
type InputLocation struct {
// For GLSL.
Name string
Location int
// For HLSL.
Semantic string
SemanticIndex int
Type DataType
Size int
}
// InputDesc describes a vertex attribute as laid out in a Buffer.
type InputDesc struct {
Type DataType
Size int
Offset int
}
// InputLayout is the driver specific representation of the mapping
// between Buffers and shader attributes.
type InputLayout interface {
Release()
}
type AccessBits uint8
type BlendFactor uint8
type DrawMode uint8
type TextureFilter uint8
type TextureFormat uint8
type BufferBinding uint8
type DataType uint8
type DepthFunc uint8
type Features uint
type Caps struct {
// BottomLeftOrigin is true if the driver has the origin in the lower left
// corner. The OpenGL driver returns true.
BottomLeftOrigin bool
Features Features
MaxTextureSize int
}
type Program interface {
Release()
SetStorageBuffer(binding int, buf Buffer)
SetVertexUniforms(buf Buffer)
SetFragmentUniforms(buf Buffer)
}
type Buffer interface {
Release()
Upload(data []byte)
Download(data []byte) error
}
type Framebuffer interface {
Invalidate()
Release()
ReadPixels(src image.Rectangle, pixels []byte) error
}
type Timer interface {
Begin()
End()
Duration() (time.Duration, bool)
Release()
}
type Texture interface {
Upload(offset, size image.Point, pixels []byte)
Release()
}
const (
DepthFuncGreater DepthFunc = iota
DepthFuncGreaterEqual
)
const (
DataTypeFloat DataType = iota
DataTypeInt
DataTypeShort
)
const (
BufferBindingIndices BufferBinding = 1 << iota
BufferBindingVertices
BufferBindingUniforms
BufferBindingTexture
BufferBindingFramebuffer
BufferBindingShaderStorage
)
const (
TextureFormatSRGB TextureFormat = iota
TextureFormatFloat
TextureFormatRGBA8
)
const (
AccessRead AccessBits = 1 + iota
AccessWrite
)
const (
FilterNearest TextureFilter = iota
FilterLinear
)
const (
FeatureTimers Features = 1 << iota
FeatureFloatRenderTargets
FeatureCompute
)
const (
DrawModeTriangleStrip DrawMode = iota
DrawModeTriangles
)
const (
BlendFactorOne BlendFactor = iota
BlendFactorOneMinusSrcAlpha
BlendFactorZero
BlendFactorDstColor
)
var ErrContentLost = errors.New("buffer content lost")
func (f Features) Has(feats Features) bool {
return f&feats == feats
}
func DownloadImage(d Device, f Framebuffer, r image.Rectangle) (*image.RGBA, error) {
img := image.NewRGBA(r)
if err := f.ReadPixels(r, img.Pix); err != nil {
return nil, err
}
if d.Caps().BottomLeftOrigin {
// OpenGL origin is in the lower-left corner. Flip the image to
// match.
flipImageY(r.Dx()*4, r.Dy(), img.Pix)
}
return img, nil
}
func flipImageY(stride, height int, pixels []byte) {
// Flip image in y-direction. OpenGL's origin is in the lower
// left corner.
row := make([]uint8, stride)
for y := 0; y < height/2; y++ {
y1 := height - y - 1
dest := y1 * stride
src := y * stride
copy(row, pixels[dest:])
copy(pixels[dest:], pixels[src:src+len(row)])
copy(pixels[src:], row)
}
}
func UploadImage(t Texture, offset image.Point, img *image.RGBA) {
var pixels []byte
size := img.Bounds().Size()
if img.Stride != size.X*4 {
panic("unsupported stride")
}
start := img.PixOffset(0, 0)
end := img.PixOffset(size.X, size.Y-1)
pixels = img.Pix[start:end]
t.Upload(offset, size, pixels)
}