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

gpu gaussian density tweaks

parent 006f6572
No related branches found
No related tags found
No related merge requests found
...@@ -43,7 +43,7 @@ export async function GaussianDensity(ctx: RuntimeContext, position: PositionDat ...@@ -43,7 +43,7 @@ export async function GaussianDensity(ctx: RuntimeContext, position: PositionDat
if (props.useGpu) { if (props.useGpu) {
if (!GaussianDensityGPU) throw 'GPU computation not supported on this platform'; if (!GaussianDensityGPU) throw 'GPU computation not supported on this platform';
if (!webgl) throw 'No WebGL context provided'; if (!webgl) throw 'No WebGL context provided';
return await GaussianDensityGPU(ctx, position, box, radius, props, webgl) return GaussianDensityGPU(position, box, radius, props, webgl)
} else { } else {
return await GaussianDensityCPU(ctx, position, box, radius, props) return await GaussianDensityCPU(ctx, position, box, radius, props)
} }
...@@ -65,7 +65,7 @@ function _computeGaussianDensityTexture(type: '2d' | '3d', position: PositionDat ...@@ -65,7 +65,7 @@ function _computeGaussianDensityTexture(type: '2d' | '3d', position: PositionDat
if (!GaussianDensityTexture) throw 'GPU computation not supported on this platform'; if (!GaussianDensityTexture) throw 'GPU computation not supported on this platform';
return Task.create('Gaussian Density', async ctx => { return Task.create('Gaussian Density', async ctx => {
return type === '2d' ? return type === '2d' ?
await GaussianDensityTexture2d(ctx, webgl, position, box, radius, props, texture) : GaussianDensityTexture2d(webgl, position, box, radius, props, texture) :
await GaussianDensityTexture3d(ctx, webgl, position, box, radius, props, texture); GaussianDensityTexture3d(webgl, position, box, radius, props, texture);
}); });
} }
\ No newline at end of file
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* @author Michael Krone <michael.krone@uni-tuebingen.de> * @author Michael Krone <michael.krone@uni-tuebingen.de>
*/ */
import { RuntimeContext } from 'mol-task'
import { PositionData, DensityData, DensityTextureData } from '../common' import { PositionData, DensityData, DensityTextureData } from '../common'
import { Box3D } from '../../geometry' import { Box3D } from '../../geometry'
import { GaussianDensityGPUProps } from '../gaussian-density' import { GaussianDensityGPUProps } from '../gaussian-density'
...@@ -53,30 +52,30 @@ export const GaussianDensityShaderCode = ShaderCode( ...@@ -53,30 +52,30 @@ export const GaussianDensityShaderCode = ShaderCode(
/** name for shared framebuffer used for gpu gaussian surface operations */ /** name for shared framebuffer used for gpu gaussian surface operations */
const FramebufferName = 'gaussian-density' const FramebufferName = 'gaussian-density'
export async function GaussianDensityGPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext): Promise<DensityData> { export function GaussianDensityGPU(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext): DensityData {
// always use texture2d when the gaussian density needs to be downloaded from the GPU, // always use texture2d when the gaussian density needs to be downloaded from the GPU,
// it's faster than texture3d // it's faster than texture3d
// console.time('GaussianDensityTexture2d') // console.time('GaussianDensityTexture2d')
const { scale, bbox, texture, dim } = await calcGaussianDensityTexture2d(ctx, webgl, position, box, radius, props) const { scale, bbox, texture, dim } = calcGaussianDensityTexture2d(webgl, position, box, radius, props)
// webgl.waitForGpuCommandsCompleteSync() // webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('GaussianDensityTexture2d') // console.timeEnd('GaussianDensityTexture2d')
const { field, idField } = await fieldFromTexture2d(webgl, texture, dim) const { field, idField } = fieldFromTexture2d(webgl, texture, dim)
return { field, idField, transform: getTransform(scale, bbox) } return { field, idField, transform: getTransform(scale, bbox) }
} }
export async function GaussianDensityTexture(ctx: RuntimeContext, webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): Promise<DensityTextureData> { export function GaussianDensityTexture(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData {
return webgl.isWebGL2 ? return webgl.isWebGL2 ?
await GaussianDensityTexture3d(ctx, webgl, position, box, radius, props, oldTexture) : GaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture) :
await GaussianDensityTexture2d(ctx, webgl, position, box, radius, props, oldTexture) GaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture)
} }
export async function GaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): Promise<DensityTextureData> { export function GaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData {
return finalizeGaussianDensityTexture(await calcGaussianDensityTexture2d(ctx, webgl, position, box, radius, props, oldTexture)) return finalizeGaussianDensityTexture(calcGaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture))
} }
export async function GaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): Promise<DensityTextureData> { export function GaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData {
return finalizeGaussianDensityTexture(await calcGaussianDensityTexture3d(ctx, webgl, position, box, radius, props, oldTexture)) return finalizeGaussianDensityTexture(calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture))
} }
function finalizeGaussianDensityTexture({ texture, scale, bbox, dim }: GaussianDensityTextureData): DensityTextureData { function finalizeGaussianDensityTexture({ texture, scale, bbox, dim }: GaussianDensityTextureData): DensityTextureData {
...@@ -94,10 +93,10 @@ function getTransform(scale: Vec3, bbox: Box3D) { ...@@ -94,10 +93,10 @@ function getTransform(scale: Vec3, bbox: Box3D) {
type GaussianDensityTextureData = { texture: Texture, scale: Vec3, bbox: Box3D, dim: Vec3} type GaussianDensityTextureData = { texture: Texture, scale: Vec3, bbox: Box3D, dim: Vec3}
async function calcGaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): Promise<GaussianDensityTextureData> { function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData {
const { smoothness } = props const { smoothness } = props
const { drawCount, positions, radii, groups, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props) const { drawCount, positions, radii, groups, delta, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props)
const [ dx, dy, dz ] = dim const [ dx, dy, dz ] = dim
const { texDimX, texDimY, texCols } = getTexture2dSize(dim) const { texDimX, texDimY, texCols } = getTexture2dSize(dim)
...@@ -148,15 +147,13 @@ async function calcGaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLCon ...@@ -148,15 +147,13 @@ async function calcGaussianDensityTexture2d(ctx: RuntimeContext, webgl: WebGLCon
setupGroupIdRendering(webgl, renderable) setupGroupIdRendering(webgl, renderable)
render(texture) render(texture)
if (ctx.shouldUpdate) await ctx.update({ message: 'gpu gaussian density calculation' })
return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim } return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim }
} }
async function calcGaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): Promise<GaussianDensityTextureData> { function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData {
const { smoothness } = props const { smoothness } = props
const { drawCount, positions, radii, groups, delta, expandedBox, dim } = await prepareGaussianDensityData(ctx, position, box, radius, props) const { drawCount, positions, radii, groups, delta, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props)
const [ dx, dy, dz ] = dim const [ dx, dy, dz ] = dim
const minDistanceTexture = createTexture(webgl, 'volume-float32', 'rgba', 'float', 'nearest') const minDistanceTexture = createTexture(webgl, 'volume-float32', 'rgba', 'float', 'nearest')
minDistanceTexture.define(dx, dy, dz) minDistanceTexture.define(dx, dy, dz)
...@@ -193,14 +190,12 @@ async function calcGaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLCon ...@@ -193,14 +190,12 @@ async function calcGaussianDensityTexture3d(ctx: RuntimeContext, webgl: WebGLCon
setupGroupIdRendering(webgl, renderable) setupGroupIdRendering(webgl, renderable)
render(texture) render(texture)
if (ctx.shouldUpdate) await ctx.update({ message: 'gpu gaussian density calculation' });
return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim } return { texture, scale: Vec3.inverse(Vec3.zero(), delta), bbox: expandedBox, dim }
} }
// //
async function prepareGaussianDensityData(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps) { function prepareGaussianDensityData(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps) {
const { resolution, radiusOffset } = props const { resolution, radiusOffset } = props
const { indices, x, y, z } = position const { indices, x, y, z } = position
...@@ -222,10 +217,6 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio ...@@ -222,10 +217,6 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio
if (maxRadius < r) maxRadius = r if (maxRadius < r) maxRadius = r
radii[i] = r radii[i] = r
groups[i] = i groups[i] = i
if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'preparing density data', current: i, max: n })
}
} }
const pad = maxRadius * 2 + resolution const pad = maxRadius * 2 + resolution
...@@ -237,9 +228,6 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio ...@@ -237,9 +228,6 @@ async function prepareGaussianDensityData(ctx: RuntimeContext, position: Positio
Vec3.ceil(dim, dim) Vec3.ceil(dim, dim)
const delta = Vec3.div(Vec3(), dim, expandedDim) const delta = Vec3.div(Vec3(), dim, expandedDim)
// console.log({ maxRadius, resolution, pad, box, expandedBox, delta })
// console.log('grid dim gpu', dim)
return { drawCount: n, positions, radii, groups, delta, expandedBox, dim } return { drawCount: n, positions, radii, groups, delta, expandedBox, dim }
} }
...@@ -330,7 +318,7 @@ function getTexture2dSize(gridDim: Vec3) { ...@@ -330,7 +318,7 @@ function getTexture2dSize(gridDim: Vec3) {
return { texDimX, texDimY, texRows, texCols } return { texDimX, texDimY, texRows, texCols }
} }
export async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3) { export function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3) {
// console.time('fieldFromTexture2d') // console.time('fieldFromTexture2d')
const { framebufferCache } = ctx const { framebufferCache } = ctx
const [ dx, dy, dz ] = dim const [ dx, dy, dz ] = dim
...@@ -349,8 +337,6 @@ export async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, di ...@@ -349,8 +337,6 @@ export async function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, di
const framebuffer = framebufferCache.get(FramebufferName).value const framebuffer = framebufferCache.get(FramebufferName).value
framebuffer.bind() framebuffer.bind()
texture.attachFramebuffer(framebuffer, 0) texture.attachFramebuffer(framebuffer, 0)
// TODO too slow, why? Too many checks if gpu ready???
// await ctx.readPixelsAsync(0, 0, width, height, image)
ctx.readPixels(0, 0, width, height, image) ctx.readPixels(0, 0, width, height, image)
// printImageData(createImageData(image, width, height), 1/3) // printImageData(createImageData(image, width, height), 1/3)
......
...@@ -42,14 +42,14 @@ export function computeUnitGaussianDensity(unit: Unit, props: GaussianDensityPro ...@@ -42,14 +42,14 @@ export function computeUnitGaussianDensity(unit: Unit, props: GaussianDensityPro
export function computeUnitGaussianDensityTexture(unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { export function computeUnitGaussianDensityTexture(unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
const { position, radius } = getUnitConformationAndRadius(unit) const { position, radius } = getUnitConformationAndRadius(unit)
return Task.create('Gaussian Density', async ctx => { return Task.create('Gaussian Density', async ctx => {
return await GaussianDensityTexture(ctx, webgl, position, unit.lookup3d.boundary.box, radius, props, texture); return GaussianDensityTexture(webgl, position, unit.lookup3d.boundary.box, radius, props, texture);
}); });
} }
export function computeUnitGaussianDensityTexture2d(unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { export function computeUnitGaussianDensityTexture2d(unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
const { position, radius } = getUnitConformationAndRadius(unit) const { position, radius } = getUnitConformationAndRadius(unit)
return Task.create('Gaussian Density', async ctx => { return Task.create('Gaussian Density', async ctx => {
return await GaussianDensityTexture2d(ctx, webgl, position, unit.lookup3d.boundary.box, radius, props, texture); return GaussianDensityTexture2d(webgl, position, unit.lookup3d.boundary.box, radius, props, texture);
}); });
} }
...@@ -65,6 +65,6 @@ export function computeStructureGaussianDensity(structure: Structure, props: Gau ...@@ -65,6 +65,6 @@ export function computeStructureGaussianDensity(structure: Structure, props: Gau
export function computeStructureGaussianDensityTexture(structure: Structure, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { export function computeStructureGaussianDensityTexture(structure: Structure, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) {
const { position, radius } = getStructureConformationAndRadius(structure) const { position, radius } = getStructureConformationAndRadius(structure)
return Task.create('Gaussian Density', async ctx => { return Task.create('Gaussian Density', async ctx => {
return await GaussianDensityTexture(ctx, webgl, position, structure.lookup3d.boundary.box, radius, props, texture); return GaussianDensityTexture(webgl, position, structure.lookup3d.boundary.box, radius, props, texture);
}); });
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment