Updated ib-compress.

This commit is contained in:
Branimir Karadžić 2014-10-03 22:22:28 -07:00
parent c9614914fd
commit 1e03fe246d
8 changed files with 107 additions and 108 deletions

View file

@ -22,15 +22,15 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "IndexBufferCompression.h" #include "indexbuffercompression.h"
#include "WriteBitstream.h" #include "writebitstream.h"
#include "IndexCompressionConstants.h" #include "indexcompressionconstants.h"
#include <assert.h> #include <assert.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#define IBC_INLINE __forceinline #define IBC_INLINE __forceinline
#else #else
#define IBC_INLINE __attribute__((always_inline)) #define IBC_INLINE inline
#endif #endif
// Individual vertex type classifications. // Individual vertex type classifications.
@ -187,11 +187,11 @@ static IBC_INLINE VertexClassification ClassifyVertex( uint32_t vertex, const ui
} }
template <typename Ty> template <typename Ty>
void CompressIndexBuffer2( const Ty* triangles, void CompressTriangleCodes1( const Ty* triangles,
uint32_t triangleCount, uint32_t triangleCount,
uint32_t* vertexRemap, uint32_t* vertexRemap,
uint32_t vertexCount, uint32_t vertexCount,
WriteBitstream& output ) WriteBitstream& output )
{ {
Edge edgeFifo[ EDGE_FIFO_SIZE ]; Edge edgeFifo[ EDGE_FIFO_SIZE ];
uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; uint32_t vertexFifo[ VERTEX_FIFO_SIZE ];
@ -558,7 +558,7 @@ static IBC_INLINE void OutputVertex( uint32_t vertex,
// no remap, so remap to the current high watermark and output a new vertex code. // no remap, so remap to the current high watermark and output a new vertex code.
vertexRemap[ vertex ] = newVertexCount; vertexRemap[ vertex ] = newVertexCount;
output.Write( IB_NEW_VERTEX, IB_CODE_BITS ); output.Write( IB_NEW_VERTEX, IB_VERTEX_CODE_BITS );
++newVertexCount; ++newVertexCount;
@ -577,7 +577,7 @@ static IBC_INLINE void OutputVertex( uint32_t vertex,
if ( vertexFifo[ vertexCursor & VERTEX_FIFO_MASK ] == vertex ) if ( vertexFifo[ vertexCursor & VERTEX_FIFO_MASK ] == vertex )
{ {
// found a cached vertex, so write out the code for a cached vertex, as the relative index into the fifo. // found a cached vertex, so write out the code for a cached vertex, as the relative index into the fifo.
output.Write( IB_CACHED_VERTEX, IB_CODE_BITS ); output.Write( IB_CACHED_VERTEX, IB_VERTEX_CODE_BITS );
output.Write( ( verticesRead - 1 ) - vertexCursor, CACHED_VERTEX_BITS ); output.Write( ( verticesRead - 1 ) - vertexCursor, CACHED_VERTEX_BITS );
return; return;
@ -585,7 +585,7 @@ static IBC_INLINE void OutputVertex( uint32_t vertex,
} }
// no cached vertex found, so write out a free vertex // no cached vertex found, so write out a free vertex
output.Write( IB_FREE_VERTEX, IB_CODE_BITS ); output.Write( IB_FREE_VERTEX, IB_VERTEX_CODE_BITS );
// free vertices are relative to the latest new vertex. // free vertices are relative to the latest new vertex.
uint32_t vertexOutput = ( newVertexCount - 1 ) - vertexRemap[ vertex ]; uint32_t vertexOutput = ( newVertexCount - 1 ) - vertexRemap[ vertex ];
@ -602,11 +602,11 @@ static IBC_INLINE void OutputVertex( uint32_t vertex,
} }
template <typename Ty> template <typename Ty>
void CompressIndexBuffer( const Ty* triangles, void CompressIndiceCodes1( const Ty* triangles,
uint32_t triangleCount, uint32_t triangleCount,
uint32_t* vertexRemap, uint32_t* vertexRemap,
uint32_t vertexCount, uint32_t vertexCount,
WriteBitstream& output ) WriteBitstream& output )
{ {
Edge edgeFifo[ EDGE_FIFO_SIZE ]; Edge edgeFifo[ EDGE_FIFO_SIZE ];
uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; uint32_t vertexFifo[ VERTEX_FIFO_SIZE ];
@ -633,7 +633,7 @@ void CompressIndexBuffer( const Ty* triangles,
int32_t edgeCursor = edgesRead - 1; int32_t edgeCursor = edgesRead - 1;
bool foundEdge = false; bool foundEdge = false;
int32_t freeVertex; int32_t freeVertex = -1; // should not be negative 1 if found, this is not used as a signal, but for debugging.
// Probe back through the edge fifo to see if one of the triangle edges is in the FIFO // Probe back through the edge fifo to see if one of the triangle edges is in the FIFO
for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor ) for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor )
@ -664,7 +664,7 @@ void CompressIndexBuffer( const Ty* triangles,
// we found an edge so write it out, then output the vertex // we found an edge so write it out, then output the vertex
if ( foundEdge ) if ( foundEdge )
{ {
output.Write( IB_CACHED_EDGE, IB_CODE_BITS ); output.Write( IB_CACHED_EDGE, IB_VERTEX_CODE_BITS );
output.Write( ( edgesRead - 1 ) - edgeCursor, CACHED_EDGE_BITS ); output.Write( ( edgesRead - 1 ) - edgeCursor, CACHED_EDGE_BITS );
const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ]; const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ];
@ -744,38 +744,48 @@ void CompressIndexBuffer( const Ty* triangles,
} }
} }
template <typename Ty>
void CompressIndexBuffer( const Ty* triangles,
uint32_t triangleCount,
uint32_t* vertexRemap,
uint32_t vertexCount,
IndexBufferCompressionFormat format,
WriteBitstream& output )
{
output.WriteVInt( format );
switch ( format )
{
case IBCF_PER_INDICE_1:
CompressIndiceCodes1<Ty>( triangles, triangleCount, vertexRemap, vertexCount, output );
break;
case IBCF_PER_TRIANGLE_1:
CompressTriangleCodes1<Ty>( triangles, triangleCount, vertexRemap, vertexCount, output );
break;
}
}
void CompressIndexBuffer( const uint16_t* triangles, void CompressIndexBuffer( const uint16_t* triangles,
uint32_t triangleCount, uint32_t triangleCount,
uint32_t* vertexRemap, uint32_t* vertexRemap,
uint32_t vertexCount, uint32_t vertexCount,
IndexBufferCompressionFormat format,
WriteBitstream& output ) WriteBitstream& output )
{ {
CompressIndexBuffer<uint16_t>( triangles, triangleCount, vertexRemap, vertexCount, output );
CompressIndexBuffer<uint16_t>( triangles, triangleCount, vertexRemap, vertexCount, format, output );
} }
void CompressIndexBuffer( const uint32_t* triangles, void CompressIndexBuffer( const uint32_t* triangles,
uint32_t triangleCount, uint32_t triangleCount,
uint32_t* vertexRemap, uint32_t* vertexRemap,
uint32_t vertexCount, uint32_t vertexCount,
IndexBufferCompressionFormat format,
WriteBitstream& output ) WriteBitstream& output )
{ {
CompressIndexBuffer<uint32_t>( triangles, triangleCount, vertexRemap, vertexCount, output ); CompressIndexBuffer<uint32_t>( triangles, triangleCount, vertexRemap, vertexCount, format, output );
} }
void CompressIndexBuffer2( const uint16_t* triangles,
uint32_t triangleCount,
uint32_t* vertexRemap,
uint32_t vertexCount,
WriteBitstream& output )
{
CompressIndexBuffer2<uint16_t>( triangles, triangleCount, vertexRemap, vertexCount, output );
}
void CompressIndexBuffer2( const uint32_t* triangles,
uint32_t triangleCount,
uint32_t* vertexRemap,
uint32_t vertexCount,
WriteBitstream& output )
{
CompressIndexBuffer2<uint32_t>( triangles, triangleCount, vertexRemap, vertexCount, output );
}

View file

@ -27,14 +27,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "WriteBitstream.h" #include "writebitstream.h"
#include "indexbuffercompressionformat.h"
// Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised // Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised
// order). // order).
// //
// This version has slightly worse compression and the matching decompression has worse performance than CompressIndexBuffer2, but it supports degenerate triangles
// (that have duplicate vertex indices). Output should be decompressed with DecompressIndexBuffer. It also changes the order of the vertices in each triangle less.
//
// It works by outputting a code (along with any required index symbols) per vertex. // It works by outputting a code (along with any required index symbols) per vertex.
// //
// Parameters: // Parameters:
@ -44,37 +42,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// where indexing with the old vertex index will get you the new one. // where indexing with the old vertex index will get you the new one.
// It should be allocated as a with at least vertexCount entries. // It should be allocated as a with at least vertexCount entries.
// [in] vertexCount - The number of vertices in the mesh. This should be less than 0xFFFFFFFF/2^32 - 1. // [in] vertexCount - The number of vertices in the mesh. This should be less than 0xFFFFFFFF/2^32 - 1.
// [in] format - The compression format to use for encoding - note the format will be encoded with the compressed data so the decompressor can select the correct algorithm.
// [in] output - The stream that the compressed data will be written to. Note that we will not flush/finish the stream // [in] output - The stream that the compressed data will be written to. Note that we will not flush/finish the stream
// in case something else is going to be written after, so WriteBitstream::Finish will need to be called after this. // in case something else is going to be written after, so WriteBitstream::Finish will need to be called after this.
void CompressIndexBuffer( const uint16_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, WriteBitstream& output ); void CompressIndexBuffer( const uint16_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, IndexBufferCompressionFormat format, WriteBitstream& output );
// Same as above but 32bit indices. // Same as above but 32bit indices.
void CompressIndexBuffer( const uint32_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, WriteBitstream& output ); void CompressIndexBuffer( const uint32_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, IndexBufferCompressionFormat format, WriteBitstream& output );
// Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised
// order).
//
// This version has slightly better compression and the matching decompression has better performance than CompressIndexBuffer, but it does not supports degenerate triangles
// (that have duplicate vertex indices). Output should be decompressed with DecompressIndexBuffer2. It changes the order of the vertices in each triangle more.
//
// This version also has compression optimisations that allow it to handle strip/fan cases a lot better compression wise.
//
// This works by outputting a code per triangle (along with the required index symbols).
//
// Parameters:
// [in] triangles - A typical triangle list index buffer (3 indices to vertices per triangle).
// [in] triangle count - The number of triangles to process.
// [out] vertexRemap - This will be populated with re-mappings that map old vertices to new vertices,
// where indexing with the old vertex index will get you the new one.
// It should be allocated as a with at least vertexCount entries.
// [in] vertexCount - The number of vertices in the mesh. This should be less than 0xFFFFFFFF/2^32 - 1.
// [in] output - The stream that the compressed data will be written to. Note that we will not flush/finish the stream
// in case something else is going to be written after, so WriteBitstream::Finish will need to be called after this.
void CompressIndexBuffer2( const uint16_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, WriteBitstream& output );
// Same as above but 32bit indices
void CompressIndexBuffer2( const uint32_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, WriteBitstream& output );
#endif // -- INDEX_BUFFER_COMPRESSION_H__ #endif // -- INDEX_BUFFER_COMPRESSION_H__

View file

@ -0,0 +1,14 @@
#ifndef INDEX_BUFFER_COMPRESSION_FORMAT_H__
#define INDEX_BUFFER_COMPRESSION_FORMAT_H__
#pragma once
enum IndexBufferCompressionFormat
{
// Per indice encoding - handles degenerates, but has worse compression/decompression speed and compression.
IBCF_PER_INDICE_1 = 0,
// Per triangle encoding - better compression/speed, does not handle degenerates.
IBCF_PER_TRIANGLE_1 = 1
};
#endif // -- INDEX_BUFFER_COMPRESSION_FORMAT_H__

View file

@ -22,13 +22,14 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "IndexBufferDecompression.h" #include "indexbufferdecompression.h"
#include "ReadBitstream.h" #include "readbitstream.h"
#include "IndexCompressionConstants.h" #include "indexcompressionconstants.h"
#include "indexbuffercompressionformat.h"
#include <assert.h> #include <assert.h>
template <typename Ty> template <typename Ty>
void DecompressIndexBuffer2( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) void DecompressTriangleCodes1( Ty* triangles, uint32_t triangleCount, ReadBitstream& input )
{ {
Edge edgeFifo[ EDGE_FIFO_SIZE ]; Edge edgeFifo[ EDGE_FIFO_SIZE ];
uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; uint32_t vertexFifo[ VERTEX_FIFO_SIZE ];
@ -341,7 +342,7 @@ void DecompressIndexBuffer2( Ty* triangles, uint32_t triangleCount, ReadBitstrea
} }
template <typename Ty> template <typename Ty>
void DecompressIndexBuffer( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) void DecompressIndiceCodes1( Ty* triangles, uint32_t triangleCount, ReadBitstream& input )
{ {
Edge edgeFifo[ EDGE_FIFO_SIZE ]; Edge edgeFifo[ EDGE_FIFO_SIZE ];
uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; uint32_t vertexFifo[ VERTEX_FIFO_SIZE ];
@ -359,7 +360,7 @@ void DecompressIndexBuffer( Ty* triangles, uint32_t triangleCount, ReadBitstream
while ( readVertex < 3 ) while ( readVertex < 3 )
{ {
IndexBufferCodes code = static_cast< IndexBufferCodes >( input.Read( IB_CODE_BITS ) ); IndexBufferCodes code = static_cast< IndexBufferCodes >( input.Read( IB_VERTEX_CODE_BITS ) );
switch ( code ) switch ( code )
{ {
@ -447,9 +448,24 @@ void DecompressIndexBuffer( Ty* triangles, uint32_t triangleCount, ReadBitstream
} }
} }
void DecompressIndexBuffer( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input ) template < typename Ty >
void DecompressIndexBuffer( Ty* triangles, uint32_t triangleCount, ReadBitstream& input )
{ {
DecompressIndexBuffer<uint16_t>( triangles, triangleCount, input ); IndexBufferCompressionFormat format = static_cast< IndexBufferCompressionFormat >( input.ReadVInt() );
switch ( format )
{
case IBCF_PER_INDICE_1:
DecompressIndiceCodes1<Ty>( triangles, triangleCount, input );
break;
case IBCF_PER_TRIANGLE_1:
DecompressTriangleCodes1<Ty>( triangles, triangleCount, input );
break;
}
} }
void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input ) void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input )
@ -457,12 +473,7 @@ void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBit
DecompressIndexBuffer<uint32_t>( triangles, triangleCount, input ); DecompressIndexBuffer<uint32_t>( triangles, triangleCount, input );
} }
void DecompressIndexBuffer2( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input ) void DecompressIndexBuffer( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input )
{ {
DecompressIndexBuffer2<uint16_t>( triangles, triangleCount, input ); DecompressIndexBuffer<uint16_t>( triangles, triangleCount, input );
} }
void DecompressIndexBuffer2( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input )
{
DecompressIndexBuffer2<uint32_t>( triangles, triangleCount, input );
}

View file

@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "ReadBitstream.h" #include "readbitstream.h"
// Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised // Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised
// order. // order.
@ -40,16 +40,4 @@ void DecompressIndexBuffer( uint16_t* triangles, uint32_t triangleCount, ReadBit
// Same as above but 32 bit indices. // Same as above but 32 bit indices.
void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input ); void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input );
// Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised
// order.
// Parameters:
// [out] triangles - Triangle list index buffer (3 indices to vertices per triangle), output from the decompression - 16bit indices
// [in] triangle count - The number of triangles to decompress.
// [in] input - The bit stream that the compressed data will be read from.
void DecompressIndexBuffer2( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input );
// Same as above but 32bit indices
void DecompressIndexBuffer2( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input );
#endif // -- INDEX_BUFFER_DECOMPRESSION_H__ #endif // -- INDEX_BUFFER_DECOMPRESSION_H__

View file

@ -29,13 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h> #include <stdint.h>
// Constant fifo and code sizes. // Constant fifo and code sizes.
const int VERTEX_FIFO_SIZE = 32; const int VERTEX_FIFO_SIZE = 32;
const int VERTEX_FIFO_MASK = VERTEX_FIFO_SIZE - 1; const int VERTEX_FIFO_MASK = VERTEX_FIFO_SIZE - 1;
const int EDGE_FIFO_SIZE = 32; const int EDGE_FIFO_SIZE = 32;
const int EDGE_FIFO_MASK = EDGE_FIFO_SIZE - 1; const int EDGE_FIFO_MASK = EDGE_FIFO_SIZE - 1;
const int CACHED_EDGE_BITS = 5; const int CACHED_EDGE_BITS = 5;
const int CACHED_VERTEX_BITS = 5; const int CACHED_VERTEX_BITS = 5;
const int IB_CODE_BITS = 2;
const int IB_VERTEX_CODE_BITS = 2;
const int IB_TRIANGLE_CODE_BITS = 4; const int IB_TRIANGLE_CODE_BITS = 4;

View file

@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -34,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#else #else
#define RBS_INLINE __attribute__((always_inline)) #define RBS_INLINE inline
#endif #endif

View file

@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <memory.h> #include <memory.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#define WBS_INLINE __forceinline #define WBS_INLINE __forceinline
#else #else
#define WBS_INLINE __attribute__((always_inline)) #define WBS_INLINE inline
#endif #endif
// Very simple bitstream for writing that will grow to accomodate written bits. // Very simple bitstream for writing that will grow to accomodate written bits.