shaders/frustumCull.glslfx
shaders/imageShader.glslfx
shaders/instancing.glslfx
+ shaders/invalidMaterialNetwork.glslfx
shaders/mesh.glslfx
shaders/meshFaceCull.glslfx
shaders/meshNormal.glslfx
#include "pxr/imaging/hio/glslfx.h"
+#include "pxr/base/tf/envSetting.h"
#include "pxr/base/tf/getenv.h"
-
#include "pxr/base/tf/hash.h"
#include <mutex>
PXR_NAMESPACE_OPEN_SCOPE
+TF_DEFINE_ENV_SETTING(HDST_ENABLE_BROKEN_SHADER_VISUAL_FEEDBACK, false,
+ "Provide visual feedback for prims when the composed shader fails to "
+ "compile or link by using the invalid material shader.");
+
namespace
{
+
+bool
+_ProvideVisualFeedbackForBrokenShaders()
+{
+ static const bool enabled =
+ TfGetEnvSetting(HDST_ENABLE_BROKEN_SHADER_VISUAL_FEEDBACK);
+ return enabled;
+}
+
const std::string&
_GetPrimPathSubstringForDebugLogging()
{
return fallbackShader;
}
+static
+HdSt_MaterialNetworkShaderSharedPtr
+_GetInvalidMaterialNetworkShader()
+{
+ static std::once_flag once;
+ static HdSt_MaterialNetworkShaderSharedPtr invalidShader;
+
+ std::call_once(once, [](){
+ HioGlslfxSharedPtr glslfx =
+ std::make_shared<HioGlslfx>(
+ HdStPackageInvalidMaterialNetworkShader());
+
+ invalidShader.reset(new HdStGLSLFXShader(glslfx));
+ });
+
+ return invalidShader;
+}
+
HdSt_DrawBatch::_DrawingProgram &
HdSt_DrawBatch::_GetDrawingProgram(HdStRenderPassStateSharedPtr const &state,
HdStResourceRegistrySharedPtr const &resourceRegistry)
TF_CODING_ERROR("Failed to compile shader for prim %s.",
firstDrawItem->GetRprimID().GetText());
-
// If we failed to compile the material network, replace it
- // with the fallback material network shader and try again.
+ // either with the invalid material network shader OR the
+ // fallback material network shader and try again.
// XXX: Note that we only say "material network shader" here
// because it is currently the only one for which we allow
// customization. We expect all the other shaders to compile
// or else the shipping code is broken and needs to be fixed.
// When we open up more shaders for customization, we will
// need to check them as well.
-
- _program.SetMaterialNetworkShader(
- _GetFallbackMaterialNetworkShader());
+
+ const HdSt_MaterialNetworkShaderSharedPtr shader =
+ _ProvideVisualFeedbackForBrokenShaders()
+ ? _GetInvalidMaterialNetworkShader()
+ : _GetFallbackMaterialNetworkShader();
+
+ _program.SetMaterialNetworkShader(shader);
bool res = _program.CompileShader(firstDrawItem,
resourceRegistry,
logCacheLookup);
- // We expect the fallback shader to always compile.
- TF_VERIFY(res, "Failed to compile with fallback material network");
+
+ // We expect the invalid/fallback shader to always compile.
+ TF_VERIFY(res, "Failed to compile with the invalid/fallback "
+ "material network shader.");
}
_shaderHash = shaderHash;
return s;
}
+TfToken
+HdStPackageInvalidMaterialNetworkShader()
+{
+ static TfToken s = _GetShaderPath("invalidMaterialNetwork.glslfx");
+ return s;
+}
+
TfToken
HdStPackageFallbackVolumeShader()
{
HDST_API
TfToken HdStPackageFallbackMaterialNetworkShader();
+HDST_API
+TfToken HdStPackageInvalidMaterialNetworkShader();
+
HDST_API
TfToken HdStPackageFallbackVolumeShader();
//
--- This is what an import might look like.
---- #import $TOOLS/hdSt/shaders/fallbackSurface.glslfx
+--- #import $TOOLS/hdSt/shaders/fallbackMaterialNetwork.glslfx
---
---- The fallback shader is used as a replacement shader if the
---- original material shader failed to compile. It needs to
---- define both the surfaceShader() and displacementShader() terminals.
+--- The fallback shader is used as a replacement shader if no material binding
+--- was provided. It needs to define both the surfaceShader() and
+--- displacementShader() terminals.
---
-- configuration
{
--- /dev/null
+-- glslfx version 0.1
+
+//
+// Copyright 2023 Pixar
+//
+// Licensed under the Apache License, Version 2.0 (the "Apache License")
+// with the following modification; you may not use this file except in
+// compliance with the Apache License and the following modification to it:
+// Section 6. Trademarks. is deleted and replaced with:
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor
+// and its affiliates, except as required to comply with Section 4(c) of
+// the License and to reproduce the content of the NOTICE file.
+//
+// You may obtain a copy of the Apache License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the Apache License with the above modification is
+// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the Apache License for the specific
+// language governing permissions and limitations under the Apache License.
+//
+
+--- This is what an import might look like.
+--- #import $TOOLS/hdSt/shaders/invalidMaterialNetwork.glslfx
+
+---
+--- The invalid shader is used as a replacement shader if the
+--- original material shader failed to compile. It needs to
+--- define both the surfaceShader() and displacementShader() terminals.
+---
+-- configuration
+{
+ "techniques": {
+ "default": {
+ "displacementShader": {
+ "source": [ "Invalid.Displacement" ]
+ },
+ "surfaceShader": {
+ "source": [ "Invalid.Surface" ]
+ }
+ }
+ }
+}
+
+--- --------------------------------------------------------------------------
+-- glsl Invalid.Surface
+
+vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord)
+{
+ vec2 t = gl_FragCoord.xy;
+ float v = mod(round(t.x + t.y), 16.0);
+
+ const vec4 invalidColor = vec4(0.7, 0.3, 0.3, 1.0);
+ return mix(color, invalidColor, v);
+
+ // Alt look:
+ // Override the color to a bright red. Don't light it.
+ // return vec4(0.9, 0.0, 0.0, 1.0);
+}
+--- --------------------------------------------------------------------------
+-- glsl Invalid.Displacement
+
+vec4 displacementShader(int index, vec4 Peye, vec3 Neye, vec4 patchCoord)
+{
+ return Peye;
+}
DEST testUsdImagingGLGeomSubsets
)
+pxr_install_test_dir(
+ SRC testenv/testUsdImagingGLInvalidMaterial
+ DEST testUsdImagingGLInvalidMaterial
+)
+
#
# Register tests that don't depend on build configuration or external libraries
# (such as MaterialX, OpenVDB, PTEX).
#
-
pxr_register_test(testUsdImagingGLBasicDrawing
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testUsdImagingGLBasicDrawing -offscreen -stage basicDrawing/basicDrawing.usda -write testUsdImagingGLBasicDrawing.png"
IMAGE_DIFF_COMPARE
TESTENV testUsdImagingGLAovVisualization
)
+pxr_register_test(testUsdImagingGLInvalidMaterial
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testUsdImagingGLBasicDrawing -offscreen -lighting -shading smooth -frameAll -stage invalidMaterial.usda -write testUsdImagingGLInvalidMaterial.png"
+ IMAGE_DIFF_COMPARE
+ testUsdImagingGLInvalidMaterial.png
+ FAIL 1
+ FAIL_PERCENT 1
+ PERCEPTUAL
+ EXPECTED_RETURN_CODE 0
+ TESTENV testUsdImagingGLInvalidMaterial
+)
+
#
# Conditionally install and register MaterialX tests
#
--- /dev/null
+-- glslfx version 0.1
+
+-- configuration
+{
+ "techniques": {
+ "default": {
+ "surfaceShader": {
+ "source": [ "Surface.Buggy" ]
+ }
+ }
+ }
+}
+
+--- --------------------------------------------------------------------------
+-- glsl Surface.Buggy
+
+vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord)
+{
+ int foo = vec2(0,0); // <-- this won't compile, thankfully.
+ // Use foo below in case compiler optimization eliminates the above line.
+ return vec4(foo, 0, 0.8, 0.8);
+}
--- /dev/null
+#usda 1.0
+(
+ upAxis = "Y"
+)
+
+def DistantLight "Sun"
+{
+ # Use default intensity and direction (light is emitted along -Z).
+ # The latter is fine since the stage is Y up.
+}
+
+def Xform "Cubes"
+{
+ def Cube "RedCube" (
+ prepend apiSchemas = ["MaterialBindingAPI"]
+ )
+ {
+ custom rel material:binding = </Materials/Red>
+ custom double3 xformOp:translate = (-2,0,0)
+ uniform token[] xformOpOrder = ["xformOp:translate"]
+ }
+
+ def Cube "BuggyCube" (
+ prepend apiSchemas = ["MaterialBindingAPI"]
+ )
+ {
+ custom rel material:binding = </Materials/Buggy>
+ custom double3 xformOp:translate = (2,0,0)
+ uniform token[] xformOpOrder = ["xformOp:translate"]
+ }
+}
+
+def Scope "Materials"
+{
+ def Material "Red" (
+ )
+ {
+ token outputs:surface.connect = </Materials/Red/PbrPreview.outputs:surface>
+
+ def Shader "PbrPreview"
+ {
+ uniform token info:id = "UsdPreviewSurface"
+ color3f inputs:diffuseColor = (0.8, 0, 0)
+ token outputs:surface
+ }
+ }
+
+ def Material "Buggy"
+ {
+ token outputs:surface.connect = </Materials/Buggy/Surface.outputs:surface>
+
+ def Shader "Surface"
+ {
+ uniform asset info:glslfx:sourceAsset = @buggyShader.glslfx@
+ uniform token info:implementationSource = "sourceAsset"
+ uniform float3 inputs:diffuseColor = (1, 0, 1)
+ token outputs:surface
+ }
+ }
+}
+