Skip to content

Commit bed2388

Browse files
committed
fix transform's uniqueness of name, add test
1 parent 1870c49 commit bed2388

14 files changed

+285
-74
lines changed

examples/text/text.go

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"runtime"
7+
8+
"github.com/soypat/glgl/math/ms2"
9+
"github.com/soypat/gsdf"
10+
"github.com/soypat/gsdf/forge/textsdf"
11+
"github.com/soypat/gsdf/glbuild"
12+
"github.com/soypat/gsdf/gleval"
13+
"github.com/soypat/gsdf/gsdfaux"
14+
)
15+
16+
const dim = 20
17+
const filename = "text.png"
18+
19+
func init() {
20+
runtime.LockOSThread()
21+
}
22+
23+
func scene(bld *gsdf.Builder) (glbuild.Shader2D, error) {
24+
var f textsdf.Font
25+
f.Configure(textsdf.FontConfig{
26+
RelativeGlyphTolerance: 0.001,
27+
})
28+
err := f.LoadTTFBytes(textsdf.ISO3098TTF())
29+
if err != nil {
30+
return nil, err
31+
}
32+
var poly ms2.PolygonBuilder
33+
poly.Nagon(7, 1)
34+
vecs, _ := poly.AppendVecs(nil)
35+
return bld.NewPolygon(vecs), bld.Err()
36+
return f.TextLine("Abc")
37+
}
38+
39+
func main() {
40+
useGPU := true
41+
if useGPU {
42+
term, err := gleval.Init1x1GLFW()
43+
if err != nil {
44+
log.Fatal(err)
45+
}
46+
defer term()
47+
}
48+
var bld gsdf.Builder
49+
s, err := scene(&bld)
50+
if err != nil {
51+
log.Fatal(err)
52+
}
53+
var sdf2 gleval.SDF2
54+
if useGPU {
55+
sdf2, err = gsdfaux.MakeGPUSDF2(s)
56+
} else {
57+
sdf2, err = gleval.NewCPUSDF2(s)
58+
}
59+
if err != nil {
60+
log.Fatal(err)
61+
}
62+
err = gsdfaux.RenderPNGFile(filename, sdf2, 300, nil)
63+
if err != nil {
64+
log.Fatal(err)
65+
}
66+
fmt.Println("PNG file rendered to", filename)
67+
}

