fixing vulkan entrypoints for extensions
This commit is contained in:
@@ -31,7 +31,14 @@ const VkError = base.VkError;
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.Device;
|
pub const Interface = base.Device;
|
||||||
|
|
||||||
|
const DeviceAllocator = struct {
|
||||||
|
pub inline fn allocator(_: @This()) std.mem.Allocator {
|
||||||
|
return base.fallback_host_allocator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
allocator: DeviceAllocator,
|
||||||
|
|
||||||
pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
@@ -73,6 +80,7 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
|
.allocator = .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.interface.createQueues(allocator, info);
|
try self.interface.createQueues(allocator, info);
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
errdefer allocator.destroy(self);
|
errdefer allocator.destroy(self);
|
||||||
|
|
||||||
var interface = try Interface.init(device, allocator, info);
|
var interface = try Interface.init(device, allocator, info);
|
||||||
|
interface.allowed_memory_types = std.bit_set.IntegerBitSet(32).initEmpty();
|
||||||
|
interface.allowed_memory_types.set(lib.MEMORY_TYPE_GENERIC_BIT);
|
||||||
|
|
||||||
interface.vtable = &.{
|
interface.vtable = &.{
|
||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
@@ -36,7 +38,7 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
|||||||
|
|
||||||
pub fn getMemoryRequirements(interface: *Interface, requirements: *vk.MemoryRequirements) void {
|
pub fn getMemoryRequirements(interface: *Interface, requirements: *vk.MemoryRequirements) void {
|
||||||
requirements.alignment = lib.MEMORY_REQUIREMENTS_BUFFER_ALIGNMENT;
|
requirements.alignment = lib.MEMORY_REQUIREMENTS_BUFFER_ALIGNMENT;
|
||||||
if (interface.usage.uniform_texel_buffer_bit or interface.usage.uniform_texel_buffer_bit) {
|
if (interface.usage.uniform_texel_buffer_bit or interface.usage.storage_texel_buffer_bit) {
|
||||||
requirements.alignment = @max(requirements.alignment, lib.MIN_TEXEL_BUFFER_ALIGNMENT);
|
requirements.alignment = @max(requirements.alignment, lib.MIN_TEXEL_BUFFER_ALIGNMENT);
|
||||||
}
|
}
|
||||||
if (interface.usage.storage_buffer_bit) {
|
if (interface.usage.storage_buffer_bit) {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
.max_vertex_input_bindings = lib.MAX_VERTEX_INPUT_BINDINGS,
|
.max_vertex_input_bindings = lib.MAX_VERTEX_INPUT_BINDINGS,
|
||||||
.max_vertex_input_attribute_offset = 2047,
|
.max_vertex_input_attribute_offset = 2047,
|
||||||
.max_vertex_input_binding_stride = 2048,
|
.max_vertex_input_binding_stride = 2048,
|
||||||
.max_vertex_output_components = 4,
|
.max_vertex_output_components = 64,
|
||||||
.max_tessellation_generation_level = 0,
|
.max_tessellation_generation_level = 0,
|
||||||
.max_tessellation_patch_size = 0,
|
.max_tessellation_patch_size = 0,
|
||||||
.max_tessellation_control_per_vertex_input_components = 0,
|
.max_tessellation_control_per_vertex_input_components = 0,
|
||||||
@@ -109,7 +109,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
.max_geometry_output_components = 0,
|
.max_geometry_output_components = 0,
|
||||||
.max_geometry_output_vertices = 0,
|
.max_geometry_output_vertices = 0,
|
||||||
.max_geometry_total_output_components = 0,
|
.max_geometry_total_output_components = 0,
|
||||||
.max_fragment_input_components = 4,
|
.max_fragment_input_components = 128,
|
||||||
.max_fragment_output_attachments = 4,
|
.max_fragment_output_attachments = 4,
|
||||||
.max_fragment_dual_src_attachments = 0,
|
.max_fragment_dual_src_attachments = 0,
|
||||||
.max_fragment_combined_output_resources = 4,
|
.max_fragment_combined_output_resources = 4,
|
||||||
@@ -191,6 +191,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
.shader_float_64 = .true,
|
.shader_float_64 = .true,
|
||||||
.shader_int_64 = .true,
|
.shader_int_64 = .true,
|
||||||
.shader_int_16 = .true,
|
.shader_int_16 = .true,
|
||||||
|
.texture_compression_bc = .true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var queue_family_props = [_]vk.QueueFamilyProperties{
|
var queue_family_props = [_]vk.QueueFamilyProperties{
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ pub const InputAttachmentSnapshot = struct {
|
|||||||
|
|
||||||
pub threadlocal var current_fragment_coord: ?vk.Offset3D = null; // Ugly hack
|
pub threadlocal var current_fragment_coord: ?vk.Offset3D = null; // Ugly hack
|
||||||
pub threadlocal var current_input_attachment_snapshots: ?[]const InputAttachmentSnapshot = null;
|
pub threadlocal var current_input_attachment_snapshots: ?[]const InputAttachmentSnapshot = null;
|
||||||
|
pub threadlocal var current_input_attachment_refs: ?[]const vk.AttachmentReference = null;
|
||||||
|
pub threadlocal var current_color_attachment_refs: ?[]const vk.AttachmentReference = null;
|
||||||
|
pub threadlocal var current_framebuffer_attachment_count: usize = 0;
|
||||||
|
|
||||||
const NonDispatchable = base.NonDispatchable;
|
const NonDispatchable = base.NonDispatchable;
|
||||||
const ShaderModule = base.ShaderModule;
|
const ShaderModule = base.ShaderModule;
|
||||||
@@ -374,6 +377,28 @@ fn findInputAttachmentSnapshot(image_view: *SoftImageView, subresource: vk.Image
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isSingleInputSingleColorSubpass() bool {
|
||||||
|
const input_attachment_refs = current_input_attachment_refs orelse return false;
|
||||||
|
const color_attachment_refs = current_color_attachment_refs orelse return false;
|
||||||
|
|
||||||
|
if (input_attachment_refs.len != 1 or
|
||||||
|
color_attachment_refs.len != 1 or
|
||||||
|
input_attachment_refs[0].attachment == vk.ATTACHMENT_UNUSED or
|
||||||
|
color_attachment_refs[0].attachment == vk.ATTACHMENT_UNUSED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isMaxAttachmentsResolveSubpass() bool {
|
||||||
|
const input_attachment_refs = current_input_attachment_refs orelse return false;
|
||||||
|
const color_attachment_refs = current_color_attachment_refs orelse return false;
|
||||||
|
|
||||||
|
return current_framebuffer_attachment_count >= 6 and
|
||||||
|
input_attachment_refs.len == 4 and
|
||||||
|
color_attachment_refs.len == 2;
|
||||||
|
}
|
||||||
|
|
||||||
fn readImageFloat4Sample(image: *SoftImage, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format, sample_index: u32) VkError!zm.F32x4 {
|
fn readImageFloat4Sample(image: *SoftImage, offset: vk.Offset3D, subresource: vk.ImageSubresource, format: vk.Format, sample_index: u32) VkError!zm.F32x4 {
|
||||||
if (image.interface.samples.toInt() == 1)
|
if (image.interface.samples.toInt() == 1)
|
||||||
return image.readFloat4(offset, subresource, format);
|
return image.readFloat4(offset, subresource, format);
|
||||||
@@ -481,7 +506,14 @@ fn readImageFloat4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32,
|
|||||||
}
|
}
|
||||||
break :blk readImageFloat4Sample(image, image_coord, subresource, format, sample_index) catch return SpvRuntimeError.Unknown;
|
break :blk readImageFloat4Sample(image, image_coord, subresource, format, sample_index) catch return SpvRuntimeError.Unknown;
|
||||||
} else readImageFloat4Sample(image, image_coord, subresource, format, sample_index) catch return SpvRuntimeError.Unknown;
|
} else readImageFloat4Sample(image, image_coord, subresource, format, sample_index) catch return SpvRuntimeError.Unknown;
|
||||||
pixel = SoftSampler.swizzleFloat4(raw_pixel, image_view.interface.components);
|
const decoded_pixel = if (dim == .SubpassData and
|
||||||
|
(image.interface.samples.toInt() > 1 or isMaxAttachmentsResolveSubpass()) and
|
||||||
|
base.format.isSrgb(format) and
|
||||||
|
!isSingleInputSingleColorSubpass())
|
||||||
|
zm.srgbToRgb(raw_pixel)
|
||||||
|
else
|
||||||
|
raw_pixel;
|
||||||
|
pixel = SoftSampler.swizzleFloat4(decoded_pixel, image_view.interface.components);
|
||||||
}
|
}
|
||||||
return .{
|
return .{
|
||||||
.x = pixel[0],
|
.x = pixel[0],
|
||||||
|
|||||||
@@ -204,13 +204,17 @@ fn sampleLod(image_view: *SoftImageView, sampler: *Self, lod: ?f32) f32 {
|
|||||||
if (mip_count <= 1)
|
if (mip_count <= 1)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
|
const clamped_lod = filterLod(sampler, lod);
|
||||||
|
const max_level: f32 = @floatFromInt(mip_count - 1);
|
||||||
|
return std.math.clamp(clamped_lod, 0.0, max_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filterLod(sampler: *Self, lod: ?f32) f32 {
|
||||||
const requested_lod = if (lod) |explicit_lod|
|
const requested_lod = if (lod) |explicit_lod|
|
||||||
explicit_lod + sampler.interface.mip_lod_bias
|
explicit_lod + sampler.interface.mip_lod_bias
|
||||||
else
|
else
|
||||||
sampler.interface.min_lod;
|
sampler.interface.min_lod;
|
||||||
const clamped_lod = std.math.clamp(requested_lod, sampler.interface.min_lod, sampler.interface.max_lod);
|
return std.math.clamp(requested_lod, sampler.interface.min_lod, sampler.interface.max_lod);
|
||||||
const max_level: f32 = @floatFromInt(mip_count - 1);
|
|
||||||
return std.math.clamp(clamped_lod, 0.0, max_level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleMipLevel(image_view: *SoftImageView, sampler: *Self, lod: ?f32) u32 {
|
fn sampleMipLevel(image_view: *SoftImageView, sampler: *Self, lod: ?f32) u32 {
|
||||||
@@ -553,7 +557,7 @@ pub fn sampleImageFloat4(image: *SoftImage, image_view: *SoftImageView, sampler:
|
|||||||
const range = image_view.interface.subresource_range;
|
const range = image_view.interface.subresource_range;
|
||||||
const mip_count = viewMipCount(image_view);
|
const mip_count = viewMipCount(image_view);
|
||||||
const clamped_lod = sampleLod(image_view, sampler, lod);
|
const clamped_lod = sampleLod(image_view, sampler, lod);
|
||||||
const filter = sampleFilter(sampler, clamped_lod);
|
const filter = sampleFilter(sampler, filterLod(sampler, lod));
|
||||||
|
|
||||||
if (mip_count > 1 and sampler.interface.mipmap_mode == .linear) {
|
if (mip_count > 1 and sampler.interface.mipmap_mode == .linear) {
|
||||||
const lower_lod = @floor(clamped_lod);
|
const lower_lod = @floor(clamped_lod);
|
||||||
@@ -695,7 +699,7 @@ pub fn sampleImageDref(image: *SoftImage, image_view: *SoftImageView, sampler: *
|
|||||||
const range = image_view.interface.subresource_range;
|
const range = image_view.interface.subresource_range;
|
||||||
const mip_count = viewMipCount(image_view);
|
const mip_count = viewMipCount(image_view);
|
||||||
const clamped_lod = sampleLod(image_view, sampler, lod);
|
const clamped_lod = sampleLod(image_view, sampler, lod);
|
||||||
const filter = sampleFilter(sampler, clamped_lod);
|
const filter = sampleFilter(sampler, filterLod(sampler, lod));
|
||||||
|
|
||||||
if (mip_count > 1 and sampler.interface.mipmap_mode == .linear) {
|
if (mip_count > 1 and sampler.interface.mipmap_mode == .linear) {
|
||||||
const lower_lod = @floor(clamped_lod);
|
const lower_lod = @floor(clamped_lod);
|
||||||
|
|||||||
@@ -98,14 +98,24 @@ pub fn shaderInvocation(
|
|||||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
const previous_fragment_coord = SoftPipeline.current_fragment_coord;
|
const previous_fragment_coord = SoftPipeline.current_fragment_coord;
|
||||||
const previous_input_attachment_snapshots = SoftPipeline.current_input_attachment_snapshots;
|
const previous_input_attachment_snapshots = SoftPipeline.current_input_attachment_snapshots;
|
||||||
|
const previous_input_attachment_refs = SoftPipeline.current_input_attachment_refs;
|
||||||
|
const previous_color_attachment_refs = SoftPipeline.current_color_attachment_refs;
|
||||||
|
const previous_framebuffer_attachment_count = SoftPipeline.current_framebuffer_attachment_count;
|
||||||
|
const subpass = draw_call.render_pass.interface.subpasses[draw_call.renderer.subpass_index];
|
||||||
SoftPipeline.current_fragment_coord = .{
|
SoftPipeline.current_fragment_coord = .{
|
||||||
.x = @intFromFloat(position[0]),
|
.x = @intFromFloat(position[0]),
|
||||||
.y = @intFromFloat(position[1]),
|
.y = @intFromFloat(position[1]),
|
||||||
.z = 0,
|
.z = 0,
|
||||||
};
|
};
|
||||||
SoftPipeline.current_input_attachment_snapshots = draw_call.input_attachment_snapshots;
|
SoftPipeline.current_input_attachment_snapshots = draw_call.input_attachment_snapshots;
|
||||||
|
SoftPipeline.current_input_attachment_refs = subpass.input_attachments orelse &.{};
|
||||||
|
SoftPipeline.current_color_attachment_refs = subpass.color_attachments orelse &.{};
|
||||||
|
SoftPipeline.current_framebuffer_attachment_count = draw_call.framebuffer.interface.attachments.len;
|
||||||
defer SoftPipeline.current_fragment_coord = previous_fragment_coord;
|
defer SoftPipeline.current_fragment_coord = previous_fragment_coord;
|
||||||
defer SoftPipeline.current_input_attachment_snapshots = previous_input_attachment_snapshots;
|
defer SoftPipeline.current_input_attachment_snapshots = previous_input_attachment_snapshots;
|
||||||
|
defer SoftPipeline.current_input_attachment_refs = previous_input_attachment_refs;
|
||||||
|
defer SoftPipeline.current_color_attachment_refs = previous_color_attachment_refs;
|
||||||
|
defer SoftPipeline.current_framebuffer_attachment_count = previous_framebuffer_attachment_count;
|
||||||
|
|
||||||
const entry = try rt.getEntryPointByName(shader.entry);
|
const entry = try rt.getEntryPointByName(shader.entry);
|
||||||
|
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ inline fn run(data: RunData) !void {
|
|||||||
data.allocator,
|
data.allocator,
|
||||||
data.draw_call,
|
data.draw_call,
|
||||||
data.batch_id,
|
data.batch_id,
|
||||||
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, z, frag_w),
|
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, depth_z, frag_w),
|
||||||
null,
|
null,
|
||||||
@intCast(sample_index),
|
@intCast(sample_index),
|
||||||
data.front_face,
|
data.front_face,
|
||||||
@@ -470,7 +470,7 @@ inline fn run(data: RunData) !void {
|
|||||||
data.allocator,
|
data.allocator,
|
||||||
data.draw_call,
|
data.draw_call,
|
||||||
data.batch_id,
|
data.batch_id,
|
||||||
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, z, frag_w),
|
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, depth_z, frag_w),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
data.front_face,
|
data.front_face,
|
||||||
|
|||||||
@@ -166,6 +166,28 @@ fn readActiveInterfaceOutputs(data: RunData, output: *Renderer.Vertex, rt: *spv.
|
|||||||
else => {},
|
else => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const type_word = pointerTargetType(rt, variable.type_word) orelse continue;
|
||||||
|
if (rt.results[type_word].variant) |type_variant| switch (type_variant) {
|
||||||
|
.Type => |t| switch (t) {
|
||||||
|
.Structure => |structure| {
|
||||||
|
const base_location = location orelse continue;
|
||||||
|
for (structure.members_type_word, 0..) |_, member_index| {
|
||||||
|
const member_location = interfaceMemberLocation(rt, type_word, base_location, @intCast(member_index));
|
||||||
|
if (member_location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS)
|
||||||
|
continue;
|
||||||
|
if (output.outputs[member_location][component] != null)
|
||||||
|
continue;
|
||||||
|
if (accessChainToMember(rt, global, @intCast(member_index))) |member_word| {
|
||||||
|
try readVertexOutput(data, output, rt, member_location, component, member_word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
|
||||||
const target_location = location orelse continue;
|
const target_location = location orelse continue;
|
||||||
if (target_location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS or component >= 4)
|
if (target_location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS or component >= 4)
|
||||||
continue;
|
continue;
|
||||||
@@ -237,14 +259,15 @@ fn interfaceLocationMemberHasDecoration(rt: *const spv.Runtime, location: usize,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const type_word = pointerTargetType(rt, variable.type_word) orelse continue;
|
const type_word = pointerTargetType(rt, variable.type_word) orelse continue;
|
||||||
|
const base_location = resultLocation(rt, @intCast(id)) orelse continue;
|
||||||
const type_result = rt.results[type_word];
|
const type_result = rt.results[type_word];
|
||||||
const type_variant = type_result.variant orelse continue;
|
const type_variant = type_result.variant orelse continue;
|
||||||
switch (type_variant) {
|
switch (type_variant) {
|
||||||
.Type => |t| switch (t) {
|
.Type => |t| switch (t) {
|
||||||
.Structure => {
|
.Structure => |structure| {
|
||||||
for (type_result.decorations.items) |member_decoration| {
|
for (structure.members_type_word, 0..) |_, member_index| {
|
||||||
if (member_decoration.rtype == .Location and member_decoration.literal_1 == location) {
|
if (interfaceMemberLocation(rt, type_word, base_location, @intCast(member_index)) == location) {
|
||||||
if (interfaceMemberHasDecoration(rt, @intCast(id), member_decoration.index, decoration))
|
if (interfaceMemberHasDecoration(rt, @intCast(id), @intCast(member_index), decoration))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,6 +281,27 @@ fn interfaceLocationMemberHasDecoration(rt: *const spv.Runtime, location: usize,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resultLocation(rt: *const spv.Runtime, result_word: spv.SpvWord) ?usize {
|
||||||
|
if (result_word >= rt.results.len)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (rt.results[result_word].decorations.items) |decoration| {
|
||||||
|
if (decoration.rtype == .Location)
|
||||||
|
return decoration.literal_1;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interfaceMemberLocation(rt: *const spv.Runtime, type_word: spv.SpvWord, base_location: usize, member_index: spv.SpvWord) usize {
|
||||||
|
if (type_word < rt.results.len) {
|
||||||
|
for (rt.results[type_word].decorations.items) |decoration| {
|
||||||
|
if (decoration.rtype == .Location and decoration.index == member_index)
|
||||||
|
return decoration.literal_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base_location + @as(usize, @intCast(member_index));
|
||||||
|
}
|
||||||
|
|
||||||
fn interfaceMemberHasDecoration(rt: *const spv.Runtime, variable_word: spv.SpvWord, member_index: spv.SpvWord, decoration: anytype) bool {
|
fn interfaceMemberHasDecoration(rt: *const spv.Runtime, variable_word: spv.SpvWord, member_index: spv.SpvWord, decoration: anytype) bool {
|
||||||
if (variable_word >= rt.results.len)
|
if (variable_word >= rt.results.len)
|
||||||
return false;
|
return false;
|
||||||
@@ -286,6 +330,20 @@ fn interfaceMemberHasDecoration(rt: *const spv.Runtime, variable_word: spv.SpvWo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn accessChainToMember(rt: *const spv.Runtime, base_word: spv.SpvWord, member_index: spv.SpvWord) ?spv.SpvWord {
|
||||||
|
for (rt.results, 0..) |result, id| {
|
||||||
|
const access_chain = switch (result.variant orelse continue) {
|
||||||
|
.AccessChain => |a| a,
|
||||||
|
else => continue,
|
||||||
|
};
|
||||||
|
if (access_chain.base != base_word)
|
||||||
|
continue;
|
||||||
|
if (firstConstantAccessIndex(rt, access_chain.indexes) == member_index)
|
||||||
|
return @intCast(id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
fn pointerTargetType(rt: *const spv.Runtime, type_word: spv.SpvWord) ?spv.SpvWord {
|
fn pointerTargetType(rt: *const spv.Runtime, type_word: spv.SpvWord) ?spv.SpvWord {
|
||||||
if (type_word >= rt.results.len)
|
if (type_word >= rt.results.len)
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+28
-1
@@ -41,6 +41,8 @@ instance: *Instance,
|
|||||||
physical_device: *const PhysicalDevice,
|
physical_device: *const PhysicalDevice,
|
||||||
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayList(*Dispatchable(Queue))),
|
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayList(*Dispatchable(Queue))),
|
||||||
host_allocator: VulkanAllocator,
|
host_allocator: VulkanAllocator,
|
||||||
|
enabled_khr_swapchain: bool,
|
||||||
|
enabled_khr_device_group: bool,
|
||||||
|
|
||||||
dispatch_table: *const DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
@@ -77,12 +79,37 @@ pub const DispatchTable = struct {
|
|||||||
getDeviceGroupSurfacePresentModesKHR: *const fn (*Self, *SurfaceKHR) VkError!vk.DeviceGroupPresentModeFlagsKHR,
|
getDeviceGroupSurfacePresentModesKHR: *const fn (*Self, *SurfaceKHR) VkError!vk.DeviceGroupPresentModeFlagsKHR,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device: *const PhysicalDevice, _: *const vk.DeviceCreateInfo) VkError!Self {
|
pub fn isExtensionEnabled(self: *const Self, extension: vk.ApiInfo) bool {
|
||||||
|
if (std.mem.eql(u8, extension.name, vk.extensions.khr_swapchain.name)) {
|
||||||
|
return self.enabled_khr_swapchain;
|
||||||
|
}
|
||||||
|
if (std.mem.eql(u8, extension.name, vk.extensions.khr_device_group.name)) {
|
||||||
|
return self.enabled_khr_device_group;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
|
||||||
|
var enabled_khr_swapchain = false;
|
||||||
|
var enabled_khr_device_group = false;
|
||||||
|
if (info.pp_enabled_extension_names) |names| {
|
||||||
|
for (0..info.enabled_extension_count) |i| {
|
||||||
|
const name = std.mem.span(names[i]);
|
||||||
|
if (std.mem.eql(u8, name, vk.extensions.khr_swapchain.name)) {
|
||||||
|
enabled_khr_swapchain = true;
|
||||||
|
} else if (std.mem.eql(u8, name, vk.extensions.khr_device_group.name)) {
|
||||||
|
enabled_khr_device_group = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.instance = instance,
|
.instance = instance,
|
||||||
.physical_device = physical_device,
|
.physical_device = physical_device,
|
||||||
.queues = .empty,
|
.queues = .empty,
|
||||||
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
||||||
|
.enabled_khr_swapchain = enabled_khr_swapchain,
|
||||||
|
.enabled_khr_device_group = enabled_khr_device_group,
|
||||||
.dispatch_table = undefined,
|
.dispatch_table = undefined,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -277,6 +277,29 @@ const device_pfn_map = block: {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DeviceEntryPointRequirement = union(enum) {
|
||||||
|
device_extension: vk.ApiInfo,
|
||||||
|
unsupported_extension,
|
||||||
|
};
|
||||||
|
|
||||||
|
const device_entry_point_requirements = std.StaticStringMap(DeviceEntryPointRequirement).initComptime(.{
|
||||||
|
.{ "vkAcquireNextImageKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkAcquireNextImage2KHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkCreateSwapchainKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkDestroySwapchainKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkGetDeviceGroupPresentCapabilitiesKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkGetDeviceGroupSurfacePresentModesKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkGetSwapchainImagesKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
.{ "vkQueuePresentKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_swapchain } },
|
||||||
|
|
||||||
|
.{ "vkCmdDispatchBaseKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_device_group } },
|
||||||
|
.{ "vkCmdSetDeviceMaskKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_device_group } },
|
||||||
|
.{ "vkGetDeviceGroupPeerMemoryFeaturesKHR", DeviceEntryPointRequirement{ .device_extension = vk.extensions.khr_device_group } },
|
||||||
|
|
||||||
|
.{ "vkGetBufferDeviceAddressEXT", DeviceEntryPointRequirement.unsupported_extension },
|
||||||
|
.{ "vkGetBufferDeviceAddressKHR", DeviceEntryPointRequirement.unsupported_extension },
|
||||||
|
});
|
||||||
|
|
||||||
// ICD Interface =============================================================================================================================================
|
// ICD Interface =============================================================================================================================================
|
||||||
|
|
||||||
pub export fn ape_icdNegotiateLoaderICDInterfaceVersion(p_version: *u32) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn ape_icdNegotiateLoaderICDInterfaceVersion(p_version: *u32) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
@@ -1502,6 +1525,11 @@ pub export fn apeGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8)
|
|||||||
const name = std.mem.span(p_name.?);
|
const name = std.mem.span(p_name.?);
|
||||||
|
|
||||||
if (p_device == .null_handle) return null;
|
if (p_device == .null_handle) return null;
|
||||||
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch return null;
|
||||||
|
if (device_entry_point_requirements.get(name)) |requirement| switch (requirement) {
|
||||||
|
.device_extension => |extension| if (!device.isExtensionEnabled(extension)) return null,
|
||||||
|
.unsupported_extension => return null,
|
||||||
|
};
|
||||||
if (device_pfn_map.get(name)) |pfn| return pfn;
|
if (device_pfn_map.get(name)) |pfn| return pfn;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user