Cleanup CUDA compressor.
This commit is contained in:
parent
2c1b75d8f3
commit
3d3409e666
@ -235,7 +235,7 @@ static __device__ float evalPermutation3(const float3 * colors, const float * we
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Sort colors
|
// Sort colors
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
__device__ void sortColors(float * values, float3 * colors, int * cmp)
|
__device__ void sortColors(float * values, int * cmp)
|
||||||
{
|
{
|
||||||
int tid = threadIdx.x;
|
int tid = threadIdx.x;
|
||||||
|
|
||||||
@ -272,53 +272,6 @@ __device__ void sortColors(float * values, float3 * colors, int * cmp)
|
|||||||
if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid];
|
if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid];
|
||||||
if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid];
|
if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid];
|
||||||
if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid];
|
if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid];
|
||||||
|
|
||||||
float3 tmp = colors[tid];
|
|
||||||
colors[cmp[tid]] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
__device__ void sortColors(float * values, float3 * colors, float * weights, int * cmp)
|
|
||||||
{
|
|
||||||
int tid = threadIdx.x;
|
|
||||||
|
|
||||||
cmp[tid] = (values[0] < values[tid]);
|
|
||||||
cmp[tid] += (values[1] < values[tid]);
|
|
||||||
cmp[tid] += (values[2] < values[tid]);
|
|
||||||
cmp[tid] += (values[3] < values[tid]);
|
|
||||||
cmp[tid] += (values[4] < values[tid]);
|
|
||||||
cmp[tid] += (values[5] < values[tid]);
|
|
||||||
cmp[tid] += (values[6] < values[tid]);
|
|
||||||
cmp[tid] += (values[7] < values[tid]);
|
|
||||||
cmp[tid] += (values[8] < values[tid]);
|
|
||||||
cmp[tid] += (values[9] < values[tid]);
|
|
||||||
cmp[tid] += (values[10] < values[tid]);
|
|
||||||
cmp[tid] += (values[11] < values[tid]);
|
|
||||||
cmp[tid] += (values[12] < values[tid]);
|
|
||||||
cmp[tid] += (values[13] < values[tid]);
|
|
||||||
cmp[tid] += (values[14] < values[tid]);
|
|
||||||
cmp[tid] += (values[15] < values[tid]);
|
|
||||||
|
|
||||||
// Resolve elements with the same index.
|
|
||||||
if (tid > 0 && cmp[tid] == cmp[0]) ++cmp[tid];
|
|
||||||
if (tid > 1 && cmp[tid] == cmp[1]) ++cmp[tid];
|
|
||||||
if (tid > 2 && cmp[tid] == cmp[2]) ++cmp[tid];
|
|
||||||
if (tid > 3 && cmp[tid] == cmp[3]) ++cmp[tid];
|
|
||||||
if (tid > 4 && cmp[tid] == cmp[4]) ++cmp[tid];
|
|
||||||
if (tid > 5 && cmp[tid] == cmp[5]) ++cmp[tid];
|
|
||||||
if (tid > 6 && cmp[tid] == cmp[6]) ++cmp[tid];
|
|
||||||
if (tid > 7 && cmp[tid] == cmp[7]) ++cmp[tid];
|
|
||||||
if (tid > 8 && cmp[tid] == cmp[8]) ++cmp[tid];
|
|
||||||
if (tid > 9 && cmp[tid] == cmp[9]) ++cmp[tid];
|
|
||||||
if (tid > 10 && cmp[tid] == cmp[10]) ++cmp[tid];
|
|
||||||
if (tid > 11 && cmp[tid] == cmp[11]) ++cmp[tid];
|
|
||||||
if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid];
|
|
||||||
if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid];
|
|
||||||
if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid];
|
|
||||||
|
|
||||||
float3 tmp = colors[tid];
|
|
||||||
colors[cmp[tid]] = tmp;
|
|
||||||
|
|
||||||
weights[cmp[tid]] = weights[tid];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -330,11 +283,10 @@ __device__ void minimizeError(float * errors, int * indices)
|
|||||||
const int idx = threadIdx.x;
|
const int idx = threadIdx.x;
|
||||||
|
|
||||||
#if __DEVICE_EMULATION__
|
#if __DEVICE_EMULATION__
|
||||||
|
|
||||||
for(int d = NUM_THREADS/2; d > 0; d >>= 1)
|
for(int d = NUM_THREADS/2; d > 0; d >>= 1)
|
||||||
{
|
{
|
||||||
__syncthreads();
|
__syncthreads();
|
||||||
|
|
||||||
if (idx < d)
|
if (idx < d)
|
||||||
{
|
{
|
||||||
float err0 = errors[idx];
|
float err0 = errors[idx];
|
||||||
@ -348,16 +300,15 @@ __device__ void minimizeError(float * errors, int * indices)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
for(int d = NUM_THREADS/2; d > 32; d >>= 1)
|
for(int d = NUM_THREADS/2; d > 32; d >>= 1)
|
||||||
{
|
{
|
||||||
__syncthreads();
|
__syncthreads();
|
||||||
|
|
||||||
if (idx < d)
|
if (idx < d)
|
||||||
{
|
{
|
||||||
float err0 = errors[idx];
|
float err0 = errors[idx];
|
||||||
float err1 = errors[idx + d];
|
float err1 = errors[idx + d];
|
||||||
|
|
||||||
if (err1 < err0) {
|
if (err1 < err0) {
|
||||||
errors[idx] = err1;
|
errors[idx] = err1;
|
||||||
indices[idx] = indices[idx + d];
|
indices[idx] = indices[idx + d];
|
||||||
@ -365,7 +316,7 @@ __device__ void minimizeError(float * errors, int * indices)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unroll last 6 steps
|
// unroll last 6 iterations
|
||||||
if (idx <= 32)
|
if (idx <= 32)
|
||||||
{
|
{
|
||||||
if (errors[idx + 32] < errors[idx]) {
|
if (errors[idx + 32] < errors[idx]) {
|
||||||
@ -398,17 +349,15 @@ __device__ void minimizeError(float * errors, int * indices)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Compress color block
|
// Load color block to shared mem
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
__global__ void compress(const uint * permutations, const uint * image, uint2 * result)
|
__device__ void loadColorBlock(const uint * image, float3 colors[16], int xrefs[16])
|
||||||
{
|
{
|
||||||
const int bid = blockIdx.x;
|
const int bid = blockIdx.x;
|
||||||
const int idx = threadIdx.x;
|
const int idx = threadIdx.x;
|
||||||
|
|
||||||
__shared__ float3 colors[16];
|
|
||||||
__shared__ float dps[16];
|
__shared__ float dps[16];
|
||||||
__shared__ int xrefs[16];
|
|
||||||
|
|
||||||
if (idx < 16)
|
if (idx < 16)
|
||||||
{
|
{
|
||||||
// Read color and copy to shared mem.
|
// Read color and copy to shared mem.
|
||||||
@ -432,8 +381,93 @@ __global__ void compress(const uint * permutations, const uint * image, uint2 *
|
|||||||
} __debugsync(); if (idx < 16) {
|
} __debugsync(); if (idx < 16) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sortColors(dps, colors, xrefs);
|
sortColors(dps, xrefs);
|
||||||
|
|
||||||
|
float3 tmp = colors[idx];
|
||||||
|
colors[xrefs[idx]] = tmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__device__ void loadColorBlock(const uint * image, float3 colors[16], float weights[16], int xrefs[16])
|
||||||
|
{
|
||||||
|
const int bid = blockIdx.x;
|
||||||
|
const int idx = threadIdx.x;
|
||||||
|
|
||||||
|
__shared__ float dps[16];
|
||||||
|
|
||||||
|
if (idx < 16)
|
||||||
|
{
|
||||||
|
// Read color and copy to shared mem.
|
||||||
|
uint c = image[(bid) * 16 + idx];
|
||||||
|
|
||||||
|
colors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f);
|
||||||
|
colors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||||
|
colors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f);
|
||||||
|
weights[idx] = ((c >> 24) & 0xFF) * (1.0f / 255.0f);
|
||||||
|
|
||||||
|
// No need to synchronize, 16 < warp size.
|
||||||
|
#if __DEVICE_EMULATION__
|
||||||
|
} __debugsync(); if (idx < 16) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Sort colors along the best fit line.
|
||||||
|
float3 axis = bestFitLine(colors);
|
||||||
|
|
||||||
|
dps[idx] = dot(colors[idx], axis);
|
||||||
|
|
||||||
|
#if __DEVICE_EMULATION__
|
||||||
|
} __debugsync(); if (idx < 16) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sortColors(dps, xrefs);
|
||||||
|
|
||||||
|
float3 tmp = colors[idx];
|
||||||
|
colors[xrefs[idx]] = tmp;
|
||||||
|
|
||||||
|
float w = weights[idx];
|
||||||
|
weights[xrefs[idx]] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__device__ void saveBlockDXT1(ushort start, ushort end, uint permutation, int xrefs[16])
|
||||||
|
{
|
||||||
|
const int bid = blockIdx.x;
|
||||||
|
const int idx = threadIdx.x;
|
||||||
|
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
permutation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reorder permutation.
|
||||||
|
uint indices = 0;
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
int ref = xrefs[i];
|
||||||
|
indices |= ((permutation >> (2 * ref)) & 3) << (2 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write endpoints.
|
||||||
|
result[bid].x = (end << 16) | start;
|
||||||
|
|
||||||
|
// Write palette indices.
|
||||||
|
result[bid].y = indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Compress color block
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
__global__ void compress(const uint * permutations, const uint * image, uint2 * result)
|
||||||
|
{
|
||||||
|
const int bid = blockIdx.x;
|
||||||
|
const int idx = threadIdx.x;
|
||||||
|
|
||||||
|
__shared__ float3 colors[16];
|
||||||
|
__shared__ int xrefs[16];
|
||||||
|
|
||||||
|
loadColorBlock(image, colors, xrefs);
|
||||||
|
|
||||||
ushort bestStart, bestEnd;
|
ushort bestStart, bestEnd;
|
||||||
uint bestPermutation;
|
uint bestPermutation;
|
||||||
@ -495,7 +529,7 @@ __global__ void compress(const uint * permutations, const uint * image, uint2 *
|
|||||||
{
|
{
|
||||||
pidx = idx + NUM_THREADS * 2;
|
pidx = idx + NUM_THREADS * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ushort start, end;
|
ushort start, end;
|
||||||
uint permutation = permutations[pidx];
|
uint permutation = permutations[pidx];
|
||||||
float error = evalPermutation4(colors, permutation, &start, &end);
|
float error = evalPermutation4(colors, permutation, &start, &end);
|
||||||
@ -552,7 +586,7 @@ __global__ void compress(const uint * permutations, const uint * image, uint2 *
|
|||||||
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = evalPermutation4(colors, permutation, &start, &end);
|
error = evalPermutation4(colors, permutation, &start, &end);
|
||||||
|
|
||||||
if (error < bestError)
|
if (error < bestError)
|
||||||
@ -561,7 +595,7 @@ __global__ void compress(const uint * permutations, const uint * image, uint2 *
|
|||||||
bestPermutation = permutation;
|
bestPermutation = permutation;
|
||||||
bestStart = start;
|
bestStart = start;
|
||||||
bestEnd = end;
|
bestEnd = end;
|
||||||
|
|
||||||
if (bestStart < bestEnd)
|
if (bestStart < bestEnd)
|
||||||
{
|
{
|
||||||
swap(bestEnd, bestStart);
|
swap(bestEnd, bestStart);
|
||||||
@ -587,24 +621,7 @@ __global__ void compress(const uint * permutations, const uint * image, uint2 *
|
|||||||
// Only write the result of the winner thread.
|
// Only write the result of the winner thread.
|
||||||
if (idx == indices[0])
|
if (idx == indices[0])
|
||||||
{
|
{
|
||||||
if (bestStart == bestEnd)
|
saveBlockDXT1(bestStart, bestEnd, bestPermutation, xrefs);
|
||||||
{
|
|
||||||
bestPermutation = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reorder permutation.
|
|
||||||
uint perm = 0;
|
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
int ref = xrefs[i];
|
|
||||||
perm |= ((bestPermutation >> (2 * ref)) & 3) << (2 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write endpoints. (bestStart, bestEnd)
|
|
||||||
result[bid].x = (bestEnd << 16) | bestStart;
|
|
||||||
|
|
||||||
// Write palette indices (permutation).
|
|
||||||
result[bid].y = perm;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,36 +633,10 @@ __global__ void compressWeighted(const uint * permutations, const uint * image,
|
|||||||
|
|
||||||
__shared__ float3 colors[16];
|
__shared__ float3 colors[16];
|
||||||
__shared__ float weights[16];
|
__shared__ float weights[16];
|
||||||
__shared__ float dps[16];
|
|
||||||
__shared__ int xrefs[16];
|
__shared__ int xrefs[16];
|
||||||
|
|
||||||
if (idx < 16)
|
loadColorBlock(image, colors, weights, xrefs);
|
||||||
{
|
|
||||||
// Read color and copy to shared mem.
|
|
||||||
uint c = image[(bid) * 16 + idx];
|
|
||||||
|
|
||||||
colors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f);
|
|
||||||
colors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f);
|
|
||||||
colors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f);
|
|
||||||
weights[idx] = ((c >> 24) & 0xFF) * (1.0f / 255.0f);
|
|
||||||
|
|
||||||
// No need to synchronize, 16 < warp size.
|
|
||||||
#if __DEVICE_EMULATION__
|
|
||||||
} __debugsync(); if (idx < 16) {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Sort colors along the best fit line.
|
|
||||||
float3 axis = bestFitLine(colors);
|
|
||||||
|
|
||||||
dps[idx] = dot(colors[idx], axis);
|
|
||||||
|
|
||||||
#if __DEVICE_EMULATION__
|
|
||||||
} __debugsync(); if (idx < 16) {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sortColors(dps, colors, weights, xrefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort bestStart, bestEnd;
|
ushort bestStart, bestEnd;
|
||||||
uint bestPermutation;
|
uint bestPermutation;
|
||||||
float bestError = FLT_MAX;
|
float bestError = FLT_MAX;
|
||||||
|
Loading…
Reference in New Issue
Block a user