driver.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package driver
4
5 import (
6 "errors"
7 "image"
8 "time"
9 )
10
11 // Device represents the abstraction of underlying GPU
12 // APIs such as OpenGL, Direct3D useful for rendering Gio
13 // operations.
14 type Device interface {
15 BeginFrame() Framebuffer
16 EndFrame()
17 Caps() Caps
18 NewTimer() Timer
19 // IsContinuousTime reports whether all timer measurements
20 // are valid at the point of call.
21 IsTimeContinuous() bool
22 NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
23 NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
24 NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
25 NewBuffer(typ BufferBinding, size int) (Buffer, error)
26 NewComputeProgram(shader ShaderSources) (Program, error)
27 NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
28 NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
29
30 DepthFunc(f DepthFunc)
31 ClearDepth(d float32)
32 Clear(r, g, b, a float32)
33 Viewport(x, y, width, height int)
34 DrawArrays(mode DrawMode, off, count int)
35 DrawElements(mode DrawMode, off, count int)
36 SetBlend(enable bool)
37 SetDepthTest(enable bool)
38 DepthMask(mask bool)
39 BlendFunc(sfactor, dfactor BlendFactor)
40
41 BindInputLayout(i InputLayout)
42 BindProgram(p Program)
43 BindFramebuffer(f Framebuffer)
44 BindTexture(unit int, t Texture)
45 BindVertexBuffer(b Buffer, stride, offset int)
46 BindIndexBuffer(b Buffer)
47 BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
48
49 MemoryBarrier()
50 DispatchCompute(x, y, z int)
51
52 Release()
53 }
54
55 type ShaderSources struct {
56 Name string
57 GLSL100ES string
58 GLSL300ES string
59 GLSL310ES string
60 GLSL130 string
61 GLSL150 string
62 HLSL string
63 Uniforms UniformsReflection
64 Inputs []InputLocation
65 Textures []TextureBinding
66 }
67
68 type UniformsReflection struct {
69 Blocks []UniformBlock
70 Locations []UniformLocation
71 Size int
72 }
73
74 type TextureBinding struct {
75 Name string
76 Binding int
77 }
78
79 type UniformBlock struct {
80 Name string
81 Binding int
82 }
83
84 type UniformLocation struct {
85 Name string
86 Type DataType
87 Size int
88 Offset int
89 }
90
91 type InputLocation struct {
92 // For GLSL.
93 Name string
94 Location int
95 // For HLSL.
96 Semantic string
97 SemanticIndex int
98
99 Type DataType
100 Size int
101 }
102
103 // InputDesc describes a vertex attribute as laid out in a Buffer.
104 type InputDesc struct {
105 Type DataType
106 Size int
107
108 Offset int
109 }
110
111 // InputLayout is the driver specific representation of the mapping
112 // between Buffers and shader attributes.
113 type InputLayout interface {
114 Release()
115 }
116
117 type AccessBits uint8
118
119 type BlendFactor uint8
120
121 type DrawMode uint8
122
123 type TextureFilter uint8
124 type TextureFormat uint8
125
126 type BufferBinding uint8
127
128 type DataType uint8
129
130 type DepthFunc uint8
131
132 type Features uint
133
134 type Caps struct {
135 // BottomLeftOrigin is true if the driver has the origin in the lower left
136 // corner. The OpenGL driver returns true.
137 BottomLeftOrigin bool
138 Features Features
139 MaxTextureSize int
140 }
141
142 type Program interface {
143 Release()
144 SetStorageBuffer(binding int, buf Buffer)
145 SetVertexUniforms(buf Buffer)
146 SetFragmentUniforms(buf Buffer)
147 }
148
149 type Buffer interface {
150 Release()
151 Upload(data []byte)
152 Download(data []byte) error
153 }
154
155 type Framebuffer interface {
156 Invalidate()
157 Release()
158 ReadPixels(src image.Rectangle, pixels []byte) error
159 }
160
161 type Timer interface {
162 Begin()
163 End()
164 Duration() (time.Duration, bool)
165 Release()
166 }
167
168 type Texture interface {
169 Upload(offset, size image.Point, pixels []byte)
170 Release()
171 }
172
173 const (
174 DepthFuncGreater DepthFunc = iota
175 DepthFuncGreaterEqual
176 )
177
178 const (
179 DataTypeFloat DataType = iota
180 DataTypeInt
181 DataTypeShort
182 )
183
184 const (
185 BufferBindingIndices BufferBinding = 1 << iota
186 BufferBindingVertices
187 BufferBindingUniforms
188 BufferBindingTexture
189 BufferBindingFramebuffer
190 BufferBindingShaderStorage
191 )
192
193 const (
194 TextureFormatSRGB TextureFormat = iota
195 TextureFormatFloat
196 TextureFormatRGBA8
197 )
198
199 const (
200 AccessRead AccessBits = 1 + iota
201 AccessWrite
202 )
203
204 const (
205 FilterNearest TextureFilter = iota
206 FilterLinear
207 )
208
209 const (
210 FeatureTimers Features = 1 << iota
211 FeatureFloatRenderTargets
212 FeatureCompute
213 )
214
215 const (
216 DrawModeTriangleStrip DrawMode = iota
217 DrawModeTriangles
218 )
219
220 const (
221 BlendFactorOne BlendFactor = iota
222 BlendFactorOneMinusSrcAlpha
223 BlendFactorZero
224 BlendFactorDstColor
225 )
226
227 var ErrContentLost = errors.New("buffer content lost")
228
229 func (f Features) Has(feats Features) bool {
230 return f&feats == feats
231 }
232
233 func DownloadImage(d Device, f Framebuffer, r image.Rectangle) (*image.RGBA, error) {
234 img := image.NewRGBA(r)
235 if err := f.ReadPixels(r, img.Pix); err != nil {
236 return nil, err
237 }
238 if d.Caps().BottomLeftOrigin {
239 // OpenGL origin is in the lower-left corner. Flip the image to
240 // match.
241 flipImageY(r.Dx()*4, r.Dy(), img.Pix)
242 }
243 return img, nil
244 }
245
246 func flipImageY(stride, height int, pixels []byte) {
247 // Flip image in y-direction. OpenGL's origin is in the lower
248 // left corner.
249 row := make([]uint8, stride)
250 for y := 0; y < height/2; y++ {
251 y1 := height - y - 1
252 dest := y1 * stride
253 src := y * stride
254 copy(row, pixels[dest:])
255 copy(pixels[dest:], pixels[src:src+len(row)])
256 copy(pixels[src:], row)
257 }
258 }
259
260 func UploadImage(t Texture, offset image.Point, img *image.RGBA) {
261 var pixels []byte
262 size := img.Bounds().Size()
263 if img.Stride != size.X*4 {
264 panic("unsupported stride")
265 }
266 start := img.PixOffset(0, 0)
267 end := img.PixOffset(size.X, size.Y-1)
268 pixels = img.Pix[start:end]
269 t.Upload(offset, size, pixels)
270 }
271