-
-
Notifications
You must be signed in to change notification settings - Fork 36k
Description
Description
The internal state of TextureNode
can conflict with other state (e.g. biasNode
, gradNode
, and compareNode
) and lead to unexpected code being generated. For example:
const sampleNeighbors = (textureNode, coord) => {
// The texture nodes below will "sample" instead of "load" with a wrong
// interpretation of "coord", because the "textureNode" has a "biasNode":
const tex1 = textureNode.load(coord)
const tex2 = textureNode.offset(ivec2(0, 1)).load(coord)
...
}
const textureNode = texture(image).bias(0.1)
const neighbors = sampleNeighbors(textureNode, screenCoordinate)
The code below doesn't solve this because texture()
copies biasNode
as well:
const tex1 = texture(textureNode).load(coord) // This will still "sample".
This also doesn't solve if we mutate dependencies in place.
const tex1 = textureNode.getBase().load(coord) // This will still "sample".
// In another place:
textureNode.biasNode = float(0.1)
The following is also problematic because it breaks the reference in value
, so later updates to textureNode.value
are not reflected.
const tex1 = texture(textureNode.value).load(coord) // Out of sync with "textureNode".
// In another place:
textureNode.value = anotherImage
Solution
Introducing explicit functions like below could solve this issue. The names can be adjusted to better align with other TSL functions (textureSize
appears to follow GLSL rather than WGSL).
textureLoad(textureNode, coords, [level = 0])
textureSample(textureNode, coords, [offset])
textureSampleBias(textureNode, coords, bias, [offset])
textureSampleGrad(textureNode, coords, ddx, ddy, [offset])
textureSampleLevel(textureNode, coords, level, [offset])
textureGather(textureNode, coords, [component = 0], [offset])
textureGatherCompare(textureNode, coords, depthRef, [offset])
textureSampleCompare(textureNode, coords, depthRef, [offset])
textureSampleCompareLevel(textureNode, coords, depthRef, [offset])
Alternatives
- Clear internal fields that conflict with the operation implied by the most recent call to
TextureNode
. (e.g. clearbiasNode
,gradNode
whenload()
is called). This would be a promising alternative. - Add a method like
TextureNode.reset()
to create a freshTextureNode
with a clean state. - Refactor the conditionals in
TextureNode.generateSnippet()
, but I doubt it would fully address the issue.
Additional context
Below is a list of texture-related WGSL and GLSL functions and their implementation status in TSL. This hopefully shows the complexity of mapping the internal state to specific sampling functions.
Load
TSL | .level(level).load(coords) |
WGSL | textureLoad (texture, coords, level) |
GLSL | texelFetch (sampler, coords, level) |
Load with offset
TSL | .offset(offset).load(coords) |
WGSL | No built-in function |
GLSL | texelFetchOffset (sampler, coords, level, offset) |
Sample
TSL | .sample(coords) |
WGSL | textureSample (texture, sampler, coords) |
GLSL | texture (sampler, coords) |
Sample with offset
TSL | .offset(offset).sample(coords) |
WGSL | textureSample (texture, sampler, coords, offset) |
GLSL | textureOffset (sampler, coords, offset) |
Sample with bias
TSL | .bias(bias).sample(coords) |
WGSL | textureSampleBias (texture, sampler, coords, bias) |
GLSL | texture (sampler, coords, bias) |
Sample with bias and offset
TSL | .bias(bias).offset(offset).sample(coords) |
WGSL | textureSampleBias (texture, sampler, coords, bias, offset) |
GLSL | texture (sampler, coords, offset, bias) |
Sample with grad
TSL | .grad(ddx, ddy).sample(coords) |
WGSL | textureSampleGrad (texture, sampler, coords, ddx, ddy) |
GLSL | textureGrad (sampler, coords, ddx, ddy) |
Sample with grad and offset
TSL | .grad(ddx, ddy).offset(offset).sample(coords) |
WGSL | textureSampleGrad (texture, sampler, coords, ddx, ddy, offset) |
GLSL | textureGradOffset (sampler, coords, ddx, ddy, offset) |
Sample with level
TSL | .level(level).sample(coords) |
WGSL | textureSampleLevel (texture, sampler, coords, level) |
GLSL | textureLod (sampler, coords, level) |
Sample with level and offset
TSL | .level(level).offset(offset).sample(coords) |
WGSL | textureSampleLevel (texture, sampler, coords, level, offset) |
GLSL | textureLodOffset (sampler, coords, level, offset) |
Gather four texels
TSL | Not implemented |
WGSL | textureGather (component, texture, sampler, coords) |
GLSL | textureGather (sampler, coords, component) |
Gather four texels with offset
TSL | Not implemented |
WGSL | textureGather (component, texture, sampler, coords, offset) |
GLSL | textureGatherOffset (sampler, coords, offset, component) |
Gather and compare four texels
TSL | Not implemented |
WGSL | textureGatherCompare (texture, sampler, coords, ref) |
GLSL | textureGather (sampler, coords, ref) |
Gather and compare four texels with offset
TSL | Not implemented |
WGSL | textureGatherCompare (texture, sampler, coords, ref, offset) |
GLSL | textureGatherOffset (sampler, coords, ref, offset) |
Compare
TSL | .compare(ref).sample(coords) |
WGSL | textureSampleCompare (texture, sampler, coords, ref) |
GLSL | texture (sampler, (coords, ref)) |
Compare with offset
TSL | .offset(offset).compare(ref).sample(coords) |
WGSL | textureSampleCompare (texture, sampler, coords, ref, offset) |
GLSL | textureOffset (sampler, (coords, ref), offset) |
Compare with level
TSL | .level(level).compare(ref).sample(coords) Note: Not tested. |
WGSL | textureSampleCompareLevel (texture, sampler, coords, ref) Note: Level is fixed to 0 syntactically. |
GLSL | textureLod (sampler, (coords, ref), level) |
Compare with level and offset
TSL | .level(level).offset(offset).compare(ref).sample(coords) Note: Not tested. |
WGSL | textureSampleCompareLevel (texture, sampler, coords, ref, offset) Note: Level is fixed to 0 syntactically. |
GLSL | textureLodOffset (sampler, (coords, ref), level, offset) |
Query samples
TSL | Not implemented |
WGSL | textureNumSamples (texture) |
GLSL | textureSamples (sampler) |
Query levels
TSL | Not implemented |
WGSL | textureNumLevels (texture) |
GLSL | textureQueryLevels (sampler) |
Query layers
TSL | Not implemented |
WGSL | textureNumLayers (texture) |
GLSL | textureSize (sampler).z |
Query size
TSL | .size(level) |
WGSL | textureDimensions (texture, level) |
GLSL | textureSize (sampler, level) |