hal/vk: pipeline creation

This commit is contained in:
Dzmitry Malyshau 2021-06-15 01:24:25 -04:00
parent 9d85602349
commit 00de15990e
7 changed files with 631 additions and 22 deletions

View File

@ -60,7 +60,7 @@ impl<A: hal::Api> CommandEncoder<A> {
fn open(&mut self) -> &mut A::CommandEncoder {
if !self.is_open {
self.is_open = true;
let label = self.label.as_ref().map(|s| s.as_str());
let label = self.label.as_deref();
unsafe { self.raw.begin_encoding(label).unwrap() };
}
&mut self.raw

View File

@ -592,8 +592,12 @@ impl<A: hal::Api> Example<A> {
}
}
#[cfg(feature = "metal")]
#[cfg(all(feature = "metal"))]
type Api = hal::api::Metal;
#[cfg(all(feature = "vulkan", not(feature = "metal")))]
type Api = hal::api::Vulkan;
#[cfg(all(not(feature = "vulkan"), not(feature = "metal")))]
type Api = hal::api::Empty;
fn main() {
let event_loop = winit::event_loop::EventLoop::new();

View File

@ -756,6 +756,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
downlevel_flags: self.downlevel_flags,
private_caps: self.private_caps.clone(),
timestamp_period: self.phd_capabilities.properties.limits.timestamp_period,
render_passes: Mutex::new(Default::default()),
}),
mem_allocator: Mutex::new(mem_allocator),
desc_allocator: Mutex::new(desc_allocator),
@ -767,6 +768,9 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
unsafe fn close(&self, device: super::Device) {
for &raw in device.shared.render_passes.lock().values() {
device.shared.raw.destroy_render_pass(raw, None);
}
device.shared.raw.destroy_device(None);
}

View File

@ -139,7 +139,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn begin_debug_marker(&mut self, group_label: &str) {}
unsafe fn end_debug_marker(&mut self) {}
unsafe fn set_render_pipeline(&mut self, pipeline: &Resource) {}
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
self.device.raw.cmd_bind_pipeline(
self.active,
vk::PipelineBindPoint::GRAPHICS,
pipeline.raw,
);
}
unsafe fn set_index_buffer<'a>(
&mut self,
@ -213,7 +219,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {}
unsafe fn end_compute_pass(&mut self) {}
unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {}
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
self.device.raw.cmd_bind_pipeline(
self.active,
vk::PipelineBindPoint::COMPUTE,
pipeline.raw,
);
}
unsafe fn dispatch(&mut self, count: [u32; 3]) {}
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {}

View File

@ -110,6 +110,23 @@ impl super::PrivateCapabilities {
}
}
pub fn derive_image_layout(usage: crate::TextureUse) -> vk::ImageLayout {
match usage {
crate::TextureUse::COPY_SRC => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
crate::TextureUse::COPY_DST => vk::ImageLayout::TRANSFER_DST_OPTIMAL,
crate::TextureUse::SAMPLED => vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
crate::TextureUse::COLOR_TARGET => vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
crate::TextureUse::DEPTH_STENCIL_WRITE => vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
_ => {
if usage.contains(crate::TextureUse::DEPTH_STENCIL_READ) {
vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
} else {
vk::ImageLayout::GENERAL
}
}
}
}
pub fn map_texture_usage(usage: crate::TextureUse) -> vk::ImageUsageFlags {
let mut flags = vk::ImageUsageFlags::empty();
if usage.contains(crate::TextureUse::COPY_SRC) {
@ -173,6 +190,46 @@ pub fn map_index_format(index_format: wgt::IndexFormat) -> vk::IndexType {
}
}
pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format {
use wgt::VertexFormat as Vf;
match vertex_format {
Vf::Uint8x2 => vk::Format::R8G8_UINT,
Vf::Uint8x4 => vk::Format::R8G8B8A8_UINT,
Vf::Sint8x2 => vk::Format::R8G8_SINT,
Vf::Sint8x4 => vk::Format::R8G8B8A8_SINT,
Vf::Unorm8x2 => vk::Format::R8G8_UNORM,
Vf::Unorm8x4 => vk::Format::R8G8B8A8_UNORM,
Vf::Snorm8x2 => vk::Format::R8G8_SNORM,
Vf::Snorm8x4 => vk::Format::R8G8B8A8_SNORM,
Vf::Uint16x2 => vk::Format::R16G16_UINT,
Vf::Uint16x4 => vk::Format::R16G16B16A16_UINT,
Vf::Sint16x2 => vk::Format::R16G16_SINT,
Vf::Sint16x4 => vk::Format::R16G16B16A16_SINT,
Vf::Unorm16x2 => vk::Format::R16G16_UNORM,
Vf::Unorm16x4 => vk::Format::R16G16B16A16_UNORM,
Vf::Snorm16x2 => vk::Format::R16G16_SNORM,
Vf::Snorm16x4 => vk::Format::R16G16B16A16_SNORM,
Vf::Float16x2 => vk::Format::R16G16_SFLOAT,
Vf::Float16x4 => vk::Format::R16G16B16A16_SFLOAT,
Vf::Float32 => vk::Format::R32_SFLOAT,
Vf::Float32x2 => vk::Format::R32G32_SFLOAT,
Vf::Float32x3 => vk::Format::R32G32B32_SFLOAT,
Vf::Float32x4 => vk::Format::R32G32B32A32_SFLOAT,
Vf::Uint32 => vk::Format::R32_UINT,
Vf::Uint32x2 => vk::Format::R32G32_UINT,
Vf::Uint32x3 => vk::Format::R32G32B32_UINT,
Vf::Uint32x4 => vk::Format::R32G32B32A32_UINT,
Vf::Sint32 => vk::Format::R32_SINT,
Vf::Sint32x2 => vk::Format::R32G32_SINT,
Vf::Sint32x3 => vk::Format::R32G32B32_SINT,
Vf::Sint32x4 => vk::Format::R32G32B32A32_SINT,
Vf::Float64 => vk::Format::R64_SFLOAT,
Vf::Float64x2 => vk::Format::R64G64_SFLOAT,
Vf::Float64x3 => vk::Format::R64G64B64_SFLOAT,
Vf::Float64x4 => vk::Format::R64G64B64A64_SFLOAT,
}
}
pub fn map_aspects(aspects: crate::FormatAspect) -> vk::ImageAspectFlags {
let mut flags = vk::ImageAspectFlags::empty();
if aspects.contains(crate::FormatAspect::COLOR) {
@ -414,3 +471,93 @@ pub fn map_binding_type(ty: wgt::BindingType) -> vk::DescriptorType {
wgt::BindingType::StorageTexture { .. } => vk::DescriptorType::STORAGE_IMAGE,
}
}
pub fn map_topology(topology: wgt::PrimitiveTopology) -> vk::PrimitiveTopology {
use wgt::PrimitiveTopology as Pt;
match topology {
Pt::PointList => vk::PrimitiveTopology::POINT_LIST,
Pt::LineList => vk::PrimitiveTopology::LINE_LIST,
Pt::LineStrip => vk::PrimitiveTopology::LINE_STRIP,
Pt::TriangleList => vk::PrimitiveTopology::TRIANGLE_LIST,
Pt::TriangleStrip => vk::PrimitiveTopology::TRIANGLE_STRIP,
}
}
pub fn map_front_face(front_face: wgt::FrontFace) -> vk::FrontFace {
match front_face {
wgt::FrontFace::Cw => vk::FrontFace::CLOCKWISE,
wgt::FrontFace::Ccw => vk::FrontFace::COUNTER_CLOCKWISE,
}
}
pub fn map_cull_face(face: wgt::Face) -> vk::CullModeFlags {
match face {
wgt::Face::Front => vk::CullModeFlags::FRONT,
wgt::Face::Back => vk::CullModeFlags::BACK,
}
}
pub fn map_stencil_op(op: wgt::StencilOperation) -> vk::StencilOp {
use wgt::StencilOperation as So;
match op {
So::Keep => vk::StencilOp::KEEP,
So::Zero => vk::StencilOp::ZERO,
So::Replace => vk::StencilOp::REPLACE,
So::Invert => vk::StencilOp::INVERT,
So::IncrementClamp => vk::StencilOp::INCREMENT_AND_CLAMP,
So::IncrementWrap => vk::StencilOp::INCREMENT_AND_WRAP,
So::DecrementClamp => vk::StencilOp::DECREMENT_AND_CLAMP,
So::DecrementWrap => vk::StencilOp::DECREMENT_AND_WRAP,
}
}
pub fn map_stencil_face(face: &wgt::StencilFaceState) -> vk::StencilOpState {
vk::StencilOpState {
fail_op: map_stencil_op(face.fail_op),
pass_op: map_stencil_op(face.pass_op),
depth_fail_op: map_stencil_op(face.depth_fail_op),
compare_op: map_comparison(face.compare),
compare_mask: !0,
write_mask: !0,
reference: 0,
}
}
fn map_blend_factor(factor: wgt::BlendFactor) -> vk::BlendFactor {
use wgt::BlendFactor as Bf;
match factor {
Bf::Zero => vk::BlendFactor::ZERO,
Bf::One => vk::BlendFactor::ONE,
Bf::Src => vk::BlendFactor::SRC_COLOR,
Bf::OneMinusSrc => vk::BlendFactor::ONE_MINUS_SRC_COLOR,
Bf::SrcAlpha => vk::BlendFactor::SRC_ALPHA,
Bf::OneMinusSrcAlpha => vk::BlendFactor::ONE_MINUS_SRC_ALPHA,
Bf::Dst => vk::BlendFactor::DST_COLOR,
Bf::OneMinusDst => vk::BlendFactor::ONE_MINUS_DST_COLOR,
Bf::DstAlpha => vk::BlendFactor::DST_ALPHA,
Bf::OneMinusDstAlpha => vk::BlendFactor::ONE_MINUS_DST_ALPHA,
Bf::SrcAlphaSaturated => vk::BlendFactor::SRC_ALPHA_SATURATE,
Bf::Constant => vk::BlendFactor::CONSTANT_COLOR,
Bf::OneMinusConstant => vk::BlendFactor::ONE_MINUS_CONSTANT_COLOR,
}
}
fn map_blend_op(operation: wgt::BlendOperation) -> vk::BlendOp {
use wgt::BlendOperation as Bo;
match operation {
Bo::Add => vk::BlendOp::ADD,
Bo::Subtract => vk::BlendOp::SUBTRACT,
Bo::ReverseSubtract => vk::BlendOp::REVERSE_SUBTRACT,
Bo::Min => vk::BlendOp::MIN,
Bo::Max => vk::BlendOp::MAX,
}
}
pub fn map_blend_component(
component: &wgt::BlendComponent,
) -> (vk::BlendOp, vk::BlendFactor, vk::BlendFactor) {
let op = map_blend_op(component.operation);
let src = map_blend_factor(component.src_factor);
let dst = map_blend_factor(component.dst_factor);
(op, src, dst)
}

View File

@ -5,7 +5,7 @@ use ash::{extensions::khr, version::DeviceV1_0, vk};
use inplace_it::inplace_or_alloc_from_iter;
use parking_lot::Mutex;
use std::{ptr, sync::Arc};
use std::{collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
impl super::DeviceShared {
unsafe fn set_object_name(
@ -53,6 +53,101 @@ impl super::DeviceShared {
.object_name(CStr::from_bytes_with_nul_unchecked(name_bytes)),
);
}
pub fn make_render_pass(
&self,
key: super::RenderPassKey,
) -> Result<vk::RenderPass, crate::DeviceError> {
Ok(match self.render_passes.lock().entry(key) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
let mut vk_attachments = Vec::new();
let mut color_refs = Vec::with_capacity(e.key().colors.len());
let mut resolve_refs = Vec::with_capacity(color_refs.capacity());
let mut ds_ref = None;
let samples = vk::SampleCountFlags::from_raw(e.key().sample_count);
for cat in e.key().colors.iter() {
color_refs.push(vk::AttachmentReference {
attachment: vk_attachments.len() as u32,
layout: cat.base.layout_in,
});
vk_attachments.push({
let (load_op, store_op) = conv::map_attachment_ops(cat.base.ops);
vk::AttachmentDescription::builder()
.format(cat.base.format)
.samples(samples)
.load_op(load_op)
.store_op(store_op)
.initial_layout(cat.base.layout_pre)
.final_layout(cat.base.layout_post)
.build()
});
let at_ref = if let Some(ref rat) = cat.resolve {
let at_ref = vk::AttachmentReference {
attachment: vk_attachments.len() as u32,
layout: rat.layout_in,
};
let (load_op, store_op) = conv::map_attachment_ops(rat.ops);
let vk_attachment = vk::AttachmentDescription::builder()
.format(rat.format)
.samples(vk::SampleCountFlags::TYPE_1)
.load_op(load_op)
.store_op(store_op)
.initial_layout(rat.layout_pre)
.final_layout(rat.layout_post)
.build();
vk_attachments.push(vk_attachment);
at_ref
} else {
vk::AttachmentReference {
attachment: vk::ATTACHMENT_UNUSED,
layout: vk::ImageLayout::UNDEFINED,
}
};
resolve_refs.push(at_ref);
}
if let Some(ref ds) = e.key().depth_stencil {
ds_ref = Some(vk::AttachmentReference {
attachment: vk_attachments.len() as u32,
layout: ds.base.layout_in,
});
let (load_op, store_op) = conv::map_attachment_ops(ds.base.ops);
let (stencil_load_op, stencil_store_op) =
conv::map_attachment_ops(ds.stencil_ops);
let vk_attachment = vk::AttachmentDescription::builder()
.format(ds.base.format)
.samples(samples)
.load_op(load_op)
.store_op(store_op)
.initial_layout(ds.base.layout_pre)
.final_layout(ds.base.layout_post)
.build();
vk_attachments.push(vk_attachment);
}
let vk_subpasses = [{
let mut vk_subpass = vk::SubpassDescription::builder()
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.color_attachments(&color_refs)
.resolve_attachments(&resolve_refs);
if let Some(ref reference) = ds_ref {
vk_subpass = vk_subpass.depth_stencil_attachment(reference)
}
vk_subpass.build()
}];
let vk_info = vk::RenderPassCreateInfo::builder()
.attachments(&vk_attachments)
.subpasses(&vk_subpasses);
let raw = unsafe { self.raw.create_render_pass(&vk_info, None)? };
*e.insert(raw)
}
})
}
}
impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
@ -636,8 +731,17 @@ impl crate::Device<super::Api> for super::Device {
desc: &crate::BindGroupLayoutDescriptor,
) -> Result<super::BindGroupLayout, crate::DeviceError> {
let mut desc_count = gpu_descriptor::DescriptorTotalCount::default();
let mut types = Vec::new();
for entry in desc.entries {
let count = entry.count.map_or(1, |c| c.get());
if entry.binding as usize > types.len() {
types.resize(
entry.binding as usize + 1,
vk::DescriptorType::INPUT_ATTACHMENT,
);
}
types[entry.binding as usize] = conv::map_binding_type(entry.ty);
match entry.ty {
wgt::BindingType::Buffer {
ty,
@ -677,7 +781,7 @@ impl crate::Device<super::Api> for super::Device {
.iter()
.map(|entry| vk::DescriptorSetLayoutBinding {
binding: entry.binding,
descriptor_type: conv::map_binding_type(entry.ty),
descriptor_type: types[entry.binding as usize],
descriptor_count: entry.count.map_or(1, |c| c.get()),
stage_flags: conv::map_shader_stage(entry.visibility),
p_immutable_samplers: ptr::null(),
@ -698,7 +802,11 @@ impl crate::Device<super::Api> for super::Device {
.set_object_name(vk::ObjectType::DESCRIPTOR_SET_LAYOUT, raw, label);
}
Ok(super::BindGroupLayout { raw, desc_count })
Ok(super::BindGroupLayout {
raw,
desc_count,
types,
})
}
unsafe fn destroy_bind_group_layout(&self, bg_layout: super::BindGroupLayout) {
self.shared
@ -757,9 +865,57 @@ impl crate::Device<super::Api> for super::Device {
&desc.layout.desc_count,
1,
)?;
Ok(super::BindGroup {
raw: vk_sets.pop().unwrap(),
})
let set = vk_sets.pop().unwrap();
let mut writes = Vec::with_capacity(desc.entries.len());
let mut buffer_infos = Vec::with_capacity(desc.buffers.len());
let mut sampler_infos = Vec::with_capacity(desc.samplers.len());
let mut image_infos = Vec::with_capacity(desc.textures.len());
for entry in desc.entries {
let ty = desc.layout.types[entry.binding as usize];
let mut write = vk::WriteDescriptorSet::builder()
.dst_set(*set.raw())
.dst_binding(entry.binding)
.descriptor_type(ty);
write = match ty {
vk::DescriptorType::SAMPLER => {
let index = sampler_infos.len();
let binding = desc.samplers[index];
let info = vk::DescriptorImageInfo::builder()
.sampler(binding.raw)
.build();
sampler_infos.push(info);
write.image_info(&sampler_infos[index..])
}
vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => {
let index = image_infos.len();
let binding = &desc.textures[index];
let layout = conv::derive_image_layout(binding.usage);
let info = vk::DescriptorImageInfo::builder()
.image_view(binding.view.raw)
.image_layout(layout)
.build();
image_infos.push(info);
write.image_info(&image_infos[index..])
}
_ => {
let index = buffer_infos.len();
let binding = &desc.buffers[index];
let mut info = vk::DescriptorBufferInfo::builder()
.buffer(binding.buffer.raw)
.offset(binding.offset);
if let Some(size) = binding.size {
info = info.range(size.get());
}
buffer_infos.push(info.build());
write.buffer_info(&buffer_infos[index..])
}
};
writes.push(write.build());
}
self.shared.raw.update_descriptor_sets(&writes, &[]);
Ok(super::BindGroup { raw: set })
}
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
self.desc_allocator
@ -771,24 +927,251 @@ impl crate::Device<super::Api> for super::Device {
&self,
desc: &crate::ShaderModuleDescriptor,
shader: crate::NagaShader,
) -> Result<Resource, crate::ShaderError> {
Ok(Resource)
) -> Result<super::ShaderModule, crate::ShaderError> {
let spv = naga::back::spv::write_vec(&shader.module, &shader.info, &self.naga_options)
.map_err(|e| crate::ShaderError::Compilation(format!("{}", e)))?;
let vk_info = vk::ShaderModuleCreateInfo::builder()
.flags(vk::ShaderModuleCreateFlags::empty())
.code(&spv);
let raw = self
.shared
.raw
.create_shader_module(&vk_info, None)
.map_err(crate::DeviceError::from)?;
Ok(super::ShaderModule { raw })
}
unsafe fn destroy_shader_module(&self, module: Resource) {}
unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
let _ = self.shared.raw.destroy_shader_module(module.raw, None);
}
unsafe fn create_render_pipeline(
&self,
desc: &crate::RenderPipelineDescriptor<super::Api>,
) -> Result<Resource, crate::PipelineError> {
Ok(Resource)
) -> Result<super::RenderPipeline, crate::PipelineError> {
let dynamic_states = [
vk::DynamicState::VIEWPORT,
vk::DynamicState::SCISSOR,
vk::DynamicState::BLEND_CONSTANTS,
vk::DynamicState::STENCIL_REFERENCE,
];
let mut compatible_rp_key = super::RenderPassKey {
sample_count: desc.multisample.count,
..Default::default()
};
let mut stages = ArrayVec::<[_; 2]>::new();
let mut vertex_buffers = Vec::with_capacity(desc.vertex_buffers.len());
let mut vertex_attributes = Vec::new();
for (i, vb) in desc.vertex_buffers.iter().enumerate() {
vertex_buffers.push(vk::VertexInputBindingDescription {
binding: i as u32,
stride: vb.array_stride as u32,
input_rate: match vb.step_mode {
wgt::InputStepMode::Vertex => vk::VertexInputRate::VERTEX,
wgt::InputStepMode::Instance => vk::VertexInputRate::INSTANCE,
},
});
for at in vb.attributes {
vertex_attributes.push(vk::VertexInputAttributeDescription {
location: at.shader_location,
binding: i as u32,
format: conv::map_vertex_format(at.format),
offset: at.offset as u32,
});
}
}
let vk_vertex_input = vk::PipelineVertexInputStateCreateInfo::builder()
.vertex_binding_descriptions(&vertex_buffers)
.vertex_attribute_descriptions(&vertex_attributes)
.build();
let vk_input_assembly = vk::PipelineInputAssemblyStateCreateInfo::builder()
.topology(conv::map_topology(desc.primitive.topology))
.primitive_restart_enable(desc.primitive.strip_index_format.is_some())
.build();
let vs_entry_point;
{
let stage = &desc.vertex_stage;
vs_entry_point = CString::new(stage.entry_point).unwrap();
stages.push(
vk::PipelineShaderStageCreateInfo::builder()
.stage(vk::ShaderStageFlags::VERTEX)
.module(stage.module.raw)
.name(&vs_entry_point)
.build(),
);
}
let fs_entry_point;
if let Some(ref stage) = desc.fragment_stage {
fs_entry_point = CString::new(stage.entry_point).unwrap();
stages.push(
vk::PipelineShaderStageCreateInfo::builder()
.stage(vk::ShaderStageFlags::FRAGMENT)
.module(stage.module.raw)
.name(&fs_entry_point)
.build(),
);
}
let mut vk_rasterization = vk::PipelineRasterizationStateCreateInfo::builder()
.depth_clamp_enable(desc.primitive.clamp_depth)
.polygon_mode(vk::PolygonMode::FILL)
.front_face(conv::map_front_face(desc.primitive.front_face));
if let Some(face) = desc.primitive.cull_mode {
vk_rasterization = vk_rasterization.cull_mode(conv::map_cull_face(face))
}
let mut vk_depth_stencil = vk::PipelineDepthStencilStateCreateInfo::builder();
if let Some(ref ds) = desc.depth_stencil {
let vk_format = self.shared.private_caps.map_texture_format(ds.format);
compatible_rp_key.depth_stencil = Some(super::DepthStencilAttachmentKey {
base: super::AttachmentKey::compatible(vk_format),
stencil_ops: crate::AttachmentOp::empty(),
});
if ds.is_depth_enabled() {
vk_depth_stencil = vk_depth_stencil
.depth_test_enable(true)
.depth_write_enable(ds.depth_write_enabled)
.depth_compare_op(conv::map_comparison(ds.depth_compare));
}
if ds.stencil.is_enabled() {
let front = conv::map_stencil_face(&ds.stencil.front);
let back = conv::map_stencil_face(&ds.stencil.back);
vk_depth_stencil = vk_depth_stencil
.stencil_test_enable(true)
.front(front)
.back(back);
}
if ds.bias.is_enabled() {
vk_rasterization = vk_rasterization
.depth_bias_enable(true)
.depth_bias_constant_factor(ds.bias.constant as f32)
.depth_bias_clamp(ds.bias.clamp)
.depth_bias_slope_factor(ds.bias.slope_scale);
}
}
let vk_viewport = vk::PipelineViewportStateCreateInfo::builder()
.flags(vk::PipelineViewportStateCreateFlags::empty())
.scissor_count(1)
.viewport_count(1)
.build();
let vk_sample_mask = [
desc.multisample.mask as u32,
(desc.multisample.mask >> 32) as u32,
];
let vk_multisample = vk::PipelineMultisampleStateCreateInfo::builder()
.rasterization_samples(vk::SampleCountFlags::from_raw(desc.multisample.count))
.alpha_to_coverage_enable(desc.multisample.alpha_to_coverage_enabled)
.sample_mask(&vk_sample_mask)
.build();
let mut vk_attachments = Vec::with_capacity(desc.color_targets.len());
for cat in desc.color_targets {
let vk_format = self.shared.private_caps.map_texture_format(cat.format);
compatible_rp_key.colors.push(super::ColorAttachmentKey {
base: super::AttachmentKey::compatible(vk_format),
resolve: None,
});
let mut vk_attachment = vk::PipelineColorBlendAttachmentState::builder()
.color_write_mask(vk::ColorComponentFlags::from_raw(cat.write_mask.bits()));
if let Some(ref blend) = cat.blend {
let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color);
let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha);
vk_attachment = vk_attachment
.color_blend_op(color_op)
.src_color_blend_factor(color_src)
.dst_color_blend_factor(color_dst)
.alpha_blend_op(alpha_op)
.src_alpha_blend_factor(color_src)
.dst_alpha_blend_factor(color_dst);
}
vk_attachments.push(vk_attachment.build());
}
let vk_color_blend = vk::PipelineColorBlendStateCreateInfo::builder()
.attachments(&vk_attachments)
.build();
let vk_dynamic_state = vk::PipelineDynamicStateCreateInfo::builder()
.dynamic_states(&dynamic_states)
.build();
let raw_pass = self
.shared
.make_render_pass(compatible_rp_key)
.map_err(crate::DeviceError::from)?;
let vk_infos = [{
vk::GraphicsPipelineCreateInfo::builder()
.layout(desc.layout.raw)
.stages(&stages)
.vertex_input_state(&vk_vertex_input)
.input_assembly_state(&vk_input_assembly)
.rasterization_state(&vk_rasterization)
.viewport_state(&vk_viewport)
.multisample_state(&vk_multisample)
.depth_stencil_state(&vk_depth_stencil)
.color_blend_state(&vk_color_blend)
.dynamic_state(&vk_dynamic_state)
.render_pass(raw_pass)
.build()
}];
let mut raw_vec = self
.shared
.raw
.create_graphics_pipelines(vk::PipelineCache::null(), &vk_infos, None)
.map_err(|(_, e)| crate::DeviceError::from(e))?;
Ok(super::RenderPipeline {
raw: raw_vec.pop().unwrap(),
})
}
unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
self.shared.raw.destroy_pipeline(pipeline.raw, None);
}
unsafe fn create_compute_pipeline(
&self,
desc: &crate::ComputePipelineDescriptor<super::Api>,
) -> Result<Resource, crate::PipelineError> {
Ok(Resource)
) -> Result<super::ComputePipeline, crate::PipelineError> {
let cs_entry_point = CString::new(desc.stage.entry_point).unwrap();
let vk_stage = vk::PipelineShaderStageCreateInfo::builder()
.stage(vk::ShaderStageFlags::COMPUTE)
.module(desc.stage.module.raw)
.name(&cs_entry_point)
.build();
let vk_infos = [{
vk::ComputePipelineCreateInfo::builder()
.layout(desc.layout.raw)
.stage(vk_stage)
.build()
}];
let mut raw_vec = self
.shared
.raw
.create_compute_pipelines(vk::PipelineCache::null(), &vk_infos, None)
.map_err(|(_, e)| crate::DeviceError::from(e))?;
Ok(super::ComputePipeline {
raw: raw_vec.pop().unwrap(),
})
}
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
self.shared.raw.destroy_pipeline(pipeline.raw, None);
}
unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
unsafe fn create_query_set(&self, desc: &wgt::QuerySetDescriptor) -> DeviceResult<Resource> {
Ok(Resource)

View File

@ -8,6 +8,7 @@ mod instance;
use std::{borrow::Borrow, ffi::CStr, sync::Arc};
use arrayvec::ArrayVec;
use ash::{
extensions::{ext, khr},
vk,
@ -44,9 +45,9 @@ impl crate::Api for Api {
type BindGroupLayout = BindGroupLayout;
type BindGroup = BindGroup;
type PipelineLayout = PipelineLayout;
type ShaderModule = Resource;
type RenderPipeline = Resource;
type ComputePipeline = Resource;
type ShaderModule = ShaderModule;
type RenderPipeline = RenderPipeline;
type ComputePipeline = ComputePipeline;
}
struct DebugUtils {
@ -133,6 +134,47 @@ struct PrivateCapabilities {
texture_d24_s8: bool,
}
#[derive(Clone, Eq, Hash, PartialEq)]
struct AttachmentKey {
format: vk::Format,
layout_pre: vk::ImageLayout,
layout_in: vk::ImageLayout,
layout_post: vk::ImageLayout,
ops: crate::AttachmentOp,
}
impl AttachmentKey {
/// Returns an attachment key for a compatible attachment.
fn compatible(format: vk::Format) -> Self {
Self {
format,
layout_pre: vk::ImageLayout::UNDEFINED,
layout_in: vk::ImageLayout::UNDEFINED,
layout_post: vk::ImageLayout::UNDEFINED,
ops: crate::AttachmentOp::empty(),
}
}
}
#[derive(Clone, Eq, Hash, PartialEq)]
struct ColorAttachmentKey {
base: AttachmentKey,
resolve: Option<AttachmentKey>,
}
#[derive(Clone, Eq, Hash, PartialEq)]
struct DepthStencilAttachmentKey {
base: AttachmentKey,
stencil_ops: crate::AttachmentOp,
}
#[derive(Clone, Eq, Default, Hash, PartialEq)]
struct RenderPassKey {
colors: ArrayVec<[ColorAttachmentKey; crate::MAX_COLOR_TARGETS]>,
depth_stencil: Option<DepthStencilAttachmentKey>,
sample_count: u32,
}
struct DeviceShared {
raw: ash::Device,
instance: Arc<InstanceShared>,
@ -142,6 +184,7 @@ struct DeviceShared {
timestamp_period: f32,
downlevel_flags: wgt::DownlevelFlags,
private_caps: PrivateCapabilities,
render_passes: Mutex<fxhash::FxHashMap<RenderPassKey, vk::RenderPass>>,
}
pub struct Device {
@ -187,6 +230,7 @@ pub struct Sampler {
pub struct BindGroupLayout {
raw: vk::DescriptorSetLayout,
desc_count: gpu_descriptor::DescriptorTotalCount,
types: Vec<vk::DescriptorType>,
}
#[derive(Debug)]
@ -211,6 +255,21 @@ pub struct CommandBuffer {
raw: vk::CommandBuffer,
}
#[derive(Debug)]
pub struct ShaderModule {
raw: vk::ShaderModule,
}
#[derive(Debug)]
pub struct RenderPipeline {
raw: vk::Pipeline,
}
#[derive(Debug)]
pub struct ComputePipeline {
raw: vk::Pipeline,
}
impl crate::Queue<Api> for Queue {
unsafe fn submit(
&mut self,