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

added basic checks if gl program is compatible with schema

parent 610f3ba9
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@
*/
import { ValueCell } from 'mol-util';
import { ArrayKind, AttributeItemSize, ElementsKind, AttributeValues } from '../webgl/buffer';
import { AttributeItemSize, ElementsKind, AttributeValues, AttributeKind } from '../webgl/buffer';
import { UniformKind, UniformValues } from '../webgl/uniform';
import { DefineKind, DefineValues } from '../shader-code';
import { Vec2, Vec3, Vec4, Mat3, Mat4 } from 'mol-math/linear-algebra';
......@@ -94,8 +94,8 @@ export function getValueVersions<T extends RenderableValues>(values: T) {
//
export type AttributeSpec<K extends ArrayKind> = { type: 'attribute', kind: K, itemSize: AttributeItemSize, divisor: number }
export function AttributeSpec<K extends ArrayKind>(kind: K, itemSize: AttributeItemSize, divisor: number): AttributeSpec<K> {
export type AttributeSpec<K extends AttributeKind> = { type: 'attribute', kind: K, itemSize: AttributeItemSize, divisor: number }
export function AttributeSpec<K extends AttributeKind>(kind: K, itemSize: AttributeItemSize, divisor: number): AttributeSpec<K> {
return { type: 'attribute', kind, itemSize, divisor }
}
......@@ -128,7 +128,7 @@ export function ValueSpec<K extends ValueKind>(kind: K): ValueSpec<K> {
export type RenderableSchema = {
[k: string]: (
AttributeSpec<ArrayKind> | UniformSpec<UniformKind> | TextureSpec<TextureKind> |
AttributeSpec<AttributeKind> | UniformSpec<UniformKind> | TextureSpec<TextureKind> |
ValueSpec<ValueKind> | DefineSpec<DefineKind> | ElementsSpec<ElementsKind>
)
}
......
......@@ -147,9 +147,34 @@ export function createBuffer(ctx: WebGLContext, array: ArrayType, usageHint: Usa
//
export type AttributeItemSize = 1 | 2 | 3 | 4 | 16
export type AttributeKind = 'float32' | 'int32'
export function getAttribType(ctx: WebGLContext, kind: AttributeKind, itemSize: AttributeItemSize) {
const { gl } = ctx
switch (kind) {
case 'int32':
switch (itemSize) {
case 1: return gl.INT
case 2: return gl.INT_VEC2
case 3: return gl.INT_VEC3
case 4: return gl.INT_VEC4
}
break
case 'float32':
switch (itemSize) {
case 1: return gl.FLOAT
case 2: return gl.FLOAT_VEC2
case 3: return gl.FLOAT_VEC3
case 4: return gl.FLOAT_VEC4
case 16: return gl.FLOAT_MAT4
}
break
}
throw new Error(`unknown attribute type for kind '${kind}' and itemSize '${itemSize}'`)
}
export type AttributeDefs = {
[k: string]: { kind: ArrayKind, itemSize: AttributeItemSize, divisor: number }
[k: string]: { kind: AttributeKind, itemSize: AttributeItemSize, divisor: number }
}
export type AttributeValues = { [k: string]: ValueCell<ArrayType> }
export type AttributeBuffers = [string, AttributeBuffer][]
......
......@@ -6,13 +6,14 @@
import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code'
import { WebGLContext } from './context';
import { getUniformSetters, UniformsList } from './uniform';
import { AttributeBuffers } from './buffer';
import { getUniformSetters, UniformsList, getUniformType } from './uniform';
import { AttributeBuffers, getAttribType } from './buffer';
import { TextureId, Textures } from './texture';
import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache';
import { idFactory } from 'mol-util/id-factory';
import { RenderableSchema } from '../renderable/schema';
import { hashFnv32a, hashString } from 'mol-data/util';
import { isProductionMode } from 'mol-util/debug';
const getNextProgramId = idFactory()
......@@ -47,6 +48,63 @@ function getLocations(ctx: WebGLContext, program: WebGLProgram, schema: Renderab
return locations
}
function checkActiveAttributes(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
const { gl } = ctx
const attribCount = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (let i = 0; i < attribCount; ++i) {
const info = gl.getActiveAttrib(program, i);
if (info) {
const { name, type } = info
const spec = schema[name]
if (spec === undefined) {
throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`)
}
if (spec.type !== 'attribute') {
throw new Error(`'${name}' must be of type 'attribute' but is '${spec.type}'`)
}
const attribType = getAttribType(ctx, spec.kind, spec.itemSize)
if (attribType !== type) {
throw new Error(`unexpected attribute type for ${name}`)
}
}
}
}
function checkActiveUniforms(ctx: WebGLContext, program: WebGLProgram, schema: RenderableSchema) {
const { gl } = ctx
const attribCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < attribCount; ++i) {
const info = gl.getActiveUniform(program, i);
if (info) {
const { name, type } = info
const spec = schema[name]
if (spec === undefined) {
throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`)
}
if (spec.type === 'uniform') {
const uniformType = getUniformType(gl, spec.kind)
if (uniformType !== type) {
throw new Error(`unexpected uniform type for ${name}`)
}
} else if (spec.type === 'texture') {
if (spec.kind === 'image-float32' || spec.kind === 'image-uint8') {
if (type !== gl.SAMPLER_2D) {
throw new Error(`unexpected sampler type for '${name}'`)
}
} else if (spec.kind === 'volume-float32' || spec.kind === 'volume-uint8') {
if (type !== (gl as WebGL2RenderingContext).SAMPLER_3D) {
throw new Error(`unexpected sampler type for '${name}'`)
}
} else {
// TODO
}
} else {
throw new Error(`'${name}' must be of type 'uniform' or 'texture' but is '${spec.type}'`)
}
}
}
}
export interface ProgramProps {
defineValues: DefineValues,
shaderCode: ShaderCode,
......@@ -77,6 +135,11 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program {
const locations = getLocations(ctx, program, schema)
const uniformSetters = getUniformSetters(schema)
if (!isProductionMode) {
checkActiveAttributes(ctx, program, schema)
checkActiveUniforms(ctx, program, schema)
}
let destroyed = false
return {
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { createAttributeBuffers, createElementsBuffer, ElementsBuffer, createAttributeBuffer, ArrayKind } from './buffer';
import { createAttributeBuffers, createElementsBuffer, ElementsBuffer, createAttributeBuffer, AttributeKind } from './buffer';
import { createTextures } from './texture';
import { WebGLContext } from './context';
import { ShaderCode } from '../shader-code';
......@@ -212,7 +212,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo
} else {
// console.log('attribute array to small, need to create new attribute', k, value.ref.id, value.ref.version)
buffer.destroy()
const { itemSize, divisor } = schema[k] as AttributeSpec<ArrayKind>
const { itemSize, divisor } = schema[k] as AttributeSpec<AttributeKind>
attributeBuffers[i] = [k, createAttributeBuffer(ctx, value.ref.value, itemSize, divisor)]
valueChanges.attributes = true
}
......
......@@ -25,6 +25,19 @@ export type UniformType = number | Vec2 | Vec3 | Vec4 | Mat3 | Mat4
export type UniformValues = { [k: string]: ValueCell<UniformType> }
export type UniformsList = [string, ValueCell<UniformType>][]
export function getUniformType(gl: GLRenderingContext, kind: UniformKind) {
switch (kind) {
case 'f': return gl.FLOAT
case 'i': return gl.INT
case 'v2': return gl.FLOAT_VEC2
case 'v3': return gl.FLOAT_VEC3
case 'v4': return gl.FLOAT_VEC4
case 'm3': return gl.FLOAT_MAT3
case 'm4': return gl.FLOAT_MAT4
default: console.error(`unknown uniform kind '${kind}'`)
}
}
export function setUniform(gl: GLRenderingContext, location: WebGLUniformLocation | null, kind: UniformKind, value: any) {
switch (kind) {
case 'f': gl.uniform1f(location, value); break
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment