@@ -30,10 +30,17 @@ type Value struct {
30
30
// index of this value within the Var list of values
31
31
Index int
32
32
33
- // VarSize is the size of each Var element, which includes any fixed ArrayN
33
+ // VarSize is the size of each Var element, which includes any fixed Var. ArrayN
34
34
// array size specified on the Var.
35
+ // The actual buffer size is VarSize * Value.ArrayN (or DynamicN for dynamic).
35
36
VarSize int
36
37
38
+ // ArrayN is the actual number of array elements, for Uniform or Storage
39
+ // variables without a fixed array size (i.e., the Var ArrayN = 1).
40
+ // This is set when the buffer is actually created, based on the data,
41
+ // or can be set directly prior to buffer creation.
42
+ ArrayN int
43
+
37
44
// DynamicIndex is the current index into a DynamicOffset variable
38
45
// to use for the SetBindGroup call. Note that this is an index,
39
46
// not an offset, so it indexes the DynamicN Vars in the Value,
@@ -112,6 +119,7 @@ func (vl *Value) init(vr *Var, dev *Device, idx int) {
112
119
vl .Index = idx
113
120
vl .Name = fmt .Sprintf ("%s_%d" , vr .Name , vl .Index )
114
121
vl .VarSize = vr .MemSize ()
122
+ vl .ArrayN = 1
115
123
vl .alignBytes = vr .alignBytes
116
124
vl .AlignVarSize = MemSizeAlign (vl .VarSize , vl .alignBytes )
117
125
vl .isDynamic = vl .role == Vertex || vl .role == Index || vr .DynamicOffset
@@ -129,11 +137,12 @@ func (vl *Value) MemSize() int {
129
137
if vl .isDynamic {
130
138
return vl .AlignVarSize * vl .dynamicN
131
139
}
132
- return vl .VarSize
140
+ return vl .ArrayN * vl . VarSize
133
141
}
134
142
135
143
// CreateBuffer creates the GPU buffer for this value if it does not
136
144
// yet exist or is not the right size.
145
+ // For !ReadOnly [Storage] buffers, calls [Value.CreateReadBuffer].
137
146
func (vl * Value ) CreateBuffer () error {
138
147
if vl .role == SampledTexture {
139
148
return nil
@@ -159,6 +168,9 @@ func (vl *Value) CreateBuffer() error {
159
168
}
160
169
vl .AllocSize = sz
161
170
vl .buffer = buf
171
+ if vl .role == Storage && ! vl .vvar .ReadOnly {
172
+ vl .CreateReadBuffer ()
173
+ }
162
174
return nil
163
175
}
164
176
@@ -214,6 +226,9 @@ func (vl *Value) SetDynamicN(n int) {
214
226
215
227
// SetValueFrom copies given values into value buffer memory,
216
228
// making the buffer if it has not yet been constructed.
229
+ // The actual ArrayN size of Storage or Uniform variables will
230
+ // be computed based on the size of the from bytes, relative to
231
+ // the variable size.
217
232
// IMPORTANT: do not use this for dynamic offset Uniform or
218
233
// Storage variables, as the alignment will not be correct;
219
234
// See [SetDynamicFromBytes].
@@ -223,6 +238,7 @@ func SetValueFrom[E any](vl *Value, from []E) error {
223
238
224
239
// SetFromBytes copies given bytes into value buffer memory,
225
240
// making the buffer if it has not yet been constructed.
241
+ // For !ReadOnly [Storage] buffers, calls [Value.CreateReadBuffer].
226
242
// IMPORTANT: do not use this for dynamic offset Uniform or
227
243
// Storage variables, as the alignment will not be correct;
228
244
// See [SetDynamicFromBytes].
@@ -232,12 +248,19 @@ func (vl *Value) SetFromBytes(from []byte) error {
232
248
return errors .Log (err )
233
249
}
234
250
nb := len (from )
251
+ an := nb / vl .VarSize
252
+ aover := nb % vl .VarSize
253
+ if aover != 0 {
254
+ err := fmt .Errorf ("gpu.Value SetFromBytes %s, Size passed: %d is not an even multiple of the variable size: %d" , vl .Name , nb , vl .VarSize )
255
+ return errors .Log (err )
256
+ }
235
257
if vl .isDynamic { // Vertex, Index at this point
236
- dn := nb / vl .VarSize
237
- vl .SetDynamicN (dn )
258
+ vl .SetDynamicN (an )
259
+ } else {
260
+ vl .ArrayN = an
238
261
}
239
262
tb := vl .MemSize ()
240
- if nb != tb {
263
+ if nb != tb { // this should never happen, but justin case
241
264
err := fmt .Errorf ("gpu.Value SetFromBytes %s, Size passed: %d != Size expected %d" , vl .Name , nb , tb )
242
265
return errors .Log (err )
243
266
}
@@ -254,6 +277,9 @@ func (vl *Value) SetFromBytes(from []byte) error {
254
277
}
255
278
vl .buffer = buf
256
279
vl .AllocSize = nb
280
+ if vl .role == Storage && ! vl .vvar .ReadOnly {
281
+ vl .CreateReadBuffer ()
282
+ }
257
283
} else {
258
284
err := vl .device .Queue .WriteBuffer (vl .buffer , 0 , from )
259
285
if errors .Log (err ) != nil {
@@ -406,9 +432,8 @@ func (vl *Value) SetFromTexture(tx *Texture) *Texture {
406
432
}
407
433
408
434
// CreateReadBuffer creates a read buffer for this value,
409
- // if it does not yet exist or is not the right size .
435
+ // for [Storage] values only. Automatically called for !ReadOnly .
410
436
// Read buffer is needed for reading values back from the GPU.
411
- // Only for Storage role variables.
412
437
func (vl * Value ) CreateReadBuffer () error {
413
438
if ! (vl .role == Storage || vl .role == StorageTexture ) {
414
439
return nil
0 commit comments