Skip to content
Snippets Groups Projects
Commit 6066de6d authored by Alexander Rose's avatar Alexander Rose
Browse files

error and debugging related improvements to gl lib

parent d7ba4d88
No related branches found
No related tags found
No related merge requests found
......@@ -125,12 +125,7 @@ const glsl300VertPrefix = `#version 300 es
`
const glsl300FragPrefix = `#version 300 es
#define varying in
layout(location = 0) out highp vec4 out_FragColor;
#define gl_FragColor out_FragColor
#define gl_FragDepthEXT gl_FragDepth
#define texture2D texture
layout(location = 0) out highp vec4 out_FragData0;
layout(location = 1) out highp vec4 out_FragData1;
layout(location = 2) out highp vec4 out_FragData2;
layout(location = 3) out highp vec4 out_FragData3;
......@@ -139,6 +134,12 @@ layout(location = 5) out highp vec4 out_FragData5;
layout(location = 6) out highp vec4 out_FragData6;
layout(location = 7) out highp vec4 out_FragData7;
#define varying in
#define texture2D texture
#define gl_FragColor out_FragData0
#define gl_FragDepthEXT gl_FragDepth
#define enabledStandardDerivatives
#define enabledFragDepth
#define requiredDrawBuffers
......
......@@ -7,7 +7,7 @@
import { createProgramCache, ProgramCache } from './program'
import { createShaderCache, ShaderCache } from './shader'
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, getVertexArrayObject, isWebGL2, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers } from './compat';
import { createFramebufferCache, FramebufferCache } from './framebuffer';
import { createFramebufferCache, FramebufferCache, checkFramebufferStatus } from './framebuffer';
import { Scheduler } from 'mol-task';
import { isProductionMode } from 'mol-util/debug';
......@@ -39,6 +39,11 @@ function getErrorDescription(gl: GLRenderingContext, error: number) {
return 'unknown error'
}
export function checkError(gl: GLRenderingContext) {
const error = gl.getError()
if (error) throw new Error(`WebGL error: '${getErrorDescription(gl, error)}'`)
}
function unbindResources (gl: GLRenderingContext) {
// bind null to all texture units
const maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)
......@@ -112,19 +117,13 @@ function waitForGpuCommandsCompleteSync(gl: GLRenderingContext): void {
}
function readPixels(gl: GLRenderingContext, x: number, y: number, width: number, height: number, buffer: Uint8Array | Float32Array) {
if (!isProductionMode && gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
console.error('Reading pixels failed. Framebuffer not complete.')
return
}
if (!isProductionMode) checkFramebufferStatus(gl)
if (buffer instanceof Uint8Array) {
gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer)
} else {
gl.readPixels(x, y, width, height, gl.RGBA, gl.FLOAT, buffer)
}
if (!isProductionMode) {
const error = gl.getError()
if (error) console.log(`Error reading pixels: '${getErrorDescription(gl, error)}'`)
}
if (!isProductionMode) checkError(gl)
}
export function createImageData(buffer: ArrayLike<number>, width: number, height: number) {
......
......@@ -7,10 +7,35 @@
import { WebGLStats } from './context'
import { idFactory } from 'mol-util/id-factory';
import { ReferenceCache, createReferenceCache } from 'mol-util/reference-cache';
import { GLRenderingContext } from './compat';
import { GLRenderingContext, isWebGL2 } from './compat';
const getNextFramebufferId = idFactory()
function getFramebufferStatusDescription(gl: GLRenderingContext, status: number) {
switch (status) {
case gl.FRAMEBUFFER_COMPLETE: return 'complete'
case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return 'incomplete attachment'
case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return 'incomplete missing attachment'
case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return 'incomplete dimensions'
case gl.FRAMEBUFFER_UNSUPPORTED: return 'unsupported'
}
if (isWebGL2(gl)) {
switch (status) {
case gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return 'incomplete multisample'
case gl.RENDERBUFFER_SAMPLES: return 'renderbuffer samples'
}
}
return 'unknown error'
}
export function checkFramebufferStatus(gl: GLRenderingContext) {
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)
if (status !== gl.FRAMEBUFFER_COMPLETE) {
const description = getFramebufferStatusDescription(gl, status)
throw new Error(`Framebuffer status: ${description}`)
}
}
export interface Framebuffer {
readonly id: number
......
......@@ -134,8 +134,12 @@ export function createProgram(gl: GLRenderingContext, state: WebGLState, extensi
vertShaderRef.value.attach(program)
fragShaderRef.value.attach(program)
gl.linkProgram(program)
if (!isProductionMode && !gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(`Could not compile WebGL program. \n\n${gl.getProgramInfoLog(program)}`);
if (!isProductionMode) {
// no-op in FF on Mac, see https://bugzilla.mozilla.org/show_bug.cgi?id=1284425
// gl.validateProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(`Could not compile WebGL program. \n\n${gl.getProgramInfoLog(program)}`);
}
}
const locations = getLocations(gl, program, schema)
......
......@@ -6,7 +6,7 @@
import { createAttributeBuffers, createElementsBuffer, ElementsBuffer, createAttributeBuffer, AttributeKind } from './buffer';
import { createTextures, Texture } from './texture';
import { WebGLContext } from './context';
import { WebGLContext, checkError } from './context';
import { ShaderCode } from '../shader-code';
import { Program } from './program';
import { RenderableSchema, RenderableValues, AttributeSpec, getValueVersions, splitValues, Values } from '../renderable/schema';
......@@ -15,6 +15,8 @@ import { deleteVertexArray, createVertexArray } from './vertex-array';
import { ValueCell } from 'mol-util';
import { ReferenceItem } from 'mol-util/reference-cache';
import { TextureImage, TextureVolume } from 'mol-gl/renderable/util';
import { checkFramebufferStatus } from './framebuffer';
import { isProductionMode } from 'mol-util/debug';
const getNextRenderItemId = idFactory()
......@@ -181,11 +183,24 @@ export function createRenderItem<T extends RenderVariantDefines, S extends keyof
if (elementsBuffer) elementsBuffer.bind()
program.bindAttributes(attributeBuffers)
}
if (!isProductionMode) {
checkFramebufferStatus(ctx.gl)
}
if (elementsBuffer) {
instancedArrays.drawElementsInstanced(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount);
} else {
instancedArrays.drawArraysInstanced(glDrawMode, 0, drawCount, instanceCount)
}
if (!isProductionMode) {
try {
checkError(ctx.gl)
} catch (e) {
// console.log('shaderCode', shaderCode)
// console.log('schema', schema)
// console.log('attributeBuffers', attributeBuffers)
throw new Error(`Error rendering item id ${id}: '${e}'`)
}
}
},
update: () => {
resetValueChanges(valueChanges)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment