summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--convtexture.c128
-rw-r--r--video.cpp63
-rw-r--r--video.hpp9
3 files changed, 169 insertions, 31 deletions
diff --git a/convtexture.c b/convtexture.c
index e5ec996..5ad4735 100644
--- a/convtexture.c
+++ b/convtexture.c
@@ -35,6 +35,73 @@ const char* format_names[] = {
#undef x
};
+void gen_mip(Image* src, Image* dst, int w, int h) {
+ const float weight = 1.0f / 4.0f;
+ int i, x, y, sw = src->w;
+ dst->pixels = malloc(w * h * sizeof *dst->pixels);
+ dst->w = w;
+ dst->h = h;
+ assert(w == src->w / 2);
+ assert(h == src->h / 2);
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ int sx = x << 1;
+ int sy = y << 1;
+ int ind[] = {
+ sx + (sy) * sw,
+ sx + 1 + (sy) * sw,
+ sx + (sy + 1) * sw,
+ sx + 1 + (sy + 1) * sw
+ };
+ float avg[4] = { 0 };
+ Colour* d = &dst->pixels[x + y * w];
+ for (i = 0; i < 4; i++) {
+ int j;
+ for (j = 0; j < 4; j++)
+ avg[j] +=
+ (float)((uint8_t*)&src->pixels[ind[i]])[j] *
+ weight;
+ }
+ d->r = (uint8_t)avg[0];
+ d->g = (uint8_t)avg[1];
+ d->b = (uint8_t)avg[2];
+ d->a = (uint8_t)avg[3];
+ }
+ }
+}
+
+int auto_count(int w, int h) {
+ int i;
+ for (i = 0; w > 1 || h > 1; i++, w >>= 1, h >>= 1);
+ return i;
+}
+
+int po2(int x) {
+ return x && (!(x & (x - 1)));
+}
+
+Image* gen_mips(Image* src, int count, int* gen_count) {
+ int i, w, h;
+ Image* imgs;
+ if (!count)
+ count = auto_count(src->w, src->h);
+ imgs = malloc(count * sizeof *imgs);
+ imgs[0] = *src;
+ w = src->w >> 1;
+ h = src->h >> 1;
+ if (count && (!po2(src->w) || !po2(src->h))) {
+ print_war("Image size not a power of 2 (no mips for you >:(\n");
+ count = 1;
+ }
+ for (i = 1; i < count; i++) {
+ gen_mip(&imgs[i - 1], &imgs[i], w, h);
+ w >>= 1;
+ h >>= 1;
+ }
+ *gen_count = i;
+ return imgs;
+}
+
unsigned encode_endpoint(const vec3* v) {
return
((unsigned)(v->r * 31.9999f) << 11) |
@@ -264,28 +331,33 @@ void compress_bc5(Colour* pixels, int w, int h, FILE* f) {
}
}
-void write_header(FILE* f, int w, int h, Texture_Format fmt) {
+void write_header(FILE* f, int w, int h, int mips, Texture_Format fmt) {
fwrite("TXTR", 1, 4, f);
fwrite(&w, 1, 4, f);
fwrite(&h, 1, 4, f);
- fwrite(&fmt, 1, 4, f);
+ fwrite(&fmt, 1, 2, f);
+ fwrite(&mips, 1, 2, f);
}
-void convert(Image* image, Texture_Format target, FILE* f) {
- write_header(f, image->w, image->h, target);
- switch (target) {
- case texture_format_bc1:
- compress_bc1(image->pixels, image->w, image->h, f);
- break;
- case texture_format_bc4:
- compress_bc4(image->pixels, image->w, image->h, f);
- break;
- case texture_format_bc5:
- compress_bc5(image->pixels, image->w, image->h, f);
- break;
- default:
- print_err("Unsupported target format.\n");
- pbreak(40);
+void convert(Image* images, int count, Texture_Format target, FILE* f) {
+ int i;
+ write_header(f, images->w, images->h, count, target);
+ for (i = 0; i < count; i++) {
+ Image* image = &images[i];
+ switch (target) {
+ case texture_format_bc1:
+ compress_bc1(image->pixels, image->w, image->h, f);
+ break;
+ case texture_format_bc4:
+ compress_bc4(image->pixels, image->w, image->h, f);
+ break;
+ case texture_format_bc5:
+ compress_bc5(image->pixels, image->w, image->h, f);
+ break;
+ default:
+ print_err("Unsupported target format.\n");
+ pbreak(40);
+ }
}
}
@@ -299,12 +371,17 @@ Texture_Format texture_format_from_string(const char* s) {
return (Texture_Format)0;
}
-int proc_bitmap(FILE* infile, FILE* outfile, Texture_Format target) {
+int proc_bitmap(
+ FILE* infile,
+ FILE* outfile,
+ Texture_Format target,
+ int mc
+) {
unsigned bmp_offset;
int bmp_w, bmp_h, s, x, y;
unsigned short bmp_bits;
Colour* buffer;
- Image img;
+ Image img, * imgs;
Colour pixel;
fseek(infile, 10, SEEK_SET);
@@ -347,7 +424,8 @@ int proc_bitmap(FILE* infile, FILE* outfile, Texture_Format target) {
img.pixels = buffer;
img.w = bmp_w;
img.h = bmp_h;
- convert(&img, target, outfile);
+ imgs = gen_mips(&img, mc, &mc);
+ convert(imgs, mc, target, outfile);
fclose(outfile);
return 0;
}
@@ -519,12 +597,13 @@ int proc_hdr(FILE* infile, FILE* outfile, int half) {
}
}
if (half) {
- write_header(outfile, w, h, texture_format_rgba16f);
+ write_header(outfile, w, h, 1, texture_format_rgba16f);
write_halves(outfile, w * h * 4, (float*)pixels);
} else {
- write_header(outfile, w, h, texture_format_rgba32f);
+ write_header(outfile, w, h, 1, texture_format_rgba32f);
fwrite(pixels, sizeof *pixels, w * h, outfile);
}
+ /* todo mipgen for hdr */
fclose(outfile);
return 0;
}
@@ -532,6 +611,7 @@ int proc_hdr(FILE* infile, FILE* outfile, int half) {
int main(int argc, const char** argv) {
FILE* outfile, * infile;
char magic[11];
+ int mips = 0;
Texture_Format target;
if (argc < 4) {
@@ -545,6 +625,8 @@ int main(int argc, const char** argv) {
return 2;
}
target = texture_format_from_string(argv[3]);
+ if (argc > 4)
+ mips = (int)strtol(argv[4], 0, 10);
outfile = fopen(argv[2], "wb");
if (!outfile) {
@@ -554,7 +636,7 @@ int main(int argc, const char** argv) {
fread(magic, 1, 10, infile); magic[10] = 0;
if (magic[0] == 'B' && magic[1] == 'M') {
- return proc_bitmap(infile, outfile, target);
+ return proc_bitmap(infile, outfile, target, mips);
}
if (string_equal(magic, "#?RADIANCE")) {
int half = target == texture_format_rgba16f;
diff --git a/video.cpp b/video.cpp
index fa98813..08ee606 100644
--- a/video.cpp
+++ b/video.cpp
@@ -2252,6 +2252,40 @@ void Context::copy(Texture_Id dst, Buffer_Id src) {
);
}
+void Context::copy(
+ Texture_Id dst,
+ Buffer_Id src,
+ int mip,
+ int x,
+ int y,
+ int w,
+ int h
+) {
+ Context_Vk* ctx = (Context_Vk*)this;
+ Device_Vk* dev = ctx->dev;
+ Texture_Vk& a = *(Texture_Vk*)&dev->get_texture(dst);
+ Buffer_Vk& b = *(Buffer_Vk*)&dev->get_buffer(src);
+ VkBufferImageCopy c{};
+ transition(dst, Resource_State::copy_dst);
+ c.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ c.imageSubresource.layerCount = 1;
+ c.imageSubresource.mipLevel = mip;
+ c.imageExtent.width = w;
+ c.imageExtent.height = h;
+ c.imageExtent.depth = 1;
+ c.imageOffset.x = x;
+ c.imageOffset.y = y;
+ ctx->check_end_rp();
+ vkCmdCopyBufferToImage(
+ ctx->cb,
+ b.buf,
+ a.image,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1,
+ &c
+ );
+}
+
void Context::transition(Texture_Id id, Resource_State state) {
Context_Vk* ctx = (Context_Vk*)this;
Device_Vk* dev = ctx->dev;
@@ -3946,13 +3980,15 @@ Asset* Texture_Loader::load(
char magic[4];
int w, h;
size_t size;
- Texture_Format fmt;
+ Texture_Format fmt = texture_format_r8i;
+ int mips = 0;
(void)a;
(void)s;
pack_read(f, magic, 4);
pack_read(f, &w, 4);
pack_read(f, &h, 4);
- pack_read(f, &fmt, 4);
+ pack_read(f, &fmt, 2);
+ pack_read(f, &mips, 2);
size = calc_size(fmt, w, h);
{
Buffer_Id buf = dev->create_buffer(
@@ -3961,9 +3997,6 @@ Asset* Texture_Loader::load(
Buffer_Flags::copy_src |
Buffer_Flags::cpu_readwrite
);
- void* mem = dev->map_buffer(buf, 0, size);
- pack_read(f, mem, size);
- dev->unmap_buffer(buf);
Texture_Id tex = dev->create_texture(
filename,
fmt,
@@ -3971,11 +4004,25 @@ Asset* Texture_Loader::load(
w,
h,
1,
+ mips,
1,
- 1,
- buf
+ 0
);
- dev->destroy_buffer(buf);
+ {
+ int i;
+ for (i = 0; i < mips; i++) {
+ size = calc_size(fmt, w, h);
+ void* mem = dev->map_buffer(buf, 0, size);
+ pack_read(f, mem, size);
+ dev->unmap_buffer(buf);
+ auto& ctx = dev->acquire();
+ ctx.copy(tex, buf, i, 0, 0, w, h);
+ dev->submit(ctx);
+ w >>= 1;
+ h >>= 1;
+ }
+ }
+ dev->destroy_bufferi(buf);
return &dev->get_texture(tex);
}
}
diff --git a/video.hpp b/video.hpp
index 5aa25bc..4afb6ba 100644
--- a/video.hpp
+++ b/video.hpp
@@ -553,6 +553,15 @@ struct Context {
void submit(const Render_Pass& rp);
void copy(Buffer_Id dst, Buffer_Id src);
void copy(Texture_Id dst, Buffer_Id src);
+ void copy(
+ Texture_Id dst,
+ Buffer_Id src,
+ int mip,
+ int x,
+ int y,
+ int w,
+ int h
+ );
void transition(Texture_Id id, Resource_State state);
void debug_push(const char* name);
void debug_pop();