Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<url>https://ulrik.is/writing</url>
<properties><id>skalarproduktraum</id></properties>
</contributor>
<contributor>
<name>Eugene Katrukha</name>
<url>https://imagej.net/people/ekatrukha</url>
<properties><id>ekatrukha</id></properties>
</contributor>
</contributors>

<mailingLists>
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/bvv/core/blocks/ByteUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class ByteUtils
private static final long BUFFER_ADDRESS_OFFSET;
private static final long BYTE_ARRAY_OFFSET;
private static final long SHORT_ARRAY_OFFSET;
private static final long FLOAT_ARRAY_OFFSET;

static
{
Expand All @@ -66,6 +67,7 @@ public Unsafe run() throws Exception

BYTE_ARRAY_OFFSET = UNSAFE.arrayBaseOffset( byte[].class );
SHORT_ARRAY_OFFSET = UNSAFE.arrayBaseOffset( short[].class );
FLOAT_ARRAY_OFFSET = UNSAFE.arrayBaseOffset( float[].class );
}
catch ( final Exception ex )
{
Expand Down Expand Up @@ -98,6 +100,17 @@ public static void copyBytes( final byte[] src, final long dst, final long sox,
{
UNSAFE.copyMemory( src, BYTE_ARRAY_OFFSET + sox, null, dst, csx );
}

public static void setFloats( final float src, final long dst, final long csx )
{
for ( int i = 0; i < csx; ++i )
UNSAFE.putFloat( dst + 4 * i, src );
}

public static void copyFloats( final float[] src, final long dst, final long sox, final long csx )
{
UNSAFE.copyMemory( src, FLOAT_ARRAY_OFFSET + 4 * sox, null, dst, 4 * csx );
}

public interface Address
{
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/bvv/core/blocks/CopySubArrayImp.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ public void copysubarray3d( final byte[] src, final int sox, final int soy, fina
copysubarray3dn( copy, sox, soy, soz, ssx, ssy, dox, doy, doz, dsx, dsy, csx, csy, csz );
}
}

public static class FloatToAddress implements CopySubArray< float[], ByteUtils.Address >
{
@Override
public void clearsubarray3d( final ByteUtils.Address dst, final int dox, final int doy, final int doz, final int dsx, final int dsy, final int csx, final int csy, final int csz )
{
final ArrayFill fill = ( o, l ) -> ByteUtils.setFloats( 0, dst.getAddress() + 4 * o, l );
fillsubarray3dn( fill, dox, doy, doz, dsx, dsy, csx, csy, csz );
}

@Override
public void copysubarray3d( final float[] src, final int sox, final int soy, final int soz, final int ssx, final int ssy, final ByteUtils.Address dst, final int dox, final int doy, final int doz, final int dsx, final int dsy, final int csx, final int csy, final int csz )
{
final ArrayCopy copy = ( so, o, l ) -> ByteUtils.copyFloats( src, dst.getAddress() + 4 * o, so, l );
copysubarray3dn( copy, sox, soy, soz, ssx, ssy, dox, doy, doz, dsx, dsy, csx, csy, csz );
}
}

static void copysubarray3dn(
ArrayCopy copysubarray1dn,
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/bvv/core/blocks/TileAccess.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

import static net.imglib2.type.PrimitiveType.BYTE;
import static net.imglib2.type.PrimitiveType.SHORT;
import static net.imglib2.type.PrimitiveType.FLOAT;

/**
* Copy blocks from a {@link ResolutionLevel3D} source to an {@link UploadBuffer}.
Expand Down Expand Up @@ -137,6 +138,16 @@ else if ( cellimg && primitive == BYTE && cacheSpec.format() == Texture.Internal
cacheSpec
);
}
else if ( cellimg && primitive == FLOAT && cacheSpec.format() == Texture.InternalFormat.R32F )
{
return new TileAccess<>(
volatil
? new GridDataAccessImp.VolatileCells<>( ( AbstractCellImg ) img )
: new GridDataAccessImp.Cells<>( ( AbstractCellImg ) img ),
new CopySubArrayImp.FloatToAddress(),
cacheSpec
);
}
}

throw new UnsupportedOperationException( "pixel and/or image type not supported (yet)." );
Expand All @@ -150,7 +161,7 @@ public static boolean isSupportedType( final Object type )
{
final PrimitiveType primitive = ( ( NativeType ) type ).getNativeTypeFactory().getPrimitiveType();
final Fraction epp = ( ( NativeType ) type ).getEntitiesPerPixel();
return ( primitive == SHORT || primitive == BYTE ) && epp.getNumerator() == epp.getDenominator();
return ( primitive == SHORT || primitive == BYTE || primitive == FLOAT ) && epp.getNumerator() == epp.getDenominator();
}

return false;
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/bvv/core/cache/TextureCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ private void initializeBlockedTiles( ArrayList< TileFillTask > tileFillTasks )
return true;
} , () -> true ), oobTile ) );
}
if(spec.format() == InternalFormat.R32F)
{
tileFillTasks.add( new TileFillTask( new DefaultFillTask( oobDummyKey, buf -> {
ByteUtils.setFloats( 0, buf.getAddress(), elementsPerTile );
return true;
} , () -> true ), oobTile ) );
}
}

private List< Tile > assignFillTiles( final int size, final int currentTimestamp )
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/bvv/core/render/DefaultSimpleStackManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.HashMap;
Expand All @@ -41,6 +42,7 @@
import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.numeric.integer.UnsignedByteType;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.util.Intervals;
import net.imglib2.view.Views;

Expand All @@ -54,13 +56,15 @@ public class DefaultSimpleStackManager implements SimpleStackManager
{
private final HashMap< SimpleStack3D< ? >, VolumeTextureU16 > texturesU16;
private final HashMap< SimpleStack3D< ? >, VolumeTextureU8 > texturesU8;
private final HashMap< SimpleStack3D< ? >, VolumeTextureU32 > texturesU32;
private final HashMap< SimpleStack3D< ? >, VolumeTextureRGBA8 > texturesRGBA8;

private final HashMap< Texture3D, Integer > timestamps;
private int currentTimestamp;

public DefaultSimpleStackManager()
{
texturesU32 = new HashMap<>();
texturesU16 = new HashMap<>();
texturesU8 = new HashMap<>();
texturesRGBA8 = new HashMap<>();
Expand Down Expand Up @@ -90,6 +94,12 @@ else if ( type instanceof UnsignedByteType )
sourceMax = new Vector3f( image.max( 0 ), image.max( 1 ), image.max( 2 ) );
sourceMin = new Vector3f( image.min( 0 ), image.min( 1 ), image.min( 2 ) );
}
else if ( type instanceof FloatType )
{
texture = texturesU32.computeIfAbsent( stack, s -> uploadToTextureU32( context, ( RandomAccessibleInterval< FloatType > ) image ) );
sourceMax = new Vector3f( image.max( 0 ), image.max( 1 ), image.max( 2 ) );
sourceMin = new Vector3f( image.min( 0 ), image.min( 1 ), image.min( 2 ) );
}
else if ( type instanceof ARGBType )
{
texture = texturesRGBA8.computeIfAbsent( stack, s -> uploadToTextureRGBA8( context, ( RandomAccessibleInterval< ARGBType > ) image ) );
Expand Down Expand Up @@ -162,6 +172,30 @@ private static void copyToBufferU16( final RandomAccessibleInterval< UnsignedSho
while ( cursor.hasNext() )
sdata.put( i++, cursor.next().getShort() );
}

private static VolumeTextureU32 uploadToTextureU32( final GpuContext context, final RandomAccessibleInterval< FloatType > rai )
{
final VolumeTextureU32 texture = new VolumeTextureU32();
texture.init( Intervals.dimensionsAsIntArray( rai ) );

final int numBytes = ( int ) ( 4 * Intervals.numElements( rai ) );
final ByteBuffer data = ByteBuffer.allocateDirect( numBytes ); // allocate a bit more than needed...
data.order( ByteOrder.nativeOrder() );
copyToBufferU32( rai, data );
texture.upload( context, data );
return texture;
}

private static void copyToBufferU32( final RandomAccessibleInterval< FloatType > rai, final ByteBuffer buffer )
{
// TODO handle specific RAI types more efficiently
// TODO multithreading
final Cursor< FloatType > cursor = Views.flatIterable( rai ).cursor();
final FloatBuffer sdata = buffer.asFloatBuffer();
int i = 0;
while ( cursor.hasNext() )
sdata.put( i++, cursor.next().getRealFloat() );
}

private static VolumeTextureU8 uploadToTextureU8( final GpuContext context, final RandomAccessibleInterval< UnsignedByteType > rai )
{
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/bvv/core/render/MultiVolumeShaderMip.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public MultiVolumeShaderMip( VolumeShaderSignature signature, final boolean useD
switch ( volumeSignature.getPixelType() )
{
default:
case SFLOAT:
case USHORT:
case UBYTE:
convert = templateConvert.instantiate();
Expand Down Expand Up @@ -520,6 +521,9 @@ public ConverterSegment( final SegmentedShader prog, final Segment segment, fina
case ARGB:
rangeScale = 0xff;
break;
case SFLOAT:
rangeScale = 1.0;
break;
}
}

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/bvv/core/render/VolumeRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,20 @@
import static com.jogamp.opengl.GL.GL_UNPACK_ALIGNMENT;
import static bvv.core.backend.Texture.InternalFormat.R8;
import static bvv.core.backend.Texture.InternalFormat.R16;
import static bvv.core.backend.Texture.InternalFormat.R32F;
import static bvv.core.render.VolumeRenderer.RepaintType.DITHER;
import static bvv.core.render.VolumeRenderer.RepaintType.FULL;
import static bvv.core.render.VolumeRenderer.RepaintType.LOAD;
import static bvv.core.render.VolumeRenderer.RepaintType.NONE;
import static bvv.core.render.VolumeShaderSignature.PixelType.ARGB;
import static bvv.core.render.VolumeShaderSignature.PixelType.UBYTE;
import static bvv.core.render.VolumeShaderSignature.PixelType.USHORT;
import static bvv.core.render.VolumeShaderSignature.PixelType.SFLOAT;
import static bvv.core.multires.SourceStacks.SourceStackType.MULTIRESOLUTION;
import static bvv.core.multires.SourceStacks.SourceStackType.SIMPLE;
import static net.imglib2.type.PrimitiveType.BYTE;
import static net.imglib2.type.PrimitiveType.SHORT;
import static net.imglib2.type.PrimitiveType.FLOAT;

import bvv.core.backend.Texture.InternalFormat;
import bvv.core.cache.CacheSpec;
Expand All @@ -69,8 +72,10 @@
import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.numeric.integer.UnsignedByteType;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.type.volatiles.VolatileUnsignedByteType;
import net.imglib2.type.volatiles.VolatileUnsignedShortType;
import net.imglib2.type.volatiles.VolatileFloatType;

import org.joml.Matrix4f;

Expand Down Expand Up @@ -145,6 +150,8 @@ void request( final RepaintType type )
private final TextureCacheAndPboChain cacheR8;

private final TextureCacheAndPboChain cacheR16;

private final TextureCacheAndPboChain cacheR32F;

private final ForkJoinPool forkJoinPool;

Expand Down Expand Up @@ -208,6 +215,7 @@ public VolumeRenderer(
// used for the first time.
cacheR8 = new TextureCacheAndPboChain( R8, cacheBlockSize, maxCacheSizeInMB );
cacheR16 = new TextureCacheAndPboChain( R16, cacheBlockSize, maxCacheSizeInMB );
cacheR32F = new TextureCacheAndPboChain( R32F, cacheBlockSize, maxCacheSizeInMB );

final int parallelism = Math.max( 1, Runtime.getRuntime().availableProcessors() / 2 );
forkJoinPool = new ForkJoinPool( parallelism );
Expand Down Expand Up @@ -306,6 +314,8 @@ else if ( type == LOAD )
volumeSignatures.add( new VolumeSignature( MULTIRESOLUTION, USHORT ) );
else if ( ( pixelType instanceof UnsignedByteType ) || ( pixelType instanceof VolatileUnsignedByteType ) )
volumeSignatures.add( new VolumeSignature( MULTIRESOLUTION, UBYTE ) );
else if ( ( pixelType instanceof FloatType ) || ( pixelType instanceof VolatileFloatType ) )
volumeSignatures.add( new VolumeSignature( MULTIRESOLUTION, SFLOAT ) );
else
throw new IllegalArgumentException( "Multiresolution stack with pixel type " + pixelType.getClass().getName() + " unsupported in BigVolumeViewer." );
}
Expand All @@ -316,6 +326,8 @@ else if ( stack instanceof SimpleStack3D )
volumeSignatures.add( new VolumeSignature( SIMPLE, USHORT ) );
else if ( pixelType instanceof UnsignedByteType )
volumeSignatures.add( new VolumeSignature( SIMPLE, UBYTE ) );
else if ( pixelType instanceof FloatType )
volumeSignatures.add( new VolumeSignature( SIMPLE, SFLOAT ) );
else if ( pixelType instanceof ARGBType )
volumeSignatures.add( new VolumeSignature( SIMPLE, ARGB ) );
else
Expand Down Expand Up @@ -523,6 +535,9 @@ private void updateBlocks(

final List< MultiResolutionStack3D< ? > > multiResStacksR16 = new ArrayList<>();
final List< VolumeBlocks > volumesR16 = new ArrayList<>();

final List< MultiResolutionStack3D< ? > > multiResStacksR32 = new ArrayList<>();
final List< VolumeBlocks > volumesR32 = new ArrayList<>();

for ( int i = 0; i < multiResStacks.size(); i++ )
{
Expand All @@ -539,6 +554,11 @@ else if ( primitiveType == SHORT )
multiResStacksR16.add( stack );
volumesR16.add( volume );
}
else if ( primitiveType == FLOAT )
{
multiResStacksR32.add( stack );
volumesR32.add( volume );
}
else
{
throw new IllegalArgumentException();
Expand All @@ -548,6 +568,8 @@ else if ( primitiveType == SHORT )
boolean complete = true;
complete &= updateBlocks( context, multiResStacksR8, volumesR8, cacheR8, forkJoinPool, renderWidth, pv );
complete &= updateBlocks( context, multiResStacksR16, volumesR16, cacheR16, forkJoinPool, renderWidth, pv );
complete &= updateBlocks( context, multiResStacksR32, volumesR32, cacheR32F, forkJoinPool, renderWidth, pv );

if ( !complete )
nextRequestedRepaint.request( LOAD );
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/bvv/core/render/VolumeShaderSignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public final class VolumeShaderSignature
{
public enum PixelType
{
SFLOAT,
USHORT,
UBYTE,
ARGB
Expand Down
Loading