renaming folders
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const base = @import("base");
|
||||
const spv = @import("spv");
|
||||
|
||||
const VkError = base.VkError;
|
||||
const SoftDevice = @import("SoftDevice.zig");
|
||||
const SoftShaderModule = @import("SoftShaderModule.zig");
|
||||
|
||||
const Self = @This();
|
||||
pub const Interface = base.PipelineCache;
|
||||
|
||||
const SpecConstant = struct {
|
||||
id: u32,
|
||||
data: []u8,
|
||||
};
|
||||
|
||||
const CacheRecord = extern struct {
|
||||
magic: [8]u8,
|
||||
version: u32,
|
||||
code_hash: u64,
|
||||
entry_hash: u64,
|
||||
spec_hash: u64,
|
||||
};
|
||||
|
||||
const CachedShader = struct {
|
||||
module: *SoftShaderModule,
|
||||
entry: []u8,
|
||||
specs: []SpecConstant,
|
||||
runtime: spv.Runtime,
|
||||
|
||||
fn deinit(self: *@This(), object_allocator: std.mem.Allocator, data_allocator: std.mem.Allocator) void {
|
||||
self.module.unref(object_allocator);
|
||||
data_allocator.free(self.entry);
|
||||
for (self.specs) |spec| {
|
||||
data_allocator.free(spec.data);
|
||||
}
|
||||
if (self.specs.len != 0) {
|
||||
data_allocator.free(self.specs);
|
||||
}
|
||||
self.runtime.deinit(data_allocator);
|
||||
}
|
||||
};
|
||||
|
||||
interface: Interface,
|
||||
mutex: std.Io.Mutex,
|
||||
shaders: std.ArrayList(CachedShader),
|
||||
|
||||
pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const vk.PipelineCacheCreateInfo) VkError!*Self {
|
||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
var interface = try Interface.init(device, allocator, info);
|
||||
|
||||
interface.vtable = &.{
|
||||
.destroy = destroy,
|
||||
};
|
||||
|
||||
self.* = .{
|
||||
.interface = interface,
|
||||
.mutex = .init,
|
||||
.shaders = .empty,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
||||
const data_allocator = soft_device.device_allocator.allocator();
|
||||
|
||||
for (self.shaders.items) |*shader| {
|
||||
shader.deinit(allocator, data_allocator);
|
||||
}
|
||||
self.shaders.deinit(data_allocator);
|
||||
allocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn cloneRuntime(
|
||||
self: *Self,
|
||||
allocator: std.mem.Allocator,
|
||||
module: *SoftShaderModule,
|
||||
entry: []const u8,
|
||||
specialization: ?*const vk.SpecializationInfo,
|
||||
image_api: spv.Runtime.ImageAPI,
|
||||
) VkError!?spv.Runtime {
|
||||
const io = self.interface.owner.io();
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
for (self.shaders.items) |*shader| {
|
||||
if (shader.module == module and std.mem.eql(u8, shader.entry, entry) and specsEqual(shader.specs, specialization)) {
|
||||
return spv.Runtime.initFrom(allocator, &shader.runtime, image_api) catch return VkError.OutOfDeviceMemory;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn storeRuntimeTemplate(
|
||||
self: *Self,
|
||||
object_allocator: std.mem.Allocator,
|
||||
data_allocator: std.mem.Allocator,
|
||||
module: *SoftShaderModule,
|
||||
entry: []const u8,
|
||||
specialization: ?*const vk.SpecializationInfo,
|
||||
image_api: spv.Runtime.ImageAPI,
|
||||
) VkError!void {
|
||||
const io = self.interface.owner.io();
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
for (self.shaders.items) |*shader| {
|
||||
if (shader.module == module and
|
||||
std.mem.eql(u8, shader.entry, entry) and
|
||||
specsEqual(shader.specs, specialization))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var cached: CachedShader = .{
|
||||
.module = module,
|
||||
.entry = data_allocator.dupe(u8, entry) catch return VkError.OutOfDeviceMemory,
|
||||
.specs = try cloneSpecs(data_allocator, specialization),
|
||||
.runtime = spv.Runtime.init(data_allocator, &module.module, image_api) catch return VkError.OutOfDeviceMemory,
|
||||
};
|
||||
|
||||
var module_ref = false;
|
||||
errdefer {
|
||||
if (module_ref) cached.module.unref(object_allocator);
|
||||
data_allocator.free(cached.entry);
|
||||
for (cached.specs) |spec| {
|
||||
data_allocator.free(spec.data);
|
||||
}
|
||||
if (cached.specs.len != 0) {
|
||||
data_allocator.free(cached.specs);
|
||||
}
|
||||
cached.runtime.deinit(data_allocator);
|
||||
}
|
||||
|
||||
module.ref();
|
||||
module_ref = true;
|
||||
try applySpecialization(&cached.runtime, data_allocator, specialization);
|
||||
try appendCacheRecord(&self.interface, module, entry, cached.specs);
|
||||
|
||||
self.shaders.append(data_allocator, cached) catch return VkError.OutOfDeviceMemory;
|
||||
}
|
||||
|
||||
fn applySpecialization(runtime: *spv.Runtime, allocator: std.mem.Allocator, specialization: ?*const vk.SpecializationInfo) VkError!void {
|
||||
const info = specialization orelse return;
|
||||
const entries = info.p_map_entries orelse return;
|
||||
const data = specializationData(info);
|
||||
|
||||
for (entries[0..info.map_entry_count]) |entry| {
|
||||
runtime.addSpecializationInfo(
|
||||
allocator,
|
||||
.{
|
||||
.id = @intCast(entry.constant_id),
|
||||
.offset = @intCast(entry.offset),
|
||||
.size = @intCast(entry.size),
|
||||
},
|
||||
data,
|
||||
) catch return VkError.OutOfDeviceMemory;
|
||||
}
|
||||
}
|
||||
|
||||
fn cloneSpecs(allocator: std.mem.Allocator, specialization: ?*const vk.SpecializationInfo) VkError![]SpecConstant {
|
||||
const info = specialization orelse return &.{};
|
||||
const entries = info.p_map_entries orelse return &.{};
|
||||
if (info.map_entry_count == 0) return &.{};
|
||||
|
||||
const data = specializationData(info);
|
||||
const specs = allocator.alloc(SpecConstant, info.map_entry_count) catch return VkError.OutOfDeviceMemory;
|
||||
var initialized: usize = 0;
|
||||
errdefer {
|
||||
for (specs[0..initialized]) |spec| {
|
||||
allocator.free(spec.data);
|
||||
}
|
||||
if (specs.len != 0) {
|
||||
allocator.free(specs);
|
||||
}
|
||||
}
|
||||
|
||||
for (specs, entries[0..info.map_entry_count]) |*spec, entry| {
|
||||
spec.* = .{
|
||||
.id = entry.constant_id,
|
||||
.data = allocator.dupe(u8, data[entry.offset .. entry.offset + entry.size]) catch return VkError.OutOfDeviceMemory,
|
||||
};
|
||||
initialized += 1;
|
||||
}
|
||||
|
||||
return specs;
|
||||
}
|
||||
|
||||
fn specsEqual(specs: []const SpecConstant, specialization: ?*const vk.SpecializationInfo) bool {
|
||||
const info = specialization orelse return specs.len == 0;
|
||||
const entries = info.p_map_entries orelse return specs.len == 0;
|
||||
if (specs.len != info.map_entry_count) return false;
|
||||
|
||||
const data = specializationData(info);
|
||||
for (specs) |spec| {
|
||||
var found = false;
|
||||
for (entries[0..info.map_entry_count]) |entry| {
|
||||
if (spec.id != entry.constant_id) continue;
|
||||
if (!std.mem.eql(u8, spec.data, data[entry.offset .. entry.offset + entry.size])) {
|
||||
return false;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn specializationData(info: *const vk.SpecializationInfo) []const u8 {
|
||||
return @as([*]const u8, @ptrCast(@alignCast(info.p_data)))[0..info.data_size];
|
||||
}
|
||||
|
||||
fn appendCacheRecord(interface: *Interface, module: *SoftShaderModule, entry: []const u8, specs: []const SpecConstant) VkError!void {
|
||||
var spec_hasher = std.hash.Wyhash.init(0);
|
||||
for (specs) |spec| {
|
||||
spec_hasher.update(std.mem.asBytes(&spec.id));
|
||||
spec_hasher.update(spec.data);
|
||||
}
|
||||
|
||||
const record: CacheRecord = .{
|
||||
.magic = "APESOFTC".*,
|
||||
.version = 1,
|
||||
.code_hash = std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(module.module.code)),
|
||||
.entry_hash = std.hash.Wyhash.hash(0, entry),
|
||||
.spec_hash = spec_hasher.final(),
|
||||
};
|
||||
|
||||
try interface.appendPayload(std.mem.asBytes(&record));
|
||||
}
|
||||
Reference in New Issue
Block a user