Request:
To support WebGPU/WGSL (translated from GLSL), GLSL Vulkan code option for needs separate texture2D and sampler binding handles passed in as function parameters instead of only sampler2D.
Description:
WebGPU/WGSL is stricter and can only bind separate texture2D and sampler, contrary to GLSL Vulkan which has options to bind a combined sampler2D (texture2D+sampler) as well as bind separate texture2D and sampler. There also looks to be a limitation in both GLSL and WGSL that prevents one from constructing a sampler2D struct (with texture2D and sampler) when one binds the texture2D and sampler separately.
To allow MaterialX GLSL Vulkan shader code to work with USD WebGPU, the generated MaterialX GLSL Vulkan code needs to be able to pass separate texture2D and sampler variables.
Steps to Reproduce:
With shader code using separate binding of texture2D and sampler, try to compile with glslang.
./glslang --target-env vulkan1.3
Original, using sampler2D: (works with GLSL Vulkan, but not WebGPU/WGSL)
layout(binding = 13) uniform sampler2D domeLightFallback;
void mx_image_color3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result)
{
...
}
void NG_tiledimage_vector3(sampler2D file, vec3 default1, vec2 texcoord1, vec2 uvtiling, vec2 uvoffset, vec2 realworldimagesize, vec2 realworldtilesize, int filtertype, int framerange, int frameoffset, int frameendaction, out vec3 out1)
{
...
mx_image_vector3(file, 0, default1, N_multtilesize_vector3_out, 2, 2, filtertype, framerange, frameoffset, frameendaction, vec2(1.000000, 1.000000), vec2(0.000000, 0.000000), N_img_vector3_out);
...
}
Proposed Option, using texture2D and sampler:
layout(binding = 0, set = 1) uniform texture2D textureBind_domeLightFallback;
layout(binding = 0, set = 2) uniform sampler samplerBind_domeLightFallback;
void mx_image_color3(texture2D textureBind_tex, sampler samplerBind_tex, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result)
{
vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
result = texture(sampler2D(textureBind_tex, samplerBind_tex), uv).rgb;
}
void NG_tiledimage_vector3(texture2D textureBind_file, sampler samplerBind_file, vec3 default1, vec2 texcoord1, vec2 uvtiling, vec2 uvoffset, vec2 realworldimagesize, vec2 realworldtilesize, int filtertype, int framerange, int frameoffset, int frameendaction, out vec3 out1)
{
...
mx_image_vector3(textureBind_file, samplerBind_file, 0, default1, N_multtilesize_vector3_out, 2, 2, filtertype, framerange, frameoffset, frameendaction, vec2(1.000000, 1.000000), vec2(0.000000, 0.000000), N_img_vector3_out);
...
}
Workarounds (and their limitations):
- Workaround1: USD WebGPU tries to workaround by using a #define. This works for some of the functions that use sampler2D directly. However, the GLSL compiler does not allow sampler2D with this construct to be passed in as a function parameter. This does not work for the shader code output from MaterialX.
#define HgiGetSampler_domeLightFallback() sampler2D(textureBind_domeLightFallback, samplerBind_domeLightFallback)
- Workaround2: Unroll mx_image* functions into function calls to remove passing in sampler2D as a function parameter. This works for some of the MaterialX shader code samples like standard_surface_plastic.mtlx. However, this does not work on calls like NG_tiledimage_vector3() that take a sampler2D function parameter and then pass it into mx_image_vector3(), which is used by more complex materials.
- Workaround3: Regex string replace sampler2D with texture2d textureBind_, sampler samplerBind_ for NG_tiledimage_vector3 and similar functions. This allows for standard_surface_brick_procedural.mtlx to now work.
Request:
To support WebGPU/WGSL (translated from GLSL), GLSL Vulkan code option for needs separate texture2D and sampler binding handles passed in as function parameters instead of only sampler2D.
Description:
WebGPU/WGSL is stricter and can only bind separate texture2D and sampler, contrary to GLSL Vulkan which has options to bind a combined sampler2D (texture2D+sampler) as well as bind separate texture2D and sampler. There also looks to be a limitation in both GLSL and WGSL that prevents one from constructing a sampler2D struct (with texture2D and sampler) when one binds the texture2D and sampler separately.
To allow MaterialX GLSL Vulkan shader code to work with USD WebGPU, the generated MaterialX GLSL Vulkan code needs to be able to pass separate texture2D and sampler variables.
Steps to Reproduce:
With shader code using separate binding of texture2D and sampler, try to compile with
glslang../glslang --target-env vulkan1.3Original, using sampler2D: (works with GLSL Vulkan, but not WebGPU/WGSL)
Proposed Option, using texture2D and sampler:
Workarounds (and their limitations):
#define HgiGetSampler_domeLightFallback() sampler2D(textureBind_domeLightFallback, samplerBind_domeLightFallback)