UNPKG

molstar

Version:

A comprehensive macromolecular library.

333 lines 17.5 kB
"use strict"; /** * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createRenderItem = exports.createComputeRenderItem = exports.createGraphicsRenderItem = exports.getDrawMode = void 0; var tslib_1 = require("tslib"); var buffer_1 = require("./buffer"); var texture_1 = require("./texture"); var context_1 = require("./context"); var schema_1 = require("../renderable/schema"); var id_factory_1 = require("../../mol-util/id-factory"); var mol_util_1 = require("../../mol-util"); var framebuffer_1 = require("./framebuffer"); var debug_1 = require("../../mol-util/debug"); var array_1 = require("../../mol-util/array"); var object_1 = require("../../mol-util/object"); var uniform_1 = require("./uniform"); var getNextRenderItemId = (0, id_factory_1.idFactory)(); function getDrawMode(ctx, drawMode) { var gl = ctx.gl; switch (drawMode) { case 'points': return gl.POINTS; case 'lines': return gl.LINES; case 'line-strip': return gl.LINE_STRIP; case 'line-loop': return gl.LINE_LOOP; case 'triangles': return gl.TRIANGLES; case 'triangle-strip': return gl.TRIANGLE_STRIP; case 'triangle-fan': return gl.TRIANGLE_FAN; } } exports.getDrawMode = getDrawMode; // var GraphicsRenderVariant = { 'colorBlended': '', 'colorWboit': '', 'pickObject': '', 'pickInstance': '', 'pickGroup': '', 'depth': '', 'markingDepth': '', 'markingMask': '' }; var GraphicsRenderVariants = Object.keys(GraphicsRenderVariant); var ComputeRenderVariant = { 'compute': '' }; var ComputeRenderVariants = Object.keys(ComputeRenderVariant); function createProgramVariant(ctx, variant, defineValues, shaderCode, schema) { defineValues = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, defineValues), { dRenderVariant: mol_util_1.ValueCell.create(variant) }); if (schema.dRenderVariant === undefined) { Object.defineProperty(schema, 'dRenderVariant', { value: (0, schema_1.DefineSpec)('string') }); } return ctx.resources.program(defineValues, shaderCode, schema); } function createValueChanges() { return { attributes: false, defines: false, elements: false, textures: false, }; } function resetValueChanges(valueChanges) { valueChanges.attributes = false; valueChanges.defines = false; valueChanges.elements = false; valueChanges.textures = false; } function createGraphicsRenderItem(ctx, drawMode, shaderCode, schema, values, materialId) { return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, GraphicsRenderVariants); } exports.createGraphicsRenderItem = createGraphicsRenderItem; function createComputeRenderItem(ctx, drawMode, shaderCode, schema, values, materialId) { if (materialId === void 0) { materialId = -1; } return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, ComputeRenderVariants); } exports.createComputeRenderItem = createComputeRenderItem; /** * Creates a render item * * - assumes that `values.drawCount` and `values.instanceCount` exist */ function createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, renderVariants) { var id = getNextRenderItemId(); var stats = ctx.stats, state = ctx.state, resources = ctx.resources; var _a = ctx.extensions, instancedArrays = _a.instancedArrays, vertexArrayObject = _a.vertexArrayObject; // emulate gl_VertexID when needed // if (!ctx.isWebGL2 && values.uVertexCount) { // not using gl_VertexID in WebGL2 but aVertex to ensure there is an active attribute with divisor 0 // since FF 85 this is not needed anymore but lets keep it for backwards compatibility // https://bugzilla.mozilla.org/show_bug.cgi?id=1679693 // see also note in src/mol-gl/shader/chunks/common-vert-params.glsl.ts if (values.uVertexCount) { var vertexCount = values.uVertexCount.ref.value; values.aVertex = mol_util_1.ValueCell.create((0, array_1.fillSerial)(new Float32Array(vertexCount))); schema.aVertex = (0, schema_1.AttributeSpec)('float32', 1, 0); } var _b = (0, schema_1.splitValues)(schema, values), attributeValues = _b.attributeValues, defineValues = _b.defineValues, textureValues = _b.textureValues, uniformValues = _b.uniformValues, materialUniformValues = _b.materialUniformValues, bufferedUniformValues = _b.bufferedUniformValues; var uniformValueEntries = Object.entries(uniformValues); var materialUniformValueEntries = Object.entries(materialUniformValues); var backBufferUniformValueEntries = Object.entries(bufferedUniformValues); var frontBufferUniformValueEntries = Object.entries((0, uniform_1.cloneUniformValues)(bufferedUniformValues)); var defineValueEntries = Object.entries(defineValues); var versions = (0, schema_1.getValueVersions)(values); var glDrawMode = getDrawMode(ctx, drawMode); var programs = {}; for (var _i = 0, renderVariants_1 = renderVariants; _i < renderVariants_1.length; _i++) { var k = renderVariants_1[_i]; programs[k] = createProgramVariant(ctx, k, defineValues, shaderCode, schema); } var textures = (0, texture_1.createTextures)(ctx, schema, textureValues); var attributeBuffers = (0, buffer_1.createAttributeBuffers)(ctx, schema, attributeValues); var elementsBuffer; var elements = values.elements; if (elements && elements.ref.value) { elementsBuffer = resources.elements(elements.ref.value); } var vertexArrays = {}; for (var _c = 0, renderVariants_2 = renderVariants; _c < renderVariants_2.length; _c++) { var k = renderVariants_2[_c]; vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null; } var drawCount = values.drawCount.ref.value; var instanceCount = values.instanceCount.ref.value; stats.drawCount += drawCount; stats.instanceCount += instanceCount; stats.instancedDrawCount += instanceCount * drawCount; var valueChanges = createValueChanges(); var destroyed = false; var currentProgramId = -1; return { id: id, materialId: materialId, getProgram: function (variant) { return programs[variant]; }, render: function (variant, sharedTexturesList) { if (drawCount === 0 || instanceCount === 0 || ctx.isContextLost) return; var program = programs[variant]; if (program.id === currentProgramId && state.currentRenderItemId === id) { program.setUniforms(uniformValueEntries); if (sharedTexturesList && sharedTexturesList.length > 0) { program.bindTextures(sharedTexturesList, 0); program.bindTextures(textures, sharedTexturesList.length); } else { program.bindTextures(textures, 0); } } else { var vertexArray = vertexArrays[variant]; if (program.id !== state.currentProgramId || program.id !== currentProgramId || materialId === -1 || materialId !== state.currentMaterialId) { // console.log('program.id changed or materialId changed/-1', materialId) if (program.id !== state.currentProgramId) program.use(); program.setUniforms(materialUniformValueEntries); state.currentMaterialId = materialId; currentProgramId = program.id; } program.setUniforms(uniformValueEntries); program.setUniforms(frontBufferUniformValueEntries); if (sharedTexturesList && sharedTexturesList.length > 0) { program.bindTextures(sharedTexturesList, 0); program.bindTextures(textures, sharedTexturesList.length); } else { program.bindTextures(textures, 0); } if (vertexArray) { vertexArray.bind(); // need to bind elements buffer explicitly since it is not always recorded in the VAO if (elementsBuffer) elementsBuffer.bind(); } else { if (elementsBuffer) elementsBuffer.bind(); program.bindAttributes(attributeBuffers); } state.currentRenderItemId = id; } if (debug_1.isDebugMode) { try { (0, framebuffer_1.checkFramebufferStatus)(ctx.gl); } catch (e) { throw new Error("Framebuffer error rendering item id " + id + ": '" + e + "'"); } } if (elementsBuffer) { instancedArrays.drawElementsInstanced(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount); } else { instancedArrays.drawArraysInstanced(glDrawMode, 0, drawCount, instanceCount); } if (debug_1.isDebugMode) { try { (0, context_1.checkError)(ctx.gl); } catch (e) { throw new Error("Draw error rendering item id " + id + ": '" + e + "'"); } } }, update: function () { resetValueChanges(valueChanges); if (values.aVertex) { var vertexCount = values.uVertexCount.ref.value; if (values.aVertex.ref.value.length < vertexCount) { mol_util_1.ValueCell.update(values.aVertex, (0, array_1.fillSerial)(new Float32Array(vertexCount))); } } for (var i = 0, il = defineValueEntries.length; i < il; ++i) { var _a = defineValueEntries[i], k = _a[0], value = _a[1]; if (value.ref.version !== versions[k]) { // console.log('define version changed', k); valueChanges.defines = true; versions[k] = value.ref.version; } } if (valueChanges.defines) { // console.log('some defines changed, need to rebuild programs'); for (var _i = 0, renderVariants_3 = renderVariants; _i < renderVariants_3.length; _i++) { var k = renderVariants_3[_i]; programs[k].destroy(); programs[k] = createProgramVariant(ctx, k, defineValues, shaderCode, schema); } } if (values.drawCount.ref.version !== versions.drawCount) { // console.log('drawCount version changed'); stats.drawCount += values.drawCount.ref.value - drawCount; stats.instancedDrawCount += instanceCount * values.drawCount.ref.value - instanceCount * drawCount; drawCount = values.drawCount.ref.value; versions.drawCount = values.drawCount.ref.version; } if (values.instanceCount.ref.version !== versions.instanceCount) { // console.log('instanceCount version changed'); stats.instanceCount += values.instanceCount.ref.value - instanceCount; stats.instancedDrawCount += values.instanceCount.ref.value * drawCount - instanceCount * drawCount; instanceCount = values.instanceCount.ref.value; versions.instanceCount = values.instanceCount.ref.version; } for (var i = 0, il = attributeBuffers.length; i < il; ++i) { var _b = attributeBuffers[i], k = _b[0], buffer = _b[1]; var value = attributeValues[k]; if (value.ref.version !== versions[k]) { if (buffer.length >= value.ref.value.length) { // console.log('attribute array large enough to update', buffer.id, k, value.ref.id, value.ref.version); buffer.updateSubData(value.ref.value, 0, buffer.length); } else { // console.log('attribute array too small, need to create new attribute', buffer.id, k, value.ref.id, value.ref.version); buffer.destroy(); var _c = schema[k], itemSize = _c.itemSize, divisor = _c.divisor; attributeBuffers[i][1] = resources.attribute(value.ref.value, itemSize, divisor); valueChanges.attributes = true; } versions[k] = value.ref.version; } } if (elementsBuffer && values.elements.ref.version !== versions.elements) { if (elementsBuffer.length >= values.elements.ref.value.length) { // console.log('elements array large enough to update', values.elements.ref.id, values.elements.ref.version); elementsBuffer.updateSubData(values.elements.ref.value, 0, elementsBuffer.length); } else { // console.log('elements array to small, need to create new elements', values.elements.ref.id, values.elements.ref.version); elementsBuffer.destroy(); elementsBuffer = resources.elements(values.elements.ref.value); valueChanges.elements = true; } versions.elements = values.elements.ref.version; } if (valueChanges.attributes || valueChanges.defines || valueChanges.elements) { // console.log('program/defines or buffers changed, update vaos'); for (var _d = 0, renderVariants_4 = renderVariants; _d < renderVariants_4.length; _d++) { var k = renderVariants_4[_d]; var vertexArray = vertexArrays[k]; if (vertexArray) vertexArray.destroy(); vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null; } } for (var i = 0, il = textures.length; i < il; ++i) { var _e = textures[i], k = _e[0], texture = _e[1]; var value = textureValues[k]; if (value.ref.version !== versions[k]) { // update of textures with kind 'texture' is done externally if (schema[k].kind !== 'texture') { // console.log('texture version changed, uploading image', k); texture.load(value.ref.value); valueChanges.textures = true; } else { textures[i][1] = value.ref.value; } versions[k] = value.ref.version; } } for (var i = 0, il = backBufferUniformValueEntries.length; i < il; ++i) { var _f = backBufferUniformValueEntries[i], k = _f[0], uniform = _f[1]; if (uniform.ref.version !== versions[k]) { // console.log('back-buffer uniform version changed, updating front-buffer', k); mol_util_1.ValueCell.update(frontBufferUniformValueEntries[i][1], (0, object_1.deepClone)(uniform.ref.value)); versions[k] = uniform.ref.version; } } return valueChanges; }, destroy: function () { if (!destroyed) { for (var _i = 0, renderVariants_5 = renderVariants; _i < renderVariants_5.length; _i++) { var k = renderVariants_5[_i]; programs[k].destroy(); var vertexArray = vertexArrays[k]; if (vertexArray) vertexArray.destroy(); } textures.forEach(function (_a) { var k = _a[0], texture = _a[1]; // lifetime of textures with kind 'texture' is defined externally if (schema[k].kind !== 'texture') { texture.destroy(); } }); attributeBuffers.forEach(function (_a) { var _ = _a[0], buffer = _a[1]; return buffer.destroy(); }); if (elementsBuffer) elementsBuffer.destroy(); stats.drawCount -= drawCount; stats.instanceCount -= instanceCount; stats.instancedDrawCount -= instanceCount * drawCount; destroyed = true; } } }; } exports.createRenderItem = createRenderItem; //# sourceMappingURL=render-item.js.map