UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rgb2dxt1.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include "cuda_dxt.h"
4
5
6#define DDS_HEADER_SIZE 128
7
8
9static void usage(const char * const name, const char * const message) {
10 printf("ERROR: %s\n", message);
11 printf("Usage: %s width height input.rgb output.dds\n", name);
12}
13
14
15int main(int argc, char** argv) {
16 FILE *in_file, *out_file;
17 size_t in_size, out_size, dds_size;
18 int size_x, size_y;
19 void *in_host = 0, *out_host = 0, *out_gpu = 0, *in_gpu = 0;
20 unsigned int * header;
21 cudaEvent_t event_begin, event_end;
22 float kernel_time_ms;
23
24 /* check arguments */
25 if(5 != argc) {
26 usage(argv[0], "Incorrect argument count.");
27 return -1;
28 }
29
30 /* get image size */
31 size_x = atoi(argv[1]);
32 size_y = atoi(argv[2]);
33 if(size_x <= 0 || (size_x & 3) || size_y == 0 || (abs(size_y) & 3)) {
34 usage(argv[0], "Image sizes must be positive numbers divisible by 4.");
35 return -1;
36 }
37
38 /* Check CUDA device */
39 if(cudaSuccess != cudaSetDevice(0)) {
40 usage(argv[0], "Cannot set CUDA device #0.");
41 return -1;
42 }
43
44 /* allocate buffers (both GPU and host buffers) */
45 in_size = size_x * abs(size_y) * 3;
46 out_size = in_size / 6;
47 dds_size = out_size + DDS_HEADER_SIZE;
48 cudaMallocHost(&in_host, in_size);
49 cudaMallocHost(&out_host, dds_size);
50 cudaMalloc(&in_gpu, in_size);
51 cudaMalloc(&out_gpu, out_size);
52 if(!in_host || !out_host || !out_gpu || !in_gpu) {
53 usage(argv[0], "Cannot allocate buffers.\n");
54 return -1;
55 }
56
57 /* open input file */
58 in_file = fopen(argv[3], "r");
59 if(!in_file) {
60 usage(argv[0], "Could not open input file.");
61 return -1;
62 }
63
64#if 0
65 /* check file size */
66 fseek(in_file, 0, SEEK_END);
67 if(ftell(in_file) != (long int)in_size) {
68 usage(argv[0], "Input file size does not match.");
69 return -1;
70 }
71 fseek(in_file, 0, SEEK_SET);
72#endif
73
74 /* load data */
75 if(1 != fread(in_host, in_size, 1, in_file)) {
76 usage(argv[0], "Could not read from input file.");
77 return -1;
78 }
79 fclose(in_file);
80
81 /* copy data into GPU buffer */
82 if(cudaSuccess != cudaMemcpy(in_gpu, in_host, in_size, cudaMemcpyHostToDevice)) {
83 usage(argv[0], "Could not copy input to GPU.");
84 return -1;
85 }
86
87 /* prepare envents for time emasurement and begin */
88 cudaEventCreate(&event_end);
89 cudaEventCreate(&event_begin);
90 cudaEventRecord(event_begin, 0);
91
92 /* compress */
93 if(cuda_rgb_to_dxt1(in_gpu, out_gpu, size_x, size_y, 0)) {
94 usage(argv[0], "DXT Encoder error.");
95 return -1;
96 }
97
98 /* measure kernel time */
99 cudaEventRecord(event_end, 0);
100
101 /* check kernel call */
102 if(cudaSuccess != cudaDeviceSynchronize()) {
104 return -1;
105 }
106
107 /* print the time */
108 cudaEventElapsedTime(&kernel_time_ms, event_begin, event_end);
109 printf("DXT1 compression time: %.3f ms.\n", kernel_time_ms);
110
111 /* copy back to host memory */
112 if(cudaSuccess != cudaMemcpy((char*)out_host + DDS_HEADER_SIZE, out_gpu, out_size, cudaMemcpyDeviceToHost)) {
113 usage(argv[0], "Could not copy output to host memory.");
114 return -1;
115 }
116
117 /*
118 * fill in DDS header
119 * http://www.team-blur-games.com/wiki/index.php?title=DDS_%28file_format%29
120 * http://msdn.microsoft.com/en-us/library/windows/desktop/bb943982%28v=vs.85%29.aspx
121 */
122 header = (unsigned int*)out_host;
123 *(header++) = 0x20534444; /* magic */
124 *(header++) = 124; /* header size */
125 *(header++) = 0xA1007; /* flags */
126 *(header++) = abs(size_y); /* height */
127 *(header++) = size_x; /* width */
128 *(header++) = size_x * 2; /* pitch (row size) in bytes */
129 *(header++) = 1; /* unused 3D depth */
130 *(header++) = 1; /* unused mipmap count */
131 *(header++) = 0; /* reserved */
132 *(header++) = 0; /* reserved */
133 *(header++) = 0; /* reserved */
134 *(header++) = 0; /* reserved */
135 *(header++) = 0; /* reserved */
136 *(header++) = 0; /* reserved */
137 *(header++) = 0; /* reserved */
138 *(header++) = 0; /* reserved */
139 *(header++) = 0; /* reserved */
140 *(header++) = 0; /* reserved */
141 *(header++) = 0; /* reserved */
142 *(header++) = 32; /* pixel format size */
143 *(header++) = 4; /* pixel format flags */
144 ((char*)header)[0] = 'D';
145 ((char*)header)[1] = 'X';
146 ((char*)header)[2] = 'T';
147 ((char*)header)[3] = '1';
148 header++; /* skip the four character code */
149 *(header++) = 0; /* pixel format (unused) */
150 *(header++) = 0; /* pixel format (unused) */
151 *(header++) = 0; /* pixel format (unused) */
152 *(header++) = 0; /* pixel format (unused) */
153 *(header++) = 0; /* pixel format (unused) */
154 *(header++) = 0x1000; /* flags */
155 *(header++) = 0; /* 3D flags */
156 *(header++) = 0; /* unused */
157 *(header++) = 0; /* unused */
158 *(header++) = 0; /* reserved */
159
160 /* open output file */
161 out_file = fopen(argv[4], "w");
162 if(!out_file) {
163 usage(argv[0], "Could not open output file for writing.");
164 return -1;
165 }
166
167 /* write output into the file */
168 if(1 != fwrite(out_host, dds_size, 1, out_file)) {
169 usage(argv[0], "Could not write into output file.");
170 return -1;
171 }
172 fclose(out_file);
173
174 /* free buffers */
175 cudaFreeHost(in_host);
176 cudaFreeHost(out_host);
177 cudaFree(in_gpu);
178 cudaFree(out_gpu);
179
180 /* indicate success */
181 return 0;
182}
183
static __device__ vec2 abs(const vec2 &v)
Definition cuda_dxt.cu:118
int cuda_rgb_to_dxt1(const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
Definition cuda_dxt.cu:782
Interface of DXT compression CUDA implementation.
#define cudaMemcpy
#define cudaSuccess
#define cudaFree
#define cudaMemcpyHostToDevice
#define cudaGetLastError
#define cudaMalloc
#define cudaFreeHost
#define cudaGetErrorString
void usage()
Definition main.cpp:28
#define DDS_HEADER_SIZE
Definition rgb2dxt1.c:6
const char * name
Definition settings.cpp:193