use std::{cell, mem, ptr, slice};
use std::os::raw::c_void;
use core::{self, handle as h, pso, state, texture, buffer, mapping};
use core::memory::{self, Bind};
use core::factory::{self as f};
use core::format::ChannelType;
use core::target::Layer;
use vk;
use {command, data, native};
use {Resources as R, SharePointer};
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct MappingGate {
pub pointer: *mut c_void,
pub status: mapping::Status<R>,
}
unsafe impl Send for MappingGate {}
unsafe impl Sync for MappingGate {}
impl mapping::Gate<R> for MappingGate {
unsafe fn set<T>(&self, index: usize, val: T) {
*(self.pointer as *mut T).offset(index as isize) = val;
}
unsafe fn slice<'a, 'b, T>(&'a self, len: usize) -> &'b [T] {
slice::from_raw_parts(self.pointer as *const T, len)
}
unsafe fn mut_slice<'a, 'b, T>(&'a self, len: usize) -> &'b mut [T] {
slice::from_raw_parts_mut(self.pointer as *mut T, len)
}
}
pub struct Factory {
share: SharePointer,
queue_family_index: u32,
mem_video_id: u32,
mem_system_id: u32,
command_pool: vk::CommandPool,
frame_handles: h::Manager<R>,
}
impl Factory {
pub fn new(share: SharePointer, qf_index: u32, mvid: u32, msys: u32) -> Factory {
let com_info = vk::CommandPoolCreateInfo {
sType: vk::STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
pNext: ptr::null(),
flags: vk::COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
queueFamilyIndex: qf_index,
};
let mut com_pool = 0;
assert_eq!(vk::SUCCESS, unsafe {
let (dev, vk) = share.get_device();
vk.CreateCommandPool(dev, &com_info, ptr::null(), &mut com_pool)
});
Factory {
share: share,
queue_family_index: qf_index,
mem_video_id: mvid,
mem_system_id: msys,
command_pool: com_pool,
frame_handles: h::Manager::new(),
}
}
pub fn create_command_buffer(&mut self) -> command::Buffer {
command::Buffer::new(self.command_pool, self.queue_family_index, self.share.clone())
}
fn view_texture(&mut self, htex: &h::RawTexture<R>, desc: texture::ResourceDesc, is_target: bool)
-> Result<native::TextureView, f::ResourceViewError> {
let raw_tex = self.frame_handles.ref_texture(htex);
let td = htex.get_info();
let sub_range = native::SubresourceRange {
aspectMask: data::map_image_aspect(td.format, desc.channel, is_target),
baseMipLevel: desc.min as u32,
levelCount: (desc.max + 1 - desc.min) as u32,
baseArrayLayer: desc.layer.unwrap_or(0) as u32,
layerCount: match desc.layer {
Some(_) => 1,
None => td.kind.get_num_slices().unwrap_or(1) as u32,
}
};
let info = vk::ImageViewCreateInfo {
sType: vk::STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
image: raw_tex.image,
viewType: match data::map_image_view_type(td.kind, desc.layer) {
Ok(vt) => vt,
Err(e) => return Err(f::ResourceViewError::Layer(e)),
},
format: match data::map_format(td.format, desc.channel) {
Some(f) => f,
None => return Err(f::ResourceViewError::Channel(desc.channel)),
},
components: data::map_swizzle(desc.swizzle),
subresourceRange: sub_range.into(),
};
let (dev, vk) = self.share.get_device();
let mut view = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateImageView(dev, &info, ptr::null(), &mut view)
});
Ok(native::TextureView {
image: raw_tex.image,
view: view,
layout: raw_tex.layout.get(), sub_range: sub_range,
})
}
fn view_target(&mut self, htex: &h::RawTexture<R>, channel: ChannelType, layer: Option<Layer>)
-> Result<native::TextureView, f::TargetViewError>
{
let rdesc = texture::ResourceDesc {
channel: channel,
layer: layer,
min: 0,
max: 0,
swizzle: core::format::Swizzle::new(),
};
self.view_texture(htex, rdesc, true).map_err(|err| match err {
f::ResourceViewError::NoBindFlag => f::TargetViewError::NoBindFlag,
f::ResourceViewError::Channel(ct) => f::TargetViewError::Channel(ct),
f::ResourceViewError::Layer(le) => f::TargetViewError::Layer(le),
f::ResourceViewError::Unsupported => f::TargetViewError::Unsupported,
})
}
#[doc(hidden)]
pub fn view_swapchain_image(&mut self, image: vk::Image, format: core::format::Format, size: (u32, u32))
-> Result<h::RawRenderTargetView<R>, f::TargetViewError> {
use core::Factory;
use core::handle::Producer;
use core::texture as t;
let raw_tex = native::Texture {
image: image,
layout: cell::Cell::new(vk::IMAGE_LAYOUT_GENERAL),
memory: 0,
};
let tex_desc = t::Info {
kind: t::Kind::D2(size.0 as t::Size, size.1 as t::Size, t::AaMode::Single),
levels: 1,
format: format.0,
bind: memory::RENDER_TARGET,
usage: memory::Usage::Data,
};
let tex = self.frame_handles.make_texture(raw_tex, tex_desc);
let view_desc = t::RenderDesc {
channel: format.1,
level: 0,
layer: None,
};
self.view_texture_as_render_target_raw(&tex, view_desc)
}
pub fn create_fence(&mut self, signalled: bool) -> vk::Fence {
let info = vk::FenceCreateInfo {
sType: vk::STRUCTURE_TYPE_FENCE_CREATE_INFO,
pNext: ptr::null(),
flags: if signalled { vk::FENCE_CREATE_SIGNALED_BIT } else { 0 },
};
let (dev, vk) = self.share.get_device();
let mut fence = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateFence(dev, &info, ptr::null(), &mut fence)
});
fence
}
fn create_buffer_impl(&mut self, info: &buffer::Info) -> (native::Buffer, Option<MappingGate>) {
let (usage, _) = data::map_usage_tiling(info.usage, info.bind);
let native_info = vk::BufferCreateInfo {
sType: vk::STRUCTURE_TYPE_BUFFER_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
size: info.size as vk::DeviceSize,
usage: usage,
sharingMode: vk::SHARING_MODE_EXCLUSIVE,
queueFamilyIndexCount: 1,
pQueueFamilyIndices: &self.queue_family_index,
};
let (dev, vk) = self.share.get_device();
let mut buf = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateBuffer(dev, &native_info, ptr::null(), &mut buf)
});
let reqs = unsafe {
let mut out = mem::zeroed();
vk.GetBufferMemoryRequirements(dev, buf, &mut out);
out
};
let mem = self.alloc(info.usage, reqs);
assert_eq!(vk::SUCCESS, unsafe {
vk.BindBufferMemory(dev, buf, mem, 0)
});
use core::memory::Usage::*;
let mapping = match info.usage {
Data | Dynamic => None,
Upload | Download => Some({
let mut m = MappingGate {
pointer: ptr::null_mut(),
status: mapping::Status::clean(),
};
let offset = 0;
let flags = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.MapMemory(dev, mem, offset, vk::WHOLE_SIZE, flags, &mut m.pointer)
});
m
}),
};
(native::Buffer {
buffer: buf,
memory: mem,
}, mapping)
}
fn alloc(&self, usage: memory::Usage, reqs: vk::MemoryRequirements) -> vk::DeviceMemory {
use core::memory::Usage::*;
let info = vk::MemoryAllocateInfo {
sType: vk::STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
pNext: ptr::null(),
allocationSize: reqs.size,
memoryTypeIndex: match usage {
Upload | Download => self.mem_system_id,
Data | Dynamic => self.mem_video_id,
},
};
let (dev, vk) = self.share.get_device();
let mut mem = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.AllocateMemory(dev, &info, ptr::null(), &mut mem)
});
mem
}
fn get_shader_stages(&mut self, program: &h::Program<R>) -> Vec<vk::PipelineShaderStageCreateInfo> {
let prog = self.frame_handles.ref_program(program);
let entry_name = b"main\0"; let mut stages = Vec::new();
if true {
stages.push(vk::PipelineShaderStageCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
stage: vk::SHADER_STAGE_VERTEX_BIT,
module: prog.vertex,
pName: entry_name.as_ptr() as *const i8,
pSpecializationInfo: ptr::null(),
});
}
if let Some(geom) = prog.geometry {
stages.push(vk::PipelineShaderStageCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
stage: vk::SHADER_STAGE_GEOMETRY_BIT,
module: geom,
pName: entry_name.as_ptr() as *const i8,
pSpecializationInfo: ptr::null(),
});
}
if true {
stages.push(vk::PipelineShaderStageCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
stage: vk::SHADER_STAGE_FRAGMENT_BIT,
module: prog.pixel,
pName: entry_name.as_ptr() as *const i8,
pSpecializationInfo: ptr::null(),
});
}
stages
}
}
impl Drop for Factory {
fn drop(&mut self) {
let (dev, vk) = self.share.get_device();
unsafe {
vk.DestroyCommandPool(dev, self.command_pool, ptr::null())
};
}
}
impl core::Factory<R> for Factory {
fn get_capabilities(&self) -> &core::Capabilities {
unimplemented!()
}
fn create_buffer_raw(&mut self, info: buffer::Info) -> Result<h::RawBuffer<R>, buffer::CreationError> {
use core::handle::Producer;
let (buffer, mapping) = self.create_buffer_impl(&info);
Ok(self.share.handles.borrow_mut().make_buffer(buffer, info, mapping))
}
fn create_buffer_immutable_raw(&mut self, data: &[u8], stride: usize, role: buffer::Role, bind: Bind)
-> Result<h::RawBuffer<R>, buffer::CreationError> {
use core::handle::Producer;
let info = buffer::Info {
role: role,
usage: memory::Usage::Data,
bind: bind,
size: data.len(),
stride: stride,
};
let (buffer, mapping) = self.create_buffer_impl(&info);
let (dev, vk) = self.share.get_device();
unsafe {
let mut ptr = ptr::null_mut();
assert_eq!(vk::SUCCESS, vk.MapMemory(dev, buffer.memory, 0, data.len() as u64, 0, &mut ptr));
ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());
vk.UnmapMemory(dev, buffer.memory);
}
Ok(self.share.handles.borrow_mut().make_buffer(buffer, info, mapping))
}
fn create_shader(&mut self, _stage: core::shade::Stage, code: &[u8])
-> Result<h::Shader<R>, core::shade::CreateShaderError> {
use core::handle::Producer;
use mirror::reflect_spirv_module;
use native::Shader;
let info = vk::ShaderModuleCreateInfo {
sType: vk::STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
codeSize: code.len(),
pCode: code.as_ptr() as *const _,
};
let (dev, vk) = self.share.get_device();
let mut shader = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateShaderModule(dev, &info, ptr::null(), &mut shader)
});
let reflection = reflect_spirv_module(code);
let shader = Shader {
shader: shader,
reflection: reflection,
};
Ok(self.share.handles.borrow_mut().make_shader(shader))
}
fn create_program(&mut self, shader_set: &core::ShaderSet<R>)
-> Result<h::Program<R>, core::shade::CreateProgramError> {
use core::handle::Producer;
use core::shade as s;
use mirror::populate_info;
let mut info = s::ProgramInfo {
vertex_attributes: Vec::new(),
globals: Vec::new(),
constant_buffers: Vec::new(),
textures: Vec::new(),
unordereds: Vec::new(),
samplers: Vec::new(),
outputs: Vec::new(),
output_depth: false,
knows_outputs: false,
};
let fh = &mut self.frame_handles;
let prog = match shader_set.clone() {
core::ShaderSet::Simple(vs, ps) => {
let (vs, ps) = (vs.reference(fh), ps.reference(fh));
populate_info(&mut info, s::Stage::Vertex, &vs.reflection);
populate_info(&mut info, s::Stage::Pixel, &ps.reflection);
native::Program {
vertex: vs.shader,
geometry: None,
pixel: ps.shader,
}
}
core::ShaderSet::Geometry(vs, gs, ps) => {
let (vs, gs, ps) = (vs.reference(fh), gs.reference(fh), ps.reference(fh));
populate_info(&mut info, s::Stage::Vertex, &vs.reflection);
populate_info(&mut info, s::Stage::Geometry, &gs.reflection);
populate_info(&mut info, s::Stage::Pixel, &ps.reflection);
native::Program {
vertex: vs.shader,
geometry: Some(gs.shader),
pixel: ps.shader,
}
},
core::ShaderSet::Tessellated(..) => unimplemented!(),
};
Ok(self.share.handles.borrow_mut().make_program(prog, info))
}
fn create_pipeline_state_raw(&mut self, program: &h::Program<R>, desc: &pso::Descriptor)
-> Result<h::RawPipelineState<R>, pso::CreationError> {
use core::handle::Producer;
let stages = self.get_shader_stages(program);
let (dev, vk) = self.share.get_device();
let set_layout = {
let mut bindings = Vec::new();
for (i, cb) in desc.constant_buffers.iter().enumerate() {
if let &Some(usage) = cb {
bindings.push(vk::DescriptorSetLayoutBinding {
binding: i as u32,
descriptorType: vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
descriptorCount: 1,
stageFlags: data::map_stage(usage),
pImmutableSamplers: ptr::null(),
});
}
}
for (i, srv) in desc.resource_views.iter().enumerate() {
if let &Some(usage) = srv {
bindings.push(vk::DescriptorSetLayoutBinding {
binding: i as u32,
descriptorType: vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
descriptorCount: 1,
stageFlags: data::map_stage(usage),
pImmutableSamplers: ptr::null(),
});
}
}
for (i, uav) in desc.unordered_views.iter().enumerate() {
if let &Some(usage) = uav {
bindings.push(vk::DescriptorSetLayoutBinding {
binding: i as u32,
descriptorType: vk::DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptorCount: 1,
stageFlags: data::map_stage(usage),
pImmutableSamplers: ptr::null(),
});
}
}
for (i, sam) in desc.samplers.iter().enumerate() {
if let &Some(usage) = sam {
bindings.push(vk::DescriptorSetLayoutBinding {
binding: i as u32,
descriptorType: vk::DESCRIPTOR_TYPE_SAMPLER,
descriptorCount: 1,
stageFlags: data::map_stage(usage),
pImmutableSamplers: ptr::null(),
});
}
}
let info = vk::DescriptorSetLayoutCreateInfo {
sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
bindingCount: bindings.len() as u32,
pBindings: bindings.as_ptr(),
};
let mut out = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateDescriptorSetLayout(dev, &info, ptr::null(), &mut out)
});
out
};
let pipe_layout = {
let info = vk::PipelineLayoutCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
setLayoutCount: 1,
pSetLayouts: &set_layout,
pushConstantRangeCount: 0,
pPushConstantRanges: ptr::null(),
};
let mut out = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreatePipelineLayout(dev, &info, ptr::null(), &mut out)
});
out
};
let pool = {
let info = vk::DescriptorPoolCreateInfo {
sType: vk::STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
maxSets: 100, poolSizeCount: 0,
pPoolSizes: ptr::null(),
};
let mut out = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateDescriptorPool(dev, &info, ptr::null(), &mut out)
});
out
};
let render_pass = {
let mut attachments = Vec::new();
let mut color_refs = Vec::new();
for col in desc.color_targets.iter().filter_map(|c| c.as_ref()) {
let layout = vk::IMAGE_LAYOUT_GENERAL; color_refs.push(vk::AttachmentReference {
attachment: attachments.len() as u32,
layout: layout,
});
attachments.push(vk::AttachmentDescription {
flags: 0,
format: match data::map_format((col.0).0, (col.0).1) {
Some(fm) => fm,
None => return Err(pso::CreationError),
},
samples: vk::SAMPLE_COUNT_1_BIT, loadOp: vk::ATTACHMENT_LOAD_OP_LOAD,
storeOp: vk::ATTACHMENT_STORE_OP_STORE,
stencilLoadOp: vk::ATTACHMENT_LOAD_OP_DONT_CARE,
stencilStoreOp: vk::ATTACHMENT_STORE_OP_DONT_CARE,
initialLayout: layout,
finalLayout: layout,
});
}
let ds_ref = vk::AttachmentReference {
attachment: attachments.len() as u32,
layout: vk::IMAGE_LAYOUT_GENERAL, };
if let Some(ds) = desc.depth_stencil {
attachments.push(vk::AttachmentDescription {
flags: 0,
format: match data::map_format((ds.0).0, (ds.0).1) {
Some(fm) => fm,
None => return Err(pso::CreationError),
},
samples: vk::SAMPLE_COUNT_1_BIT, loadOp: vk::ATTACHMENT_LOAD_OP_LOAD,
storeOp: vk::ATTACHMENT_STORE_OP_STORE,
stencilLoadOp: vk::ATTACHMENT_LOAD_OP_LOAD,
stencilStoreOp: vk::ATTACHMENT_STORE_OP_STORE,
initialLayout: vk::IMAGE_LAYOUT_GENERAL, finalLayout: vk::IMAGE_LAYOUT_GENERAL,
});
}
let info = vk::RenderPassCreateInfo {
sType: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
attachmentCount: attachments.len() as u32,
pAttachments: attachments.as_ptr(),
subpassCount: 1,
pSubpasses: &vk::SubpassDescription {
flags: 0,
pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS,
inputAttachmentCount: 0,
pInputAttachments: ptr::null(),
colorAttachmentCount: color_refs.len() as u32,
pColorAttachments: color_refs.as_ptr(),
pResolveAttachments: ptr::null(),
pDepthStencilAttachment: if desc.depth_stencil.is_some() {&ds_ref} else {ptr::null()},
preserveAttachmentCount: 0,
pPreserveAttachments: ptr::null(),
},
dependencyCount: 0,
pDependencies: ptr::null(),
};
let mut out = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateRenderPass(dev, &info, ptr::null(), &mut out)
});
out
};
let pipeline = {
let mut vertex_bindings = Vec::new();
for (i, vbuf) in desc.vertex_buffers.iter().enumerate() {
if let &Some(v) = vbuf {
vertex_bindings.push(vk::VertexInputBindingDescription {
binding: i as u32,
stride: v.stride as u32,
inputRate: v.rate as vk::VertexInputRate,
});
}
}
let mut vertex_attributes = Vec::new();
for (i, attr) in desc.attributes.iter().enumerate() {
if let &Some(a) = attr {
vertex_attributes.push(vk::VertexInputAttributeDescription {
location: i as u32,
binding: a.0 as u32,
format: match data::map_format(a.1.format.0, a.1.format.1) {
Some(fm) => fm,
None => return Err(pso::CreationError),
},
offset: a.1.offset as u32,
});
}
}
let mut attachments = Vec::new();
for ocd in desc.color_targets.iter() {
if let &Some(ref cd) = ocd {
attachments.push(data::map_blend(&cd.1));
}
}
let (polygon, line_width) = data::map_polygon_mode(desc.rasterizer.method);
let info = vk::GraphicsPipelineCreateInfo {
sType: vk::STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
stageCount: stages.len() as u32,
pStages: stages.as_ptr(),
pVertexInputState: &vk::PipelineVertexInputStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
vertexBindingDescriptionCount: vertex_bindings.len() as u32,
pVertexBindingDescriptions: vertex_bindings.as_ptr(),
vertexAttributeDescriptionCount: vertex_attributes.len() as u32,
pVertexAttributeDescriptions: vertex_attributes.as_ptr(),
},
pInputAssemblyState: &vk::PipelineInputAssemblyStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
topology: data::map_topology(desc.primitive),
primitiveRestartEnable: vk::FALSE,
},
pTessellationState: ptr::null(),
pViewportState: &vk::PipelineViewportStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
viewportCount: 1,
pViewports: &vk::Viewport {
x: 0.0,
y: 0.0,
width: 1.0,
height: 1.0,
minDepth: 0.0,
maxDepth: 1.0,
},
scissorCount: 1,
pScissors: &vk::Rect2D {
offset: vk::Offset2D {
x: 0, y: 0,
},
extent: vk::Extent2D {
width: 1, height: 1,
},
},
},
pRasterizationState: &vk::PipelineRasterizationStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
depthClampEnable: vk::TRUE,
rasterizerDiscardEnable: vk::FALSE,
polygonMode: polygon,
cullMode: data::map_cull_face(desc.rasterizer.cull_face),
frontFace: data::map_front_face(desc.rasterizer.front_face),
depthBiasEnable: if desc.rasterizer.offset.is_some() { vk::TRUE } else { vk::FALSE },
depthBiasConstantFactor: desc.rasterizer.offset.map_or(0.0, |off| off.1 as f32),
depthBiasClamp: 1.0,
depthBiasSlopeFactor: desc.rasterizer.offset.map_or(0.0, |off| off.0 as f32),
lineWidth: line_width,
},
pMultisampleState: &vk::PipelineMultisampleStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
rasterizationSamples: vk::SAMPLE_COUNT_1_BIT, sampleShadingEnable: vk::FALSE,
minSampleShading: 0.0,
pSampleMask: ptr::null(),
alphaToCoverageEnable: vk::FALSE,
alphaToOneEnable: vk::FALSE,
},
pDepthStencilState: &vk::PipelineDepthStencilStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
depthTestEnable: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { depth: Some(_), ..} )) => vk::TRUE,
_ => vk::FALSE,
},
depthWriteEnable: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { depth: Some(state::Depth { write: true, ..}), ..} )) => vk::TRUE,
_ => vk::FALSE,
},
depthCompareOp: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { depth: Some(state::Depth { fun, ..}), ..} )) => data::map_comparison(fun),
_ => vk::COMPARE_OP_NEVER,
},
depthBoundsTestEnable: vk::FALSE,
stencilTestEnable: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { front: Some(_), ..} )) => vk::TRUE,
Some((_, pso::DepthStencilInfo { back: Some(_), ..} )) => vk::TRUE,
_ => vk::FALSE,
},
front: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { front: Some(ref s), ..} )) => data::map_stencil_side(s),
_ => unsafe { mem::zeroed() },
},
back: match desc.depth_stencil {
Some((_, pso::DepthStencilInfo { back: Some(ref s), ..} )) => data::map_stencil_side(s),
_ => unsafe { mem::zeroed() },
},
minDepthBounds: 0.0,
maxDepthBounds: 1.0,
},
pColorBlendState: &vk::PipelineColorBlendStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
logicOpEnable: vk::FALSE,
logicOp: vk::LOGIC_OP_CLEAR,
attachmentCount: attachments.len() as u32,
pAttachments: attachments.as_ptr(),
blendConstants: [0.0; 4],
},
pDynamicState: &vk::PipelineDynamicStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
dynamicStateCount: 1,
pDynamicStates: [
vk::DYNAMIC_STATE_VIEWPORT,
vk::DYNAMIC_STATE_SCISSOR,
vk::DYNAMIC_STATE_BLEND_CONSTANTS,
vk::DYNAMIC_STATE_STENCIL_REFERENCE,
].as_ptr(),
},
layout: pipe_layout,
renderPass: render_pass,
subpass: 0,
basePipelineHandle: 0,
basePipelineIndex: 0,
};
let mut out = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateGraphicsPipelines(dev, 0, 1, &info, ptr::null(), &mut out)
});
out
};
let pso = native::Pipeline {
pipeline: pipeline,
pipe_layout: pipe_layout,
desc_layout: set_layout,
desc_pool: pool,
render_pass: render_pass,
program: program.clone(),
};
Ok(self.share.handles.borrow_mut().make_pso(pso, program))
}
fn create_texture_raw(&mut self, desc: texture::Info, hint: Option<core::format::ChannelType>,
_data_opt: Option<&[&[u8]]>) -> Result<h::RawTexture<R>, texture::CreationError> {
use core::handle::Producer;
let (w, h, d, aa) = desc.kind.get_dimensions();
let slices = desc.kind.get_num_slices();
let (usage, tiling) = data::map_usage_tiling(desc.usage, desc.bind);
let chan_type = hint.unwrap_or(core::format::ChannelType::Uint);
let info = vk::ImageCreateInfo {
sType: vk::STRUCTURE_TYPE_IMAGE_CREATE_INFO,
pNext: ptr::null(),
flags: vk::IMAGE_CREATE_MUTABLE_FORMAT_BIT |
(if desc.kind.is_cube() {vk::IMAGE_CREATE_CUBE_COMPATIBLE_BIT} else {0}),
imageType: data::map_image_type(desc.kind),
format: match data::map_format(desc.format, chan_type) {
Some(f) => f,
None => return Err(texture::CreationError::Format(desc.format, hint)),
},
extent: vk::Extent3D {
width: w as u32,
height: h as u32,
depth: if slices.is_none() {d as u32} else {1},
},
mipLevels: desc.levels as u32,
arrayLayers: slices.unwrap_or(1) as u32,
samples: aa.get_num_fragments() as vk::SampleCountFlagBits,
tiling: tiling,
usage: usage,
sharingMode: vk::SHARING_MODE_EXCLUSIVE,
queueFamilyIndexCount: 0,
pQueueFamilyIndices: ptr::null(),
initialLayout: data::map_image_layout(desc.bind),
};
let (dev, vk) = self.share.get_device();
let mut image = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateImage(dev, &info, ptr::null(), &mut image)
});
let reqs = unsafe {
let mut out = mem::zeroed();
vk.GetImageMemoryRequirements(dev, image, &mut out);
out
};
let tex = native::Texture {
image: image,
layout: cell::Cell::new(info.initialLayout),
memory: self.alloc(desc.usage, reqs),
};
assert_eq!(vk::SUCCESS, unsafe {
vk.BindImageMemory(dev, image, tex.memory, 0)
});
Ok(self.share.handles.borrow_mut().make_texture(tex, desc))
}
fn view_buffer_as_shader_resource_raw(&mut self, _hbuf: &h::RawBuffer<R>)
-> Result<h::RawShaderResourceView<R>, f::ResourceViewError> {
Err(f::ResourceViewError::Unsupported) }
fn view_buffer_as_unordered_access_raw(&mut self, _hbuf: &h::RawBuffer<R>)
-> Result<h::RawUnorderedAccessView<R>, f::ResourceViewError> {
Err(f::ResourceViewError::Unsupported) }
fn view_texture_as_shader_resource_raw(&mut self, htex: &h::RawTexture<R>, desc: texture::ResourceDesc)
-> Result<h::RawShaderResourceView<R>, f::ResourceViewError> {
use core::handle::Producer;
self.view_texture(htex, desc, false).map(|view|
self.share.handles.borrow_mut().make_texture_srv(view, htex))
}
fn view_texture_as_unordered_access_raw(&mut self, _htex: &h::RawTexture<R>)
-> Result<h::RawUnorderedAccessView<R>, f::ResourceViewError> {
Err(f::ResourceViewError::Unsupported) }
fn view_texture_as_render_target_raw(&mut self, htex: &h::RawTexture<R>, desc: texture::RenderDesc)
-> Result<h::RawRenderTargetView<R>, f::TargetViewError>
{
use core::handle::Producer;
let mut dim = htex.get_info().kind.get_dimensions();
if desc.layer.is_some() {
dim.2 = 1; }
self.view_target(htex, desc.channel, desc.layer).map(|view|
self.share.handles.borrow_mut().make_rtv(view, htex, dim))
}
fn view_texture_as_depth_stencil_raw(&mut self, htex: &h::RawTexture<R>, desc: texture::DepthStencilDesc)
-> Result<h::RawDepthStencilView<R>, f::TargetViewError>
{
use core::handle::Producer;
let mut dim = htex.get_info().kind.get_dimensions();
if desc.layer.is_some() {
dim.2 = 1; }
let channel = ChannelType::Unorm; self.view_target(htex, channel, desc.layer).map(|view|
self.share.handles.borrow_mut().make_dsv(view, htex, dim))
}
fn create_sampler(&mut self, info: texture::SamplerInfo) -> h::Sampler<R> {
use core::handle::Producer;
let (min, mag, mip, aniso) = data::map_filter(info.filter);
let native_info = vk::SamplerCreateInfo {
sType: vk::STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
magFilter: mag,
minFilter: min,
mipmapMode: mip,
addressModeU: data::map_wrap(info.wrap_mode.0),
addressModeV: data::map_wrap(info.wrap_mode.1),
addressModeW: data::map_wrap(info.wrap_mode.2),
mipLodBias: info.lod_bias.into(),
anisotropyEnable: if aniso > 0.0 { vk::TRUE } else { vk::FALSE },
maxAnisotropy: aniso,
compareEnable: if info.comparison.is_some() { vk::TRUE } else { vk::FALSE },
compareOp: data::map_comparison(info.comparison.unwrap_or(state::Comparison::Never)),
minLod: info.lod_range.0.into(),
maxLod: info.lod_range.1.into(),
borderColor: match data::map_border_color(info.border) {
Some(bc) => bc,
None => {
error!("Unsupported border color {:x}", info.border.0);
vk::BORDER_COLOR_FLOAT_TRANSPARENT_BLACK
}
},
unnormalizedCoordinates: vk::FALSE,
};
let (dev, vk) = self.share.get_device();
let mut sampler = 0;
assert_eq!(vk::SUCCESS, unsafe {
vk.CreateSampler(dev, &native_info, ptr::null(), &mut sampler)
});
self.share.handles.borrow_mut().make_sampler(sampler, info)
}
fn read_mapping<'a, 'b, T>(&'a mut self, _: &'b h::Buffer<R, T>)
-> Result<mapping::Reader<'b, R, T>,
mapping::Error>
where T: Copy
{
unimplemented!()
}
fn write_mapping<'a, 'b, T>(&'a mut self, _: &'b h::Buffer<R, T>)
-> Result<mapping::Writer<'b, R, T>,
mapping::Error>
where T: Copy
{
unimplemented!()
}
}