Skip to content

Commit f195909

Browse files
committed
add usage of glgl.CompileFlags and bump glgl version; compile gleval.*GPU shaders on configure where possible
1 parent fabf771 commit f195909

8 files changed

Lines changed: 108 additions & 79 deletions

File tree

examples/test/glsdf3test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"github.com/soypat/gsdf/gsdfaux"
2727
)
2828

29+
const compileFlags glgl.CompileFlags = glgl.CompileFlagsStrict
30+
2931
func main() {
3032
start := time.Now()
3133
err := run()
@@ -358,7 +360,10 @@ func test_polygongpu() error {
358360
}
359361
polyGPU := &gleval.PolygonGPU{Vertices: vecs}
360362
invocX, _, _ := programmer.ComputeInvocations()
361-
polyGPU.Configure(gleval.ComputeConfig{InvocX: invocX})
363+
polyGPU.Configure(gleval.ComputeConfig{
364+
InvocX: invocX,
365+
CompileFlags: compileFlags,
366+
})
362367
return testsdf2("poly", sdfcpu, polyGPU)
363368
}
364369

@@ -387,7 +392,10 @@ func test_multidisplacegpu() error {
387392
Displacements: displace,
388393
}
389394
invocX, _, _ := programmer.ComputeInvocations()
390-
err = displGPU.Configure(programmer, circle, gleval.ComputeConfig{InvocX: invocX})
395+
err = displGPU.Configure(programmer, circle, gleval.ComputeConfig{
396+
InvocX: invocX,
397+
CompileFlags: compileFlags,
398+
})
391399
if err != nil {
392400
return err
393401
}
@@ -424,7 +432,10 @@ func test_linesgpu() error {
424432
Width: width,
425433
}
426434
invocX, _, _ := programmer.ComputeInvocations()
427-
linesGPU.Configure(gleval.ComputeConfig{InvocX: invocX})
435+
linesGPU.Configure(gleval.ComputeConfig{
436+
InvocX: invocX,
437+
CompileFlags: compileFlags,
438+
})
428439
return testsdf2("lines", linesCPU, linesGPU)
429440
}
430441

@@ -632,6 +643,7 @@ func makeGPUSDF3(s glbuild.Shader3D) *gleval.SDF3Compute {
632643
sdfgpu, err := gleval.NewComputeGPUSDF3(&source, s.Bounds(), gleval.ComputeConfig{
633644
InvocX: invocX,
634645
ShaderObjects: ssbos,
646+
CompileFlags: compileFlags,
635647
})
636648
if err != nil {
637649
panic(err)
@@ -655,6 +667,7 @@ func makeGPUSDF2(s glbuild.Shader2D) gleval.SDF2 {
655667
sdfgpu, err := gleval.NewComputeGPUSDF2(&source, s.Bounds(), gleval.ComputeConfig{
656668
InvocX: invocX,
657669
ShaderObjects: ssbos,
670+
CompileFlags: compileFlags,
658671
})
659672
if err != nil {
660673
panic(err)

glbuild/glbuild.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1385,7 +1385,7 @@ func unwrap(s Shader) Shader {
13851385
return nil
13861386
}
13871387

1388-
func SprintShader(sh Shader) string {
1388+
func FormatShader(sh Shader) string {
13891389
if sh == nil {
13901390
panic("nil shader")
13911391
}

glbuild/glbuild_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func TestSprintShader(t *testing.T) {
6464
s1 := bld.NewCircle(1.0)
6565
s2 := bld.NewRectangle(2, 3)
6666
composite := bld.Difference2D(s1, s2)
67-
str := glbuild.SprintShader(composite)
67+
str := glbuild.FormatShader(composite)
6868
if str != "diff2D(circle2D,rect2D)" {
6969
t.Error(str)
7070
}

gleval/gpu.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func NewComputeGPUSDF3(glglSourceCode io.Reader, bb ms3.Box, cfg ComputeConfig)
4040
if err != nil {
4141
return nil, err
4242
}
43+
combinedSource.CompileFlags = cfg.CompileFlags
4344
glprog, err := glgl.CompileProgram(combinedSource)
4445
if err != nil {
4546
return nil, errors.New(string(combinedSource.Compute) + "\n" + err.Error())
@@ -67,6 +68,8 @@ type ComputeConfig struct {
6768
InvocX int
6869
// ShaderObjects contains buffer data and definitions required by shader for correct evaluation.
6970
ShaderObjects []glbuild.ShaderObject
71+
// CompileFlags controls compile behaviour, mainly for performance gains at the cost of debuggability and program correctness.
72+
CompileFlags glgl.CompileFlags
7073
}
7174

7275
func (sdf *SDF3Compute) Bounds() ms3.Box {
@@ -103,6 +106,7 @@ func NewComputeGPUSDF2(glglSourceCode io.Reader, bb ms2.Box, cfg ComputeConfig)
103106
if err != nil {
104107
return nil, err
105108
}
109+
combinedSource.CompileFlags = cfg.CompileFlags
106110
glprog, err := glgl.CompileProgram(combinedSource)
107111
if err != nil {
108112
return nil, errors.New(string(combinedSource.Compute) + "\n" + err.Error())
@@ -240,10 +244,10 @@ void main() {
240244

241245
// PolygonGPU implements a direct polygon evaluation via GPU.
242246
type Lines2DGPU struct {
247+
prog glgl.Program
243248
Lines [][2]ms2.Vec
244249
Width float32
245250
evaluations uint64
246-
shader string
247251
invocX int
248252
}
249253

@@ -276,8 +280,16 @@ func (lines *Lines2DGPU) Configure(cfg ComputeConfig) error {
276280
if cfg.InvocX < 1 {
277281
return errZeroInvoc
278282
}
283+
shader := fmt.Sprintf(linesshader, cfg.InvocX)
284+
glprog, err := glgl.CompileProgram(glgl.ShaderSource{
285+
Compute: shader,
286+
CompileFlags: cfg.CompileFlags,
287+
})
288+
if err != nil {
289+
return errors.New(shader + "\n" + err.Error())
290+
}
291+
lines.prog = glprog
279292
lines.invocX = cfg.InvocX
280-
lines.shader = fmt.Sprintf(linesshader, cfg.InvocX)
281293
return nil
282294
}
283295

@@ -331,10 +343,10 @@ void main() {
331343

332344
// PolygonGPU implements a direct polygon evaluation via GPU.
333345
type DisplaceMulti2D struct {
346+
prog glgl.Program
334347
Displacements []ms2.Vec
335348
elemBB ms2.Box
336349
evaluations uint64
337-
shader []byte
338350
invocX int
339351
}
340352

@@ -368,9 +380,17 @@ func (disp *DisplaceMulti2D) Configure(programmer *glbuild.Programmer, element g
368380
} else if len(ssbos) > 0 {
369381
return errors.New("objectsunsupported for displace multi")
370382
}
383+
shader := fmt.Sprintf(multiDisplaceShader, buf.Bytes(), cfg.InvocX, basename)
384+
glprog, err := glgl.CompileProgram(glgl.ShaderSource{
385+
Compute: shader,
386+
CompileFlags: cfg.CompileFlags,
387+
})
388+
if err != nil {
389+
return err
390+
}
391+
disp.prog = glprog
371392
disp.elemBB = element.Bounds()
372393
disp.invocX = cfg.InvocX
373-
disp.shader = fmt.Appendf(disp.shader[:0], multiDisplaceShader, buf.Bytes(), cfg.InvocX, basename)
374394
return nil
375395
}
376396

gleval/gpu_cgo.go

Lines changed: 41 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -75,30 +75,25 @@ func (b *Batcher) runBinop(binopBody string, cfg ComputeConfig, dst, A, B []floa
7575
func (lines *Lines2DGPU) evaluate(pos []ms2.Vec, dist []float32, userData any) (err error) {
7676
if len(pos) != len(dist) {
7777
return errors.New("position and distance buffer length mismatch")
78-
} else if lines.shader == "" {
79-
return errors.New("need to initialize LinesGPU before first use")
78+
} else if lines.prog.ID() == 0 {
79+
return errors.New("program id is 0, did you configure Lines2DGPU?")
8080
}
81-
prog, err := glgl.CompileProgram(glgl.ShaderSource{Compute: lines.shader})
82-
if err != nil {
83-
return fmt.Errorf("compiling GL program: %w", err)
84-
}
85-
defer prog.Delete()
81+
prog := lines.prog
8682
prog.Bind()
83+
defer prog.Unbind()
8784
loc, err := prog.UniformLocation("WidthOffset\x00")
8885
if err != nil {
8986
return err
9087
}
91-
prog.SetUniformf(loc, lines.Width/2)
92-
err = glgl.Err()
88+
err = prog.SetUniformf(loc, lines.Width/2)
9389
if err != nil {
94-
return fmt.Errorf("binding LinesGPU program: %w", err)
90+
return err
9591
}
96-
defer prog.Unbind()
92+
9793
var p runtime.Pinner
9894
ssbo := loadSSBO(lines.Lines, 2, gl.STATIC_DRAW)
99-
err = glgl.Err()
100-
if err != nil {
101-
return err
95+
if ssbo == 0 {
96+
return glErrOrMessage("loading lines SSBO got zero id")
10297
}
10398
p.Pin(&ssbo)
10499
defer p.Unpin()
@@ -114,19 +109,16 @@ func (lines *Lines2DGPU) evaluate(pos []ms2.Vec, dist []float32, userData any) (
114109
func (poly *PolygonGPU) evaluate(pos []ms2.Vec, dist []float32, userData any) (err error) {
115110
if len(pos) != len(dist) {
116111
return errors.New("position and distance buffer length mismatch")
112+
} else if poly.prog.ID() == 0 {
113+
return errors.New("bad program compile or PolygonGPU not initialized before first use")
117114
}
118115
prog := poly.prog
119116
prog.Bind()
120-
err = glgl.Err()
121-
if err != nil {
122-
return fmt.Errorf("binding PolygonGPU program: %w", err)
123-
}
124117
defer prog.Unbind()
125118
var p runtime.Pinner
126119
ssbo := loadSSBO(poly.Vertices, 2, gl.STATIC_DRAW)
127-
err = glgl.Err()
128-
if err != nil {
129-
return err
120+
if ssbo == 0 {
121+
return glErrOrMessage("loading polygon vertices SSBO")
130122
}
131123
p.Pin(&ssbo)
132124
defer p.Unpin()
@@ -141,27 +133,17 @@ func (poly *PolygonGPU) evaluate(pos []ms2.Vec, dist []float32, userData any) (e
141133
func (lines *DisplaceMulti2D) evaluate(pos []ms2.Vec, dist []float32, userData any) (err error) {
142134
if len(pos) != len(dist) {
143135
return errors.New("position and distance buffer length mismatch")
144-
} else if len(lines.shader) == 0 {
145-
return errors.New("need to initialize LinesGPU before first use")
136+
} else if lines.prog.ID() == 0 {
137+
return errors.New("bad compile or need to initialize LinesGPU before first use")
146138
}
147-
cmp := unsafe.String(&lines.shader[0], len(lines.shader))
148-
prog, err := glgl.CompileProgram(glgl.ShaderSource{Compute: cmp})
149-
if err != nil {
150-
return fmt.Errorf("compiling GL program: %w", err)
151-
}
152-
defer prog.Delete()
153-
prog.Bind()
154139

155-
err = glgl.Err()
156-
if err != nil {
157-
return fmt.Errorf("binding LinesGPU program: %w", err)
158-
}
140+
prog := lines.prog
141+
prog.Bind()
159142
defer prog.Unbind()
160143
var p runtime.Pinner
161144
ssbo := loadSSBO(lines.Displacements, 2, gl.STATIC_DRAW)
162-
err = glgl.Err()
163-
if err != nil {
164-
return err
145+
if ssbo == 0 {
146+
return glErrOrMessage("loading displacements SSBO got zero id")
165147
}
166148
p.Pin(&ssbo)
167149
defer p.Unpin()
@@ -200,17 +182,13 @@ func copySSBO[T any](dst []T, ssbo uint32) error {
200182
gl.BindBuffer(gl.SHADER_STORAGE_BUFFER, ssbo)
201183
ptr := gl.MapBufferRange(gl.SHADER_STORAGE_BUFFER, 0, bufSize, gl.MAP_READ_BIT)
202184
if ptr == nil {
203-
err := glgl.Err()
204-
if err != nil {
205-
return err
206-
}
207-
return errors.New("failed to map buffer")
185+
return glErrOrMessage("failed to map SSBO buffer during copy")
208186
}
209187
defer gl.UnmapBuffer(gl.SHADER_STORAGE_BUFFER)
210188
gpuBytes := unsafe.Slice((*byte)(ptr), bufSize)
211189
bufBytes := unsafe.Slice((*byte)(unsafe.Pointer(&dst[0])), bufSize)
212190
copy(bufBytes, gpuBytes)
213-
return glgl.Err()
191+
return nil
214192
}
215193

216194
func computeEvaluate[T ms2.Vec | ms3.Vec](pos []T, dist []float32, invocX int, objects []glbuild.ShaderObject) (err error) {
@@ -240,17 +218,16 @@ func computeEvaluate[T ms2.Vec | ms3.Vec](pos []T, dist []float32, invocX int, o
240218
ssbo := &objects[i]
241219
if ssbo.IsBindable() {
242220
id := ssbosIDs[iid]
221+
if id == 0 {
222+
p.Unpin()
223+
return glErrOrMessage("zero id for SSBO set by GL during compute binding")
224+
}
243225
iid++
244226
gl.BindBuffer(gl.SHADER_STORAGE_BUFFER, id)
245227
gl.BufferData(gl.SHADER_STORAGE_BUFFER, ssbo.Size, ssbo.Data, gl.STATIC_DRAW)
246228
gl.BindBufferBase(gl.SHADER_STORAGE_BUFFER, uint32(ssbo.Binding), id)
247229
}
248230
}
249-
err := glgl.Err()
250-
if err != nil {
251-
p.Unpin()
252-
return fmt.Errorf("binding SSBOs: %w", err)
253-
}
254231
}
255232

256233
var posSSBO, distSSBO uint32
@@ -259,32 +236,33 @@ func computeEvaluate[T ms2.Vec | ms3.Vec](pos []T, dist []float32, invocX int, o
259236
defer p.Unpin()
260237

261238
posSSBO = loadSSBO(pos, 0, gl.STATIC_DRAW)
262-
err = glgl.Err()
263-
if err != nil {
264-
return err
239+
if posSSBO == 0 {
240+
return glErrOrMessage("zero SSBO id set by GL during compute loading")
265241
}
242+
266243
defer gl.DeleteBuffers(1, &posSSBO)
267244

268245
distSSBO = createSSBO(elemSize[float32]()*len(dist), 1, gl.DYNAMIC_READ)
269-
err = glgl.Err()
270-
if err != nil {
271-
return err
246+
if distSSBO == 0 {
247+
return glErrOrMessage("zero id SSBO creating distance buffer")
272248
}
273249
nWorkX := (len(dist) + invocX - 1) / invocX
274250
defer gl.DeleteBuffers(1, &distSSBO)
275251
gl.DispatchCompute(uint32(nWorkX), 1, 1)
276-
err = glgl.Err()
277-
if err != nil {
278-
return err
279-
}
280252
gl.MemoryBarrier(gl.SHADER_STORAGE_BARRIER_BIT)
281-
err = glgl.Err()
282-
if err != nil {
283-
return err
284-
}
285253
err = copySSBO(dist, distSSBO)
286254
if err != nil {
287255
return err
288256
}
289-
return nil
257+
return glgl.Err()
258+
}
259+
260+
func glErrOrMessage(defaultMsg string) (err error) {
261+
err = glgl.Err()
262+
if err == nil {
263+
err = errors.New(defaultMsg)
264+
} else {
265+
err = fmt.Errorf("%s: %w", defaultMsg, err)
266+
}
267+
return err
290268
}

go.mod

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
module github.com/soypat/gsdf
22

3-
go 1.22.1
3+
go 1.23.0
4+
5+
toolchain go1.24.2
46

57
require (
68
github.com/chewxy/math32 v1.11.1
79
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71
8-
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b
10+
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728
911
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
10-
github.com/soypat/geometry v0.0.0-20250426195511-b8a0ef6615b7
11-
github.com/soypat/glgl v0.0.0-20241218113040-663b03b49704
12+
github.com/soypat/geometry v0.0.0-20250508182632-816898eefdf5
13+
github.com/soypat/glgl v0.0.0-20250512221855-eace9dbeac6b
1214
golang.org/x/image v0.22.0
1315
)
1416

1517
require (
16-
github.com/go-gl/glfw v0.0.0-20221017161538-93cebf72946b // indirect
17-
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 // indirect
18+
github.com/go-gl/glfw v0.0.0-20250301202403-da16c1255728 // indirect
19+
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
1820
)

0 commit comments

Comments
 (0)