github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/gpu/internal/driver/driver.go (about) 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(clear bool, viewport image.Point) 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 }