/// <summary> /// (Re)initialize the debugger. This method must /// be called whenever a program is compiled. /// </summary> /// <param name="scene"></param> public static void Initilize(Dict scene) { // allocate GPU resources buf = new GLBuffer(DbgBufKey, "dbg", BufferUsageHint.DynamicRead, stage_size * 6 * 16); tex = new GLTexture(DbgTexKey, "dbg", GpuFormat.Rgba32f, buf, null); #if DEBUG // add to scene for debug inspection scene.Add(DbgBufKey, buf); scene.Add(DbgTexKey, tex); #endif passes.Clear(); // reset watch count for indexing in debug mode dbgVarCount = 0; }
/// <summary> /// Bind texture to compute-image unit. /// </summary> /// <param name="unit">Image unit.</param> /// <param name="tex">Texture object.</param> /// <param name="level">Texture mipmap level.</param> /// <param name="layer">Texture array index or texture depth.</param> /// <param name="access">How the texture will be accessed by the shader.</param> /// <param name="format">Pixel format of texture pixels.</param> public static void BindImg(int unit, GLTexture tex, int level = 0, int layer = 0, TextureAccess access = TextureAccess.ReadOnly, GpuFormat format = GpuFormat.Rgba8) => FxDebugger.BindImg(unit, level, tex?.glImg?.Length > 0, layer, access, format, tex?.glname ?? 0);
/// <summary> /// Bind texture to texture unit. /// </summary> /// <param name="unit">Texture unit.</param> /// <param name="tex">Texture object.</param> public static void BindTex(int unit, GLTexture tex) => FxDebugger.BindTex(unit, tex?.glImg?.Target ?? TextureTarget.TextureBuffer, tex?.glname ?? 0);
/// <summary> /// Execute pass. /// </summary> /// <param name="width">Width of the OpenGL control.</param> /// <param name="height">Height of the OpenGL control.</param> /// <param name="frame">The ID of the current frame.</param> public void Exec(int width, int height, int frame) { // in debug mode check if the // OpenGL sate is valid ThrowOnGLError($"OpenGL error at the beginning of pass '{Name}'."); int fbWidth = width, fbHeight = height; /// BIND FRAGMENT OUTPUT // (widthOut and heightOut must be // computed before setting the glViewport) if (fragoutput != null) { fbWidth = fragoutput.Width; fbHeight = fragoutput.Height; fragoutput.Bind(); } /// SET DEFAULT VIEWPORT GL.Viewport(0, 0, fbWidth, fbHeight); /// CALL USER SPECIFIED OPENGL FUNCTIONS foreach (var x in glfunc) { x.mtype.Invoke(null, x.inval); ThrowOnGLError($"OpenGL error in OpenGL function '{x.mtype.Name}' of pass '{Name}'."); } /// BIND PROGRAM if (glname > 0) { GL.BindProgramPipeline(glname); } /// BIND VERTEX OUTPUT (transform feedback) /// must be done after glUseProgram vertoutput?.Bind(); ThrowOnGLError($"OpenGL error vertex output binding of pass '{Name}'."); /// BIND TEXTURES foreach (var x in textures) { GLTexture.BindTex(x.unit, x.obj); ThrowOnGLError($"OpenGL error in texture '{x.obj?.Name}' of pass '{Name}'."); } foreach (var x in texImages) { GLTexture.BindImg(x.unit, x.obj, x.level, x.layer, x.access, x.format); ThrowOnGLError($"OpenGL error in image '{x.obj?.Name}' of pass '{Name}'."); } foreach (var x in sampler) { GL.BindSampler(x.unit, x.obj?.glname ?? 0); ThrowOnGLError($"OpenGL error in sampler '{x.obj?.Name}' of pass '{Name}'."); } /// EXECUTE EXTERNAL CODE foreach (var x in csexec) { x.Update(glname, width, height, fbWidth, fbHeight); ThrowOnGLError($"OpenGL error in C# execution '{x.Name}' of pass '{Name}'."); } /// BIND DEBUGGER if (TraceDebugInfo && GenDebugInfo && drawcalls.Count > 0) { try { Shader.DrawCall = drawcalls.First(); if (dbgcomp != null) { dbgcomp.Debug(); } else if (dbgvert != null) { dbgvert.Debug(); dbgtess?.Debug(); dbgeval?.Debug(); dbggeom?.Debug(); dbgfrag?.Debug(); } } catch (Exception e) { throw new Exception($"Debugger crashed with the following message: {e.Message}", e); } finally { TraceDebugInfo = false; } } /// EXECUTE DRAW AND COMPUTE CALLS // begin timer query MeasureTime(); StartTimer(frame); // execute draw calls drawcalls.ForEach(call => call.Draw()); compcalls.ForEach(call => call.Compute()); // end timer query EndTimer(); /// UNBIND OPENGL OBJECTS csexec.ForEach(e => e.EndPass(glname)); /// UNBIND OUTPUT BUFFERS fragoutput?.Unbind(); vertoutput?.Unbind(); /// UNBIND OPENGL RESOURCES GL.BindProgramPipeline(0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GL.BindBuffer(BufferTarget.DrawIndirectBuffer, 0); GL.BindBuffer(BufferTarget.DispatchIndirectBuffer, 0); GL.BindVertexArray(0); // in debug mode check if the pass // left a valid OpenGL sate ThrowOnGLError($"OpenGL error at the end of pass '{Name}'."); }
/// <summary> /// Bind texture to compute-image unit. /// </summary> /// <param name="unit">Image unit.</param> /// <param name="tex">Texture object.</param> /// <param name="level">Texture mipmap level.</param> /// <param name="layer">Texture array index or texture depth.</param> /// <param name="access">How the texture will be accessed by the shader.</param> /// <param name="format">Pixel format of texture pixels.</param> public static void BindImg(int unit, GLTexture tex, int level = 0, int layer = 0, TextureAccess access = TextureAccess.ReadOnly, GpuFormat format = GpuFormat.Rgba8) { GL.BindImageTexture(unit, tex?.glname ?? 0, level, tex?.glImg?.Length > 0, Math.Max(layer, 0), access, (SizedInternalFormat)format); }