examples/ui-geb/uigeb.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ func scene(bld *gsdf.Builder) (glbuild.Shader3D, error) {
4646
G = bld.Translate2D(G, -szG.X/2, -szG.Y/2)
4747
E = bld.Translate2D(E, -szE.X/2, -szE.Y/2)
4848
B = bld.Translate2D(B, -szB.X/2, -szB.Y/2)
49+
const round1 = 0.01
50+
G = bld.Offset2D(G, -round1)
51+
E = bld.Offset2D(E, -round1)
52+
B = bld.Offset2D(B, -round1)
4953

5054
// GEB size. Scale all letters to match size.
5155
szz := ms2.MaxElem(szG, ms2.MaxElem(szE, szB)).Max()
@@ -64,16 +68,22 @@ func scene(bld *gsdf.Builder) (glbuild.Shader3D, error) {
6468
G3 = bld.Transform(G3, ms3.ScaleMat4(ms3.Vec{X: sclG.X, Y: sclG.Y, Z: 1}))
6569
E3 = bld.Transform(E3, ms3.ScaleMat4(ms3.Vec{X: sclE.X, Y: sclE.Y, Z: 1}))
6670
B3 = bld.Transform(B3, ms3.ScaleMat4(ms3.Vec{X: sclB.X, Y: sclB.Y, Z: 1}))
71+
const round2 = 0.025
72+
G3 = bld.Offset(G3, -round2)
73+
E3 = bld.Offset(E3, -round2)
74+
B3 = bld.Offset(B3, -round2)
6775

6876
// Orient letters.
6977
const deg90 = math.Pi / 2
70-
E3 = bld.Rotate(E3, deg90, ms3.Vec{Y: 1})
71-
B3 = bld.Rotate(B3, -deg90, ms3.Vec{X: 1})
78+
GEB1 := bld.Intersection(G3, bld.Rotate(E3, deg90, ms3.Vec{Y: 1}))
79+
GEB1 = bld.Intersection(GEB1, bld.Rotate(B3, -deg90, ms3.Vec{X: 1}))
7280

73-
GEB := bld.Intersection(G3, E3)
74-
GEB = bld.Intersection(GEB, B3)
75-
// return bld.Union(G3, E3, B3), bld.Err() // For debugging.
76-
return GEB, bld.Err()
81+
GEB2 := bld.Intersection(E3, bld.Rotate(G3, deg90, ms3.Vec{Y: 1}))
82+
GEB2 = bld.Intersection(GEB2, bld.Rotate(B3, -deg90, ms3.Vec{X: 1}))
83+
84+
GEB2 = bld.Translate(GEB2, 0, GEB2.Bounds().Size().Y*1.5, 0)
85+
86+
return bld.Union(GEB1, GEB2), bld.Err()
7787
}
7888

7989
func main() {

glbuild/glbuild.go

+56-5
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,15 @@ func (p *Programmer) writeShaders(w io.Writer, nodes []Shader) (n int, objs []Sh
277277
newObjects := p.objsScratch[prevIdx:]
278278
for i := range newObjects {
279279
if newObjects[i].Binding != -1 {
280-
return n, nil, fmt.Errorf("shader buffer object binding should be set to -1 until shader generated for %T, %q", node, newObjects[i].NamePtr)
280+
return n, nil, fmt.Errorf("shader buffer object binding should be set to -1 until shader generated for %T, %q", unwraproot(node), newObjects[i].NamePtr)
281281
}
282282
newObjects[i].Binding = currentBase
283283
currentBase++
284284
obj := newObjects[i]
285285
nameHash := hash(obj.NamePtr, 0)
286286
_, nameConflict := p.names[nameHash]
287287
if nameConflict {
288-
return n, nil, fmt.Errorf("shader buffer object name conflict resolution not implemented: %T has buffer conflicting name %q of type %s", node, obj.NamePtr, obj.Element.String())
288+
return n, nil, fmt.Errorf("shader buffer object name conflict resolution not implemented: %T has buffer conflicting name %q of type %s", unwraproot(node), obj.NamePtr, obj.Element.String())
289289
}
290290
p.names[nameHash] = nameHash
291291
blockName := unsafe.String(&obj.NamePtr[0], len(obj.NamePtr)) + "Buffer"
@@ -316,7 +316,17 @@ func (p *Programmer) writeShaders(w io.Writer, nodes []Shader) (n int, objs []Sh
316316
if bodyHash == gotBodyHash {
317317
continue // Shader already written and is identical, skip.
318318
}
319-
return n, nil, fmt.Errorf("duplicate %T shader name %q w/ body:\n%s", node, name, body)
319+
// Look for identical shader
320+
var conflictBody []byte
321+
for j := i + 1; j < len(nodes); j++ {
322+
conflictBody = nodes[j].AppendShaderName(conflictBody[:0])
323+
if bytes.Equal(conflictBody, name) {
324+
conflictBody = nodes[j].AppendShaderBody(conflictBody[:0])
325+
break
326+
}
327+
conflictBody = conflictBody[:0]
328+
}
329+
return n, nil, fmt.Errorf("duplicate %T shader name %q w/ body:\n%s\n\nconflict with distinct shader with same name:\n%s", unwraproot(node), name, body, conflictBody)
320330
} else {
321331
p.names[nameHash] = bodyHash // Not found, add it.
322332
}
@@ -368,6 +378,9 @@ func ShortenNames2D(root *Shader2D, maxRewriteLen int) error {
368378

369379
func rewriteName3(s3 *Shader3D, scratch []byte, rewritelen int) []byte {
370380
sd3 := *s3
381+
if _, ok := sd3.(*nameOverloadShader3D); ok {
382+
return scratch // Already overloaded.
383+
}
371384
name, scratch := makeShortname(sd3, scratch, rewritelen)
372385
if name == nil {
373386
return scratch
@@ -378,6 +391,9 @@ func rewriteName3(s3 *Shader3D, scratch []byte, rewritelen int) []byte {
378391

379392
func rewriteName2(s2 *Shader2D, scratch []byte, rewritelen int) []byte {
380393
sd2 := *s2
394+
if _, ok := sd2.(*nameOverloadShader2D); ok {
395+
return scratch // Already overloaded.
396+
}
381397
name, scratch := makeShortname(sd2, scratch, rewritelen)
382398
if name == nil {
383399
return scratch
@@ -960,6 +976,7 @@ func (ob3 *overloadBounds3) Evaluate(pos []ms3.Vec, dist []float32, userData any
960976
}
961977
return sdf.Evaluate(pos, dist, userData)
962978
}
979+
func (ob3 *overloadBounds3) unwrap() Shader { return ob3.Shader3D }
963980

964981
// OverloadShader2DBounds overloads a [Shader2D] Bounds method with the argument bounding box.
965982
func OverloadShader2DBounds(s Shader2D, bb ms2.Box) Shader2D {
@@ -985,6 +1002,8 @@ func (ob3 *overloadBounds2) Evaluate(pos []ms2.Vec, dist []float32, userData any
9851002
return sdf.Evaluate(pos, dist, userData)
9861003
}
9871004

1005+
func (ob2 *overloadBounds2) unwrap() Shader { return ob2.Shader2D }
1006+
9881007
var _ Shader3D = (*CachedShader3D)(nil) // Interface implementation compile-time check.
9891008

9901009
// CachedShader3D implements the Shader3D interface with results it caches for another Shader3D on a call to RefreshCache.
@@ -1045,6 +1064,8 @@ func (c3 *CachedShader3D) Evaluate(pos []ms3.Vec, dist []float32, userData any)
10451064
return sdf.Evaluate(pos, dist, userData)
10461065
}
10471066

1067+
func (c3 *CachedShader3D) unwrap() Shader { return c3.Shader }
1068+
10481069
var _ Shader2D = (*CachedShader2D)(nil) // Interface implementation compile-time check.
10491070

10501071
// CachedShader2D implements the Shader2D interface with results it caches for another Shader2D on a call to RefreshCache.
@@ -1095,6 +1116,8 @@ func (c2 *CachedShader2D) AppendShaderObjects(objs []ShaderObject) []ShaderObjec
10951116
return c2.Shader.AppendShaderObjects(objs)
10961117
}
10971118

1119+
func (c2 *CachedShader2D) unwrap() Shader { return c2.Shader }
1120+
10981121
type nameOverloadShader3D struct {
10991122
Shader Shader3D
11001123
name []byte
@@ -1150,6 +1173,8 @@ func (nos3 *nameOverloadShader3D) AppendShaderName(b []byte) []byte {
11501173
return append(b, nos3.name...)
11511174
}
11521175

1176+
func (nos3 *nameOverloadShader3D) unwrap() Shader { return nos3.Shader }
1177+
11531178
type nameOverloadShader2D struct {
11541179
Shader Shader2D
11551180
name []byte
@@ -1182,6 +1207,8 @@ func (nos2 *nameOverloadShader2D) AppendShaderObjects(objs []ShaderObject) []Sha
11821207
return nos2.Shader.AppendShaderObjects(objs)
11831208
}
11841209

1210+
func (nos2 *nameOverloadShader2D) unwrap() Shader { return nos2.Shader }
1211+
11851212
func hash(b []byte, in uint64) uint64 {
11861213
// Leaving md5 here since we may need to revert to
11871214
// a more entropic hash to avoid collisions...
@@ -1200,9 +1227,33 @@ func hash(b []byte, in uint64) uint64 {
12001227
x = (x ^ (x >> 27)) * 0x94d049bb133111eb
12011228
x ^= x >> 31
12021229
b = b[8:]
1230+
12031231
}
1204-
for i := range b {
1205-
x ^= uint64(b[i]) << i * 8
1232+
if len(b) > 0 {
1233+
var buf [8]byte
1234+
copy(buf[:], b)
1235+
x ^= binary.LittleEndian.Uint64(buf[:])
1236+
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9
1237+
x = (x ^ (x >> 27)) * 0x94d049bb133111eb
1238+
x ^= x >> 31
12061239
}
12071240
return x
12081241
}
1242+
1243+
func unwraproot(s Shader) Shader {
1244+
i := 0
1245+
var sbase Shader
1246+
for s != nil && i < 6 {
1247+
sbase = s
1248+
s = unwrap(s)
1249+
i++
1250+
}
1251+
return sbase
1252+
}
1253+
1254+
func unwrap(s Shader) Shader {
1255+
if unwrapper, ok := s.(interface{ unwrap() Shader }); ok {
1256+
return unwrapper.unwrap()
1257+
}
1258+
return nil
1259+
}

gleval/gleval.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,14 @@ type BlockCachedSDF3 struct {
111111
evals uint64
112112
}
113113

114+
func (c3 *BlockCachedSDF3) VecPool() *VecPool {
115+
vp, _ := GetVecPool(c3.sdf)
116+
return vp
117+
}
118+
114119
// Reset resets the SDF3 and reuses the underlying buffers for future SDF evaluations. It also resets statistics such as evaluations and cache hits.
115-
func (c3 *BlockCachedSDF3) Reset(sdf SDF3, res ms3.Vec) error {
116-
if res.X <= 0 || res.Y <= 0 || res.Z <= 0 {
120+
func (c3 *BlockCachedSDF3) Reset(sdf SDF3, resX, resY, resZ float32) error {
121+
if resX <= 0 || resY <= 0 || resZ <= 0 {
117122
return errors.New("invalid resolution for BlockCachedSDF3")
118123
}
119124
if c3.m == nil {
@@ -125,7 +130,7 @@ func (c3 *BlockCachedSDF3) Reset(sdf SDF3, res ms3.Vec) error {
125130
// Ncells := ms3.DivElem(bb.Size(), res)
126131
*c3 = BlockCachedSDF3{
127132
sdf: sdf,
128-
mul: ms3.DivElem(ms3.Vec{X: 1, Y: 1, Z: 1}, res),
133+
mul: ms3.DivElem(ms3.Vec{X: 1, Y: 1, Z: 1}, ms3.Vec{X: resX, Y: resY, Z: resZ}),
129134
m: c3.m,
130135
posbuf: c3.posbuf[:0],
131136
distbuf: c3.distbuf[:0],

gleval/gpu_cgo.go

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ func computeEvaluate[T ms2.Vec | ms3.Vec](pos []T, dist []float32, invocX int, o
187187
}
188188
err := glgl.Err()
189189
if err != nil {
190+
p.Unpin()
190191
return fmt.Errorf("binding SSBOs: %w", err)
191192
}
192193
}

glrender/glrender_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func levelsVisual(filename string, startCube icube, targetLvl int, origin ms3.Ve
226226
s = bld.Union(s, bb)
227227
}
228228
s = bld.Scale(s, 0.5/s.Bounds().Size().Max())
229-
glbuild.ShortenNames3D(&s, 8)
229+
glbuild.ShortenNames3D(&s, 12)
230230
prog := glbuild.NewDefaultProgrammer()
231231
fp, err := os.Create(filename)
232232
if err != nil {

glrender/octreerenderer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ func (oc *Octree) debugVisual(filename string, lvlDescent int, merge glbuild.Sha
253253
s = bld.Union(s, bb)
254254
}
255255
s = bld.Scale(s, 0.5/s.Bounds().Size().Max())
256-
glbuild.ShortenNames3D(&s, 8)
256+
glbuild.ShortenNames3D(&s, 12)
257257
prog := glbuild.NewDefaultProgrammer()
258258
fp, err := os.Create(filename)
259259
if err != nil {

gsdf.go

+31-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package gsdf
22

33
import (
44
_ "embed"
5+
"encoding/binary"
56
"errors"
67
"fmt"
78
"unsafe"
89

910
"github.com/chewxy/math32"
1011
"github.com/soypat/glgl/math/ms2"
1112
"github.com/soypat/glgl/math/ms3"
13+
"github.com/soypat/gsdf/glbuild"
1214
)
1315

1416
const (
@@ -41,18 +43,14 @@ type Builder struct {
4143
}
4244

4345
func (bld *Builder) useGPU(n int) bool {
44-
return bld.limVecGPU != 0 && n > bld.limVecGPU || n > 1024
46+
return bld.limVecGPU != 0 && n > bld.limVecGPU || n > 1
4547
}
4648

4749
func makeHashName[T any](dst []byte, name string, vec []T) []byte {
4850
var z T
4951
data := unsafe.Pointer(&vec[0])
50-
bdata := unsafe.Slice((*byte)(data), len(vec)*int(unsafe.Sizeof(z)))
51-
_ = bdata
52-
// for _, b := range bdata {
53-
54-
// }
55-
return fmt.Appendf(dst, "%s%x", name, uintptr(data))
52+
sz := len(vec) * int(unsafe.Sizeof(z))
53+
return fmt.Appendf(dst, "%s%x_%x", name, uintptr(data), sz)
5654
}
5755

5856
func (bld *Builder) Flags() Flags {
@@ -186,3 +184,29 @@ func hashAdd(a, b, num float32) (aNew, bNew float32) {
186184
func hashfint(f float32) float32 {
187185
return float32(int(f*1000000)%1000000) / 1000000 // Keep within [0.0, 1.0)
188186
}
187+
188+
func hash(b []byte, in uint64) uint64 {
189+
x := in
190+
for len(b) >= 8 {
191+
x ^= binary.LittleEndian.Uint64(b)
192+
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9
193+
x = (x ^ (x >> 27)) * 0x94d049bb133111eb
194+
x ^= x >> 31
195+
b = b[8:]
196+
197+
}
198+
if len(b) > 0 {
199+
var buf [8]byte
200+
copy(buf[:], b)
201+
x ^= binary.LittleEndian.Uint64(buf[:])
202+
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9
203+
x = (x ^ (x >> 27)) * 0x94d049bb133111eb
204+
x ^= x >> 31
205+
}
206+
return x
207+
}
208+
209+
func hashshaderptr(s glbuild.Shader) uint64 {
210+
v := *(*[2]uintptr)(unsafe.Pointer(&s))
211+
return (uint64(v[0]) ^ (uint64(v[1]) << 8)) * 0xbf58476d1ce4e5b9
212+
}

0 commit comments

Comments
 (0)