【问题标题】:Dart WebGL DebuggingDart WebGL 调试
【发布时间】:2014-01-21 03:01:13
【问题描述】:

我已经开始使用 Dart 和 WebGL 编写一些技术演示和测试,但是我似乎无法弄清楚如何在 Dart 中调试 WebGL。

Markus Notch(Minecraft 的创造者)有一个 livestream on twitch,他也在其中使用 Dart 和 WebGL 编写了他的游戏,但是每次他搞砸了一些东西时,他都会从 WebGL 的控制台中收到一个错误日志,其中包含错误的描述.例如退房 1:13:30。遗憾的是,我在他的代码中找不到进行调试的部分。

当然,我可以使用getShaderParameter()getProgramParameter() 检查着色器中的错误,然后使用适当的getInfoLog() 方法获取错误日志,但是对于常规调试(例如检查INVALID_ENUM 错误)我可以使用getError() 将错误作为整数获取,但不能将其转换为枚举、错误消息或任何人类可读的调试信息。

我尝试查看web_gl.dart 的源代码,但在其中找不到任何可以进行调试的内容。

非常感谢任何帮助。

编辑:基于 Notch 的回答 Chromium(可能)会自动记录这些错误。不过,gl.getError() 不适合我,而 Chromium 控制台为空时会报告错误 1280。 :(

Edit2:找到解决方案,看看我的答案。

【问题讨论】:

  • Dart Editor 控制台中的输出看起来像是 Chrome 的重定向默认输出。如果 Chrome 检测到您的 WebGL 代码有问题,它会将输出打印到控制台,但您无法以任何方式控制它。但 Chrome 只检测严重问题。
  • 关于 getError():没有简单易用的构建方式。 [webgl-debug.js][1] 带有一个名为WebGLDebugUtils.glEnumToString(enum) 的方法,可以将它们转换为命名错误。您可以使用 js-interop 使用该方法,但由于它需要使用 WebGL 进行初始化,因此它可能不起作用(我不确定 js-interop 是否可以将 Dart 渲染上下文转换为 Javascript 上下文)。如果您看一下代码,您可以使用镜像自己实现它,但这并不是一个好的解决方案。 [1]:khronos.org/webgl/wiki/Debugging

标签: debugging webgl dart


【解决方案1】:

编辑:我完全误解了这个问题。忽略这个答案。

对于着色器(顶点和片段):

gl.compileShader(shader);
boolean isCompiled = gl.getShaderParameter(shader, WebGL.COMPILE_STATUS);
if (isCompiled == false) {
  String compileLog = gl.getShaderInfoLog(shader);
  // Display the compile log
}

对于链接程序:

gl.linkProgram(program);
bool isCompiled = gl.getProgramParameter(program, WebGL.LINK_STATUS);
if (isCompiled == false) {
  String linkLog = gl.getProgramInfoLog(program);
  // Display the link log
}

在某些硬件上,如果没有错误,着色器信息日志和程序信息日志将是一个空字符串,但您不能依赖此行为。

【讨论】:

  • 感谢 Notch 亲自回答这个问题,但恐怕你误解了我的问题。我知道如何调试着色器,我遇到的问题是如何将错误从gl.getErrors() 转换为实际的错误消息,就像您在 1:13:32 “WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER 绑定”。
  • 哦,这就是我前一天晚上喝酒后试图变得聪明的结果。我不知道该怎么做。我假设 Chromium 正在输出 WebGL 错误消息。
  • 似乎我错过了一些明显的东西,或者问题出在我的安装上。我会试着调查一下,不过还是谢谢你的努力。 :)
【解决方案2】:

好的,所以我实际上找到了答案,而且非常明显。

Notch 是对的:Chromium 会自动报告 WebGL 错误。但是,它在一段时间后停止记录它们(“WebGL: too many errors, no more errors will be reported to the console for this context.”),由于我每帧都在记录东西,我的控制台很快就填满了我自己的信息,将 Chromium 的日志推送到非常顶部,甚至删除它们(不确定调试控制台最多可以存储多少行,但我记得滚动到顶部几次,我从未见过 Chromium 的报告)。

应用程序的快速启动和停止显示信息。
一定喜欢这种错误。 叹息

【讨论】:

    【解决方案3】:

    在这里聚会有点晚了,但是有一种强大的方法可以在 Dart 中处理 WebGL 中的错误,那就是通过为 WebGLRenderingContext 创建一个代理对象。此解决方案使用 dart:mirrors,因此仅应在开发期间使用,并且应在交付代码中关闭。关闭它的另一个原因是,一直调用 getError 可能会真正消耗您的性能,但这提供了一种在开发过程中寻找错误的相对轻松的方法。

    class DebugRenderingContext implements WebGL.RenderingContext {
      final StreamController<RenderingErrorEvent> _onErrorController;
      final WebGL.RenderingContext _gl;
    
      DebugRenderingContext(WebGL.RenderingContext gl)
          : _gl = gl
          , _onErrorController = new StreamController<RenderingErrorEvent>();
    
      Stream<RenderingErrorEvent> get onError => _onErrorController.stream;
    
      dynamic noSuchMethod(Invocation invocation) {
        // Invoke the method and get the result
        var mirror = reflect(_gl);
        var result = mirror.delegate(invocation);
    
        // See if there was an error
        var errorCode = _gl.getError();
    
        // Multiple errors can occur with a single call to WebGL so continue to
        // loop until WebGL doesn't return an error
        while (errorCode != WebGL.NO_ERROR) {
          if (!_onErrorController.isPaused) {
            // Query the symbol name
            var methodName = MirrorSystem.getName(invocation.memberName);
    
            // Put the error in the stream
            _onErrorController.add(new RenderingErrorEvent._internal(errorCode, methodName));
          }
    
          errorCode = _gl.getError();
        }
    
        return result;
      }
    }
    

    所以这段代码包装了一个 WebGL.RenderingContext 并通过类的 noSuchMethod 方法调用实际上下文的方法。 noSuchMethod 在调用的镜像中传递,该镜像提供被调用的方法和参数。这被委托给实际的 WebGL.RenderingContext。

    从那里检查 getError 值,如果发现错误,则将其放入流中。这只是一个类,可以为您提供类似于 Khronos 提供的良好输出。

    class RenderingErrorEvent {
      /// The [WebGL] error code.
      final int error;
      /// The name of the method whose call resulted in the [error].
      final String methodName;
    
      RenderingErrorEvent(this.error, this.methodName);
    
      /// Retrieves a human readable error message.
      String get message {
        var errorMessage;
    
        switch (error) {
          case WebGL.INVALID_ENUM:
            errorMessage = 'An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.';
            break;
          case WebGL.INVALID_VALUE:
            errorMessage = 'A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.';
            break;
          case WebGL.INVALID_OPERATION:
            errorMessage = 'The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.';
            break;
          case WebGL.INVALID_FRAMEBUFFER_OPERATION:
            errorMessage = 'The framebuffer object is not complete. The offending command is ignored and has no other side effect than to set the error flag.';
            break;
          case WebGL.OUT_OF_MEMORY:
            errorMessage = 'There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.';
            break;
          default:
            errorMessage = 'An unknown error occurred';
            break;
        }
    
        return '${methodName}: ${errorMessage}';
      }
    }
    

    此代码不处理扩展,但可以通过扩展来处理。您只需要提供一个 getExtension 方法并围绕您关心的扩展创建相同类型的包装器。

    【讨论】:

      【解决方案4】:

      也许这是来自 web_gl 模块的日志输出。 您可以尝试将以下代码添加到您的main()

      Logger.root.level = Level.ALL;
      Logger.root.onRecord.listen((LogRecord rec) {
        print('${rec.level.name}: ${rec.time}: ${rec.message}');
      });
      

      ** 编辑 **
      我试过了,我认为打印日志输出没有帮助。

      您可以试试 Chrome 扩展程序 WebGL InspectorWeb Tracing Framework

      【讨论】:

      • WebGL 检查器仅适用于 Javascript 代码,与 Dart2Js 不兼容。但我不确定跟踪框架。上次我试过了,没用,不过没啥意思。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-19
      • 2014-01-10
      • 1970-01-01
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多