Begin new Asset Pipeline
This commit is contained in:
139
src/engine/Texture.zig
Normal file
139
src/engine/Texture.zig
Normal file
@@ -0,0 +1,139 @@
|
||||
const Texture = @This();
|
||||
const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const Engine = @import("Engine.zig");
|
||||
|
||||
pub const Usage = enum {
|
||||
base_color,
|
||||
normal,
|
||||
occlusion_roughness_metallic,
|
||||
emissive,
|
||||
|
||||
pub fn format(self: Usage) vk.Format {
|
||||
return switch (self) {
|
||||
.base_color => .r8g8b8_srgb,
|
||||
.normal => .r8g8b8_snorm,
|
||||
.occlusion_roughness_metallic => .r8g8b8_unorm,
|
||||
.emissive => .r16g16b16_sfloat,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn sampleCount(self: Usage) usize {
|
||||
return switch (self) {
|
||||
.base_color => 3,
|
||||
.normal => 3,
|
||||
.occlusion_roughness_metallic => 3,
|
||||
.emissive => 3,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn SampleType(comptime self: Usage) type {
|
||||
return switch (self) {
|
||||
.base_color => u8,
|
||||
.normal => u8,
|
||||
.occlusion_roughness_metallic => u8,
|
||||
.emissive => f16,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn sampleSize(self: Usage) usize {
|
||||
return switch (self) {
|
||||
inline else => |x| @sizeOf(SampleType(x)),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn TexelType(comptime self: Usage) type {
|
||||
return [self.sampleCount()]SampleType(self);
|
||||
}
|
||||
|
||||
pub fn texelSize(self: Usage) usize {
|
||||
return switch (self) {
|
||||
inline else => |x| @sizeOf(TexelType(x)),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
image: vk.Image,
|
||||
image_view: vk.ImageView,
|
||||
memory: vk.DeviceMemory,
|
||||
|
||||
width: u32,
|
||||
height: u32,
|
||||
usage: Usage,
|
||||
|
||||
pub fn init(engine: *Engine, width: u32, height: u32, usage: Usage) !Texture {
|
||||
const format: vk.Format = usage.format();
|
||||
|
||||
const image = try engine.device.createImage(&.{
|
||||
.image_type = .@"2d",
|
||||
.format = format,
|
||||
.extent = .{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mip_levels = 1,
|
||||
.array_layers = 1,
|
||||
.samples = .{ .@"1_bit" = true },
|
||||
.tiling = .optimal,
|
||||
.usage = .{
|
||||
.transfer_src_bit = true,
|
||||
.sampled_bit = true,
|
||||
},
|
||||
.sharing_mode = .exclusive,
|
||||
.initial_layout = .undefined,
|
||||
}, &engine.vk_allocator.interface);
|
||||
errdefer engine.device.destroyImage(image, &engine.vk_allocator.interface);
|
||||
|
||||
const memory_requirements = engine.device.getImageMemoryRequirements(image);
|
||||
const memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||
errdefer engine.device.freeMemory(memory, &engine.vk_allocator.interface);
|
||||
|
||||
try engine.device.bindImageMemory(image, memory, 0);
|
||||
|
||||
const image_view = try engine.device.createImageView(&.{
|
||||
.image = image,
|
||||
.view_type = .@"2d",
|
||||
.format = format,
|
||||
.components = .{
|
||||
.r = .identity,
|
||||
.g = .identity,
|
||||
.b = .identity,
|
||||
.a = .identity,
|
||||
},
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_level = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
}, &engine.vk_allocator.interface);
|
||||
errdefer engine.device.destroyImageView(image_view, &engine.vk_allocator.interface);
|
||||
|
||||
return .{
|
||||
.image = image,
|
||||
.image_view = image_view,
|
||||
.memory = memory,
|
||||
.width = width,
|
||||
.height = height,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Texture, engine: *Engine) void {
|
||||
engine.device.destroyImageView(self.image_view, &engine.vk_allocator.interface);
|
||||
engine.device.freeMemory(self.memory, &engine.vk_allocator.interface);
|
||||
engine.device.destroyImage(self.image, &engine.vk_allocator.interface);
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn write(self: Texture, comptime T: type, data: []const T) void {
|
||||
const bytes_per_texel = self.format.texelSize();
|
||||
const bytes_per_row = self.width * bytes_per_texel;
|
||||
const byte_length = self.height * bytes_per_row;
|
||||
|
||||
std.debug.assert(data.len * @sizeOf(T) == byte_length);
|
||||
}
|
||||
Reference in New Issue
Block a user