Browse Source

removed MRT support for GPU gaussian density (slow)

Alexander Rose 6 years ago
parent
commit
5996ae6b16

+ 0 - 2
src/mol-gl/renderable/gaussian-density.ts

@@ -25,8 +25,6 @@ export const GaussianDensitySchema = {
     uBboxSize: UniformSpec('v3'),
     uGridDim: UniformSpec('v3'),
     uAlpha: UniformSpec('f'),
-
-    dDrawBuffers: DefineSpec('number'),
 }
 export type GaussianDensitySchema = typeof GaussianDensitySchema
 export type GaussianDensityValues = Values<GaussianDensitySchema>

+ 7 - 32
src/mol-gl/shader/gaussian-density.frag

@@ -7,8 +7,8 @@
 
 precision highp float;
 
-varying vec3 position;
-varying float radius;
+varying vec3 vPosition;
+varying float vRadius;
 
 uniform vec3 uBboxSize;
 uniform vec3 uBboxMin;
@@ -19,40 +19,15 @@ uniform float uCurrentX;
 uniform float uCurrentY;
 uniform float uAlpha;
 
-#if dDrawBuffers >= 4
-    layout(location = 1) out vec4 out1;
-    layout(location = 2) out vec4 out2;
-    layout(location = 3) out vec4 out3;
-#endif
-#if dDrawBuffers >= 8
-    layout(location = 4) out vec4 out4;
-    layout(location = 5) out vec4 out5;
-    layout(location = 6) out vec4 out6;
-    layout(location = 7) out vec4 out7;
-#endif
-
-float calcDensity(float x, float y, float z, float radiusSq) {
+vec4 calc(float x, float y, float z, float radiusSq) {
     vec3 fragPos = vec3(x, y, z) / uGridDim;
-    float dist = distance(fragPos * uBboxSize, position * uBboxSize);
+    float dist = distance(fragPos * uBboxSize, vPosition * uBboxSize);
     float density = exp(-uAlpha * ((dist * dist) / radiusSq));
-    return density;
+    return vec4(density);
 }
 
-const vec3 color = vec3(1.0, 1.0, 1.0);
-
 void main() {
-    float radiusSq = radius * radius;
+    float radiusSq = vRadius * vRadius;
     vec2 v = gl_FragCoord.xy - vec2(uCurrentX, uCurrentY) - 0.5;
-    gl_FragColor = vec4(color, calcDensity(v.x, v.y, uCurrentSlice, radiusSq));
-    #if dDrawBuffers >= 4
-        out1 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 1.0, radiusSq));
-        out2 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 2.0, radiusSq));
-        out3 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 3.0, radiusSq));
-    #endif
-    #if dDrawBuffers >= 8
-        out4 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 4.0, radiusSq));
-        out5 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 5.0, radiusSq));
-        out6 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 6.0, radiusSq));
-        out7 = vec4(color, calcDensity(v.x, v.y, uCurrentSlice + 7.0, radiusSq));
-    #endif
+    gl_FragColor = calc(v.x, v.y, uCurrentSlice, radiusSq);
 }

+ 6 - 6
src/mol-gl/shader/gaussian-density.vert

@@ -10,8 +10,8 @@ precision highp float;
 attribute vec3 aPosition;
 attribute float aRadius;
 
-varying vec3 position;
-varying float radius;
+varying vec3 vPosition;
+varying float vRadius;
 
 uniform vec3 uBboxSize;
 uniform vec3 uBboxMin;
@@ -20,9 +20,9 @@ uniform vec3 uGridDim;
 uniform float uCurrentSlice;
 
 void main() {
-    radius = aRadius;
+    vRadius = aRadius;
     float scale = max(uBboxSize.z, max(uBboxSize.x, uBboxSize.y));
-    gl_PointSize = (radius / scale) * max(uGridDim.x, uGridDim.y) * 6.0;
-    position = (aPosition - uBboxMin) / uBboxSize;
-    gl_Position = vec4(position * 2.0 - 1.0, 1.0);
+    gl_PointSize = (vRadius / scale) * max(uGridDim.x, uGridDim.y) * 6.0;
+    vPosition = (aPosition - uBboxMin) / uBboxSize;
+    gl_Position = vec4(vPosition * 2.0 - 1.0, 1.0);
 }

+ 11 - 54
src/mol-math/geometry/gaussian-density/gpu.ts

@@ -17,7 +17,7 @@ import { RenderableState } from 'mol-gl/renderable'
 import { createRenderable, createGaussianDensityRenderObject } from 'mol-gl/render-object'
 import { Context, createContext, getGLContext } from 'mol-gl/webgl/context';
 import { createFramebuffer } from 'mol-gl/webgl/framebuffer';
-import { createTexture, Texture, TextureAttachment } from 'mol-gl/webgl/texture';
+import { createTexture, Texture } from 'mol-gl/webgl/texture';
 import { GLRenderingContext } from 'mol-gl/webgl/compat';
 
 export async function GaussianDensityGPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps): Promise<DensityData> {
@@ -36,11 +36,11 @@ export async function GaussianDensityGPU(ctx: RuntimeContext, position: Position
 }
 
 export async function GaussianDensityTexture(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, oldTexture?: Texture): Promise<DensityTextureData> {
-    console.time(`GaussianDensityTexture, ${webgl.maxDrawBuffers > 0 ? 'multi' : 'single'}`)
-    const { texture, scale, bbox, dim } = webgl.maxDrawBuffers > 0 ?
-        await GaussianDensityMultiDrawBuffer(ctx, webgl, position, box, radius, props, oldTexture) :
-        await GaussianDensitySingleDrawBuffer(ctx, webgl, position, box, radius, props, oldTexture)
-    console.timeEnd(`GaussianDensityTexture, ${webgl.maxDrawBuffers > 0 ? 'multi' : 'single'}`)
+    console.time(`GaussianDensityTexture, ${webgl.isWebGL2 ? '3d' : '2d'}`)
+    const { texture, scale, bbox, dim } = webgl.isWebGL2 ?
+        await GaussianDensityTexture3d(ctx, webgl, position, box, radius, props, oldTexture) :
+        await GaussianDensityTexture2d(ctx, webgl, position, box, radius, props, oldTexture)
+    console.timeEnd(`GaussianDensityTexture, ${webgl.isWebGL2 ? '3d' : '2d'}`)
 
     const transform = Mat4.identity()
     Mat4.fromScaling(transform, scale)
@@ -51,7 +51,7 @@ export async function GaussianDensityTexture(ctx: RuntimeContext, webgl: Context
 
 //
 
-async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, texture?: Texture) {
+async function GaussianDensityTexture2d(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, texture?: Texture) {
     const { smoothness } = props
 
     const { drawCount, positions, radii, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props)
@@ -119,14 +119,13 @@ async function GaussianDensitySingleDrawBuffer(ctx: RuntimeContext, webgl: Conte
     return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim }
 }
 
-async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, texture?: Texture) {
+async function GaussianDensityTexture3d(ctx: RuntimeContext, webgl: Context, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, texture?: Texture) {
     const { smoothness } = props
 
     const { drawCount, positions, radii, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props)
     const [ dx, dy, dz ] = dim
     const renderObject = getGaussianDensityRenderObject(webgl, drawCount, positions, radii, expandedBox, dim, smoothness)
     const renderable = createRenderable(webgl, renderObject)
-    const drawBuffers = Math.min(8, webgl.maxDrawBuffers)
 
     //
 
@@ -136,7 +135,6 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex
     const framebuffer = createFramebuffer(webgl)
     framebuffer.bind()
 
-    setDrawBuffers(gl, drawBuffers)
     gl.viewport(0, 0, dx, dy)
     setRenderingDefaults(gl)
 
@@ -145,36 +143,14 @@ async function GaussianDensityMultiDrawBuffer(ctx: RuntimeContext, webgl: Contex
     }
     texture.define(dx, dy, dz)
 
-    // z-slices to be render with multi render targets
-    const dzMulti = Math.floor(dz / drawBuffers) * drawBuffers
-
-    // render multi target
-    const programMulti = renderable.getProgram('draw')
-    programMulti.use()
-    for (let i = 0; i < dzMulti; i += drawBuffers) {
-        ValueCell.update(uCurrentSlice, i)
-        for (let k = 0; k < drawBuffers; ++k) {
-            texture.attachFramebuffer(framebuffer, k as TextureAttachment, i + k)
-        }
-        renderable.render('draw');
-    }
-
-    // render single target
-    ValueCell.updateIfChanged(renderable.values.dDrawBuffers, 1)
-    renderable.update()
-    const programSingle = renderable.getProgram('draw')
-    programSingle.use()
-    for (let i = dzMulti; i < dz; ++i) {
+    const programDensity = renderable.getProgram('draw')
+    programDensity.use()
+    for (let i = 0; i < dz; ++i) {
         ValueCell.update(uCurrentSlice, i)
         texture.attachFramebuffer(framebuffer, 0, i)
         renderable.render('draw')
     }
 
-    // must detach framebuffer attachments before reading is possible
-    for (let k = 0; k < drawBuffers; ++k) {
-        texture.detachFramebuffer(framebuffer, k as TextureAttachment)
-    }
-
     framebuffer.destroy() // clean up
 
     await ctx.update({ message: 'gpu gaussian density calculation' });
@@ -256,8 +232,6 @@ function getGaussianDensityRenderObject(webgl: Context, drawCount: number, posit
         uBboxSize: ValueCell.create(extent),
         uGridDim: ValueCell.create(dimensions),
         uAlpha: ValueCell.create(smoothness),
-
-        dDrawBuffers: ValueCell.create(Math.min(8, webgl.maxDrawBuffers)),
     }
     const state: RenderableState = {
         visible: true,
@@ -279,23 +253,6 @@ function setRenderingDefaults(gl: GLRenderingContext) {
     gl.enable(gl.BLEND)
 }
 
-function setDrawBuffers(gl: WebGL2RenderingContext, drawBuffers: number) {
-    if (drawBuffers === 1) {
-        gl.drawBuffers([
-            gl.COLOR_ATTACHMENT0,
-        ]);
-    } else if (drawBuffers === 4) {
-        gl.drawBuffers([
-            gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3,
-        ]);
-    } else if (drawBuffers === 8) {
-        gl.drawBuffers([
-            gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3,
-            gl.COLOR_ATTACHMENT4, gl.COLOR_ATTACHMENT5, gl.COLOR_ATTACHMENT6, gl.COLOR_ATTACHMENT7,
-        ]);
-    }
-}
-
 function fieldFromTexture2d(ctx: Context, texture: Texture, dim: Vec3) {
     console.time('fieldFromTexture2d')
     const { gl } = ctx