Skip to content

Commit 4b2588e

Browse files
committed
the great SSBO refactor: replace textures with SSBOs, fix some tests
1 parent 75ed488 commit 4b2588e

File tree

4 files changed

+262
-166
lines changed

4 files changed

+262
-166
lines changed

examples/test/glsdf3test.go

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ import (
2626
)
2727

2828
func main() {
29+
start := time.Now()
30+
err := run()
31+
elapsed := time.Since(start).Round(time.Millisecond)
32+
if err != nil {
33+
log.Fatalf("FAIL in %s: %s", elapsed, err.Error())
34+
}
35+
log.Println("PASS in ", elapsed)
36+
}
37+
38+
func run() error {
2939
_, terminate, err := glgl.InitWithCurrentWindow33(glgl.WindowConfig{
3040
Title: "compute",
3141
Version: [2]int{4, 6},
@@ -36,26 +46,24 @@ func main() {
3646
log.Fatal("FAIL to start GLFW", err.Error())
3747
}
3848
defer terminate()
39-
40-
start := time.Now()
4149
err = test_polygongpu()
4250
if err != nil {
43-
log.Fatal("FAIL testing PolygonGPU: ", err.Error())
51+
return fmt.Errorf("testing polygonGPU: %w", err)
4452
}
53+
4554
err = test_visualizer_generation()
4655
if err != nil {
47-
log.Fatal("FAIL generating visualization GLSL: ", err.Error())
56+
return fmt.Errorf("generating visualization GLSL: %w", err)
4857
}
4958
err = test_sdf_gpu_cpu()
5059
if err != nil {
51-
log.Fatal("FAIL testing CPU/GPU sdf comparisons: ", err.Error())
60+
return fmt.Errorf("testing CPU/GPU sdf comparisons: %w", err)
5261
}
5362
err = test_stl_generation()
5463
if err != nil {
55-
log.Fatal("FAIL generating STL: ", err.Error())
64+
return fmt.Errorf("generating STL: %w", err)
5665
}
57-
58-
log.Println("PASS in ", time.Since(start).Round(time.Millisecond))
66+
return nil
5967
}
6068

6169
var programmer = glbuild.NewDefaultProgrammer()
@@ -144,21 +152,22 @@ func test_sdf_gpu_cpu() error {
144152
scratchDist := make([]float32, maxBuf)
145153
scratchPos := make([]ms3.Vec, maxBuf)
146154
scratchPos2 := make([]ms2.Vec, maxBuf)
147-
for _, primitive := range PremadePrimitives {
148-
log.Printf("begin evaluating %s", getBaseTypename(primitive))
155+
156+
for _, primitive := range PremadePrimitives2D {
157+
log.Printf("evaluate 2D %s\n", getBaseTypename(primitive))
149158
bounds := primitive.Bounds()
150-
pos := appendMeshgrid(scratchPos[:0], bounds, nx, ny, nz)
159+
pos := appendMeshgrid2D(scratchPos2[:0], bounds, nx, ny)
151160
distCPU := scratchDistCPU[:len(pos)]
152161
distGPU := scratchDistGPU[:len(pos)]
153-
sdfcpu, err := gleval.AssertSDF3(primitive)
162+
sdfcpu, err := gleval.AssertSDF2(primitive)
154163
if err != nil {
155164
return err
156165
}
157166
err = sdfcpu.Evaluate(pos, distCPU, vp)
158167
if err != nil {
159168
return err
160169
}
161-
sdfgpu := makeGPUSDF3(primitive)
170+
sdfgpu := makeGPUSDF2(primitive)
162171
err = sdfgpu.Evaluate(pos, distGPU, nil)
163172
if err != nil {
164173
return err
@@ -168,28 +177,28 @@ func test_sdf_gpu_cpu() error {
168177
description := sprintOpPrimitive(nil, primitive)
169178
return fmt.Errorf("%s: %s", description, err)
170179
}
171-
err = test_bounds(sdfcpu, scratchDist, vp)
172-
if err != nil {
173-
description := sprintOpPrimitive(nil, primitive)
174-
return fmt.Errorf("%s: %s", description, err)
175-
}
180+
// err = test_bounds(sdfcpu, scratchDist, vp)
181+
// if err != nil {
182+
// description := sprintOpPrimitive(nil, primitive)
183+
// return fmt.Errorf("%s: %s", description, err)
184+
// }
176185
}
177186

178-
for _, primitive := range PremadePrimitives2D {
179-
log.Printf("evaluate 2D %s\n", getBaseTypename(primitive))
187+
for _, primitive := range PremadePrimitives {
188+
log.Printf("begin evaluating %s", getBaseTypename(primitive))
180189
bounds := primitive.Bounds()
181-
pos := appendMeshgrid2D(scratchPos2[:0], bounds, nx, ny, nz)
190+
pos := appendMeshgrid(scratchPos[:0], bounds, nx, ny, nz)
182191
distCPU := scratchDistCPU[:len(pos)]
183192
distGPU := scratchDistGPU[:len(pos)]
184-
sdfcpu, err := gleval.AssertSDF2(primitive)
193+
sdfcpu, err := gleval.AssertSDF3(primitive)
185194
if err != nil {
186195
return err
187196
}
188197
err = sdfcpu.Evaluate(pos, distCPU, vp)
189198
if err != nil {
190199
return err
191200
}
192-
sdfgpu := makeGPUSDF2(primitive)
201+
sdfgpu := makeGPUSDF3(primitive)
193202
err = sdfgpu.Evaluate(pos, distGPU, nil)
194203
if err != nil {
195204
return err
@@ -199,11 +208,11 @@ func test_sdf_gpu_cpu() error {
199208
description := sprintOpPrimitive(nil, primitive)
200209
return fmt.Errorf("%s: %s", description, err)
201210
}
202-
// err = test_bounds(sdfcpu, scratchDist, vp)
203-
// if err != nil {
204-
// description := sprintOpPrimitive(nil, primitive)
205-
// return fmt.Errorf("%s: %s", description, err)
206-
// }
211+
err = test_bounds(sdfcpu, scratchDist, vp)
212+
if err != nil {
213+
description := sprintOpPrimitive(nil, primitive)
214+
return fmt.Errorf("%s: %s", description, err)
215+
}
207216
}
208217

209218
for _, op := range BinaryOps {
@@ -431,32 +440,43 @@ func test_visualizer_generation() error {
431440
}
432441

433442
func test_polygongpu() error {
443+
const Nvertices = 16000
434444
var polybuilder ms2.PolygonBuilder
435-
polybuilder.NagonSmoothed(5, 2, 4, 0.1)
445+
polybuilder.Nagon(Nvertices, 2)
436446
vecs, err := polybuilder.AppendVecs(nil)
437447
if err != nil {
438448
return err
439449
}
450+
440451
poly, err := gsdf.NewPolygon(vecs)
441452
if err != nil {
442453
return err
443454
}
444455
polyGPU := gleval.PolygonGPU{Vertices: vecs}
445-
pos := appendMeshgrid2D(nil, poly.Bounds(), 32, 32, 32)
446-
distCPU := make([]float32, len(pos))
447-
distGPU := make([]float32, len(pos))
448-
sdfcpu, err := gleval.NewCPUSDF2(poly)
449-
if err != nil {
450-
return err
451-
}
452-
err = polyGPU.Evaluate(pos, distGPU, nil)
453-
if err != nil {
454-
return err
455-
}
456-
err = sdfcpu.Evaluate(pos, distCPU, nil)
457-
if err != nil {
458-
return err
456+
for _, sz := range []int{32} {
457+
now := time.Now()
458+
pos := appendMeshgrid2D(nil, poly.Bounds(), sz, sz)
459+
distCPU := make([]float32, len(pos))
460+
distGPU := make([]float32, len(pos))
461+
sdfcpu, err := gleval.NewCPUSDF2(poly)
462+
if err != nil {
463+
return err
464+
}
465+
err = polyGPU.Evaluate(pos, distGPU, nil)
466+
if err != nil {
467+
return err
468+
}
469+
fmt.Println(sz, time.Since(now).Round(time.Millisecond))
470+
err = sdfcpu.Evaluate(pos, distCPU, nil)
471+
if err != nil {
472+
return err
473+
}
474+
err = cmpDist(pos, distCPU, distGPU)
475+
if err != nil {
476+
return err
477+
}
459478
}
479+
460480
log.Println("PASS polygongpu")
461481
return nil
462482
}
@@ -623,7 +643,7 @@ func appendMeshgrid(dst []ms3.Vec, bounds ms3.Box, nx, ny, nz int) []ms3.Vec {
623643
return dst
624644
}
625645

626-
func appendMeshgrid2D(dst []ms2.Vec, bounds ms2.Box, nx, ny, nz int) []ms2.Vec {
646+
func appendMeshgrid2D(dst []ms2.Vec, bounds ms2.Box, nx, ny int) []ms2.Vec {
627647
nxyz := ms2.Vec{X: float32(nx), Y: float32(ny)}
628648
dxyz := ms2.DivElem(bounds.Size(), nxyz)
629649
var xy ms2.Vec
@@ -691,12 +711,12 @@ func cmpDist[T any](pos []T, dcpu, dgpu []float32) error {
691711
mismatches := 0
692712
const tol = 5e-3
693713
var mismatchErr error
694-
for i, dg := range dcpu {
695-
dc := dgpu[i]
714+
for i, dc := range dcpu {
715+
dg := dgpu[i]
696716
diff := math32.Abs(dg - dc)
697717
if diff > tol {
698718
mismatches++
699-
msg := fmt.Sprintf("mismatch: pos=%+v cpu=%f, gpu=%f (diff=%f)", pos[i], dc, dg, diff)
719+
msg := fmt.Sprintf("mismatch: pos=%+v cpu=%f, gpu=%f (diff=%f) idx=%d", pos[i], dc, dg, diff, i)
700720
if mismatchErr == nil {
701721
mismatchErr = errors.New("cpu vs. gpu distance mismatch")
702722
}

glbuild/glbuild.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"strconv"
11+
"unsafe"
1112

1213
"github.com/soypat/glgl/math/ms2"
1314
"github.com/soypat/glgl/math/ms3"
@@ -95,21 +96,26 @@ func (p *Programmer) WriteComputeSDF3(w io.Writer, obj Shader3D) (int, error) {
9596
if err != nil {
9697
return n, err
9798
}
99+
const sz = unsafe.Sizeof(ms3.Vec{})
98100
ngot, err = fmt.Fprintf(w, `
99101
100102
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
101-
layout(rgba32f, binding = 0) uniform image2D in_tex;
102-
// The binding argument refers to the textures Unit.
103-
layout(r32f, binding = 1) uniform image2D out_tex;
103+
104+
// Input: 3D positions at which to evaluate SDF.
105+
layout(std140, binding = 0) buffer PositionsBuffer {
106+
vec3 vbo_positions[];
107+
};
108+
109+
// Output: Result of SDF evaluation are the distances. Maps to position buffer.
110+
layout(std430, binding = 1) buffer DistancesBuffer {
111+
float vbo_distances[];
112+
};
104113
105114
void main() {
106-
// get position to read/write data from.
107-
ivec2 pos = ivec2( gl_GlobalInvocationID.xy );
108-
// Get SDF position value.
109-
vec3 p = imageLoad( in_tex, pos ).rgb;
110-
float distance = %s(p);
111-
// store new value in image
112-
imageStore( out_tex, pos, vec4( distance, 0.0, 0.0, 0.0 ) );
115+
int idx = int( gl_GlobalInvocationID.x );
116+
117+
vec3 p = vbo_positions[idx]; // Get position to evaluate SDF at.
118+
vbo_distances[idx] = %s(p); // Evaluate SDF and store to distance buffer.
113119
}
114120
`, baseName)
115121

@@ -137,18 +143,22 @@ func (p *Programmer) WriteComputeSDF2(w io.Writer, obj Shader2D) (int, error) {
137143
ngot, err = fmt.Fprintf(w, `
138144
139145
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
140-
layout(rg32f, binding = 0) uniform image2D in_tex;
141-
// The binding argument refers to the textures Unit.
142-
layout(r32f, binding = 1) uniform image2D out_tex;
146+
147+
// Input: 2D positions at which to evaluate SDF.
148+
layout(std430, binding = 0) buffer PositionsBuffer {
149+
vec2 vbo_positions[];
150+
};
151+
152+
// Output: Result of SDF evaluation are the distances. Maps to position buffer.
153+
layout(std430, binding = 1) buffer DistancesBuffer {
154+
float vbo_distances[];
155+
};
143156
144157
void main() {
145-
// get position to read/write data from.
146-
ivec2 pos = ivec2( gl_GlobalInvocationID.xy );
147-
// Get SDF position value.
148-
vec2 p = imageLoad( in_tex, pos ).rg;
149-
float distance = %s(p);
150-
// store new value in image
151-
imageStore( out_tex, pos, vec4( distance, 0.0, 0.0, 0.0 ) );
158+
int idx = int( gl_GlobalInvocationID.x );
159+
160+
vec2 p = vbo_positions[idx]; // Get position to evaluate SDF at.
161+
vbo_distances[idx] = %s(p); // Evaluate SDF and store to distance buffer.
152162
}
153163
`, baseName)
154164

0 commit comments

Comments
 (0)