From 149e91a8277991badbbc0b9338d0bb96394c7635 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 6 Jun 2018 00:14:34 -0400 Subject: [PATCH] Cull flags, dynamic states, and dynamic buffers --- Cargo.lock | 14 ++--- Makefile | 2 +- libportability-gfx/src/conv.rs | 31 +++++---- libportability-gfx/src/impls.rs | 107 +++++++++++++++++++------------- 4 files changed, 91 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4a569c..2baf34e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,7 +252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "gfx-backend-dx12" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#505e8057803d8cc0302b5fdcfe7ae807b8f3b8cf" +source = "git+https://github.com/gfx-rs/gfx#f3d012dcfb75cfa363c4858d110a8469f002313d" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "derivative 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "gfx-backend-metal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#505e8057803d8cc0302b5fdcfe7ae807b8f3b8cf" +source = "git+https://github.com/gfx-rs/gfx#f3d012dcfb75cfa363c4858d110a8469f002313d" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -283,14 +283,14 @@ dependencies = [ "metal-rs 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "spirv_cross 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spirv_cross 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gfx-backend-vulkan" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#505e8057803d8cc0302b5fdcfe7ae807b8f3b8cf" +source = "git+https://github.com/gfx-rs/gfx#f3d012dcfb75cfa363c4858d110a8469f002313d" dependencies = [ "ash 0.24.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -308,7 +308,7 @@ dependencies = [ [[package]] name = "gfx-hal" version = "0.1.0" -source = "git+https://github.com/gfx-rs/gfx#505e8057803d8cc0302b5fdcfe7ae807b8f3b8cf" +source = "git+https://github.com/gfx-rs/gfx#f3d012dcfb75cfa363c4858d110a8469f002313d" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -666,7 +666,7 @@ dependencies = [ [[package]] name = "spirv_cross" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1010,7 +1010,7 @@ dependencies = [ "checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" "checksum spirv_cross 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "387a12e5de5d5cd284d07fe7edbcac83163c0b9b4304bd3a0efb1274bcda83cf" -"checksum spirv_cross 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1af833c4f35713d2d739de6e8a2a05614b25800fd48d07d98ca3a143a1df6ce1" +"checksum spirv_cross 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c30addbd9ad947994bcd75019e06d09cccbe30d481f8ce6a16e1b406235b69" "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" diff --git a/Makefile b/Makefile index b8be991..24fe7cf 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ FULL_LIBRARY_PATH=$(CURDIR)/target/debug LIBRARY=target/debug/libportability.$(LIB_EXTENSION) LIBRARY_FAST=target/release/libportability.$(LIB_EXTENSION) -.PHONY: all rebuild debug debug-version release binding run cts cts-pick cts-debug clean cherry +.PHONY: all rebuild debug debug-version release binding run cts clean cherry all: $(TARGET) diff --git a/libportability-gfx/src/conv.rs b/libportability-gfx/src/conv.rs index b47a3b0..a1e3066 100644 --- a/libportability-gfx/src/conv.rs +++ b/libportability-gfx/src/conv.rs @@ -414,8 +414,8 @@ pub fn map_descriptor_type(ty: VkDescriptorType) -> pso::DescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER => pso::DescriptorType::StorageBuffer, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT => pso::DescriptorType::InputAttachment, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER => pso::DescriptorType::CombinedImageSampler, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC | - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => unimplemented!(), + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC => pso::DescriptorType::UniformBufferDynamic, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC => pso::DescriptorType::StorageBufferDynamic, _ => panic!("Unexpected descriptor type: {:?}", ty), } } @@ -514,18 +514,23 @@ pub fn map_polygon_mode(mode: VkPolygonMode, line_width: f32) -> pso::PolygonMod } } -pub fn map_cull_face(cull: VkCullModeFlags) -> Option { - use super::VkCullModeFlagBits::*; - - if cull == VK_CULL_MODE_NONE as _ { None } - else if cull == VK_CULL_MODE_FRONT_BIT as _ { Some(pso::CullFace::Front) } - else if cull == VK_CULL_MODE_BACK_BIT as _ { Some(pso::CullFace::Back) } - else if cull == VK_CULL_MODE_FRONT_AND_BACK as _ { - // TODO: can we support it? - error!("VK_CULL_MODE_FRONT_AND_BACK is not supported yet"); - Some(pso::CullFace::Front) +pub fn map_stencil_face(face: VkStencilFaceFlags) -> pso::Face { + match unsafe { mem::transmute(face) } { + VkStencilFaceFlagBits::VK_STENCIL_FACE_FRONT_BIT => pso::Face::FRONT, + VkStencilFaceFlagBits::VK_STENCIL_FACE_BACK_BIT => pso::Face::BACK, + VkStencilFaceFlagBits::VK_STENCIL_FRONT_AND_BACK => pso::Face::all(), + _ => panic!("Unexpected stencil face: {:?}", face), + } +} + +pub fn map_cull_face(cull: VkCullModeFlags) -> pso::Face { + match unsafe { mem::transmute(cull) } { + VkCullModeFlagBits::VK_CULL_MODE_NONE => pso::Face::empty(), + VkCullModeFlagBits::VK_CULL_MODE_FRONT_BIT => pso::Face::FRONT, + VkCullModeFlagBits::VK_CULL_MODE_BACK_BIT => pso::Face::BACK, + VkCullModeFlagBits::VK_CULL_MODE_FRONT_AND_BACK => pso::Face::all(), + _ => panic!("Unexpected cull face: {:?}", cull), } - else { panic!("Unexpected cull mode: {:?}", cull) } } pub fn map_front_face(face: VkFrontFace) -> pso::FrontFace { diff --git a/libportability-gfx/src/impls.rs b/libportability-gfx/src/impls.rs index 0c219fb..bb88c97 100644 --- a/libportability-gfx/src/impls.rs +++ b/libportability-gfx/src/impls.rs @@ -1307,7 +1307,13 @@ pub extern "C" fn gfxCreateImage( info.samples, ), info.mipLevels as _, - conv::map_format(info.format).unwrap(), + match conv::map_format(info.format) { + Some(format) => format, + None => { + error!("Attempted to create an image with format {:?}", info.format); + return VkResult::VK_ERROR_OUT_OF_HOST_MEMORY + } + }, conv::map_tiling(info.tiling), conv::map_image_usage(info.usage), unsafe { mem::transmute(info.flags) }, @@ -1708,6 +1714,14 @@ pub extern "C" fn gfxCreateGraphicsPipelines( None }; + let empty_dyn_states = []; + let dyn_states = match unsafe { info.pDynamicState.as_ref() } { + Some(state) if !rasterizer_discard => unsafe { + slice::from_raw_parts(state.pDynamicStates, state.dynamicStateCount as _) + }, + _ => &empty_dyn_states, + }; + // TODO: `pDepthStencilState` could contain garbage, but implementations // can ignore it in some circumstances. How to handle it? let depth_stencil = if !rasterizer_discard { @@ -1724,12 +1738,25 @@ pub extern "C" fn gfxCreateGraphicsPipelines( pso::DepthTest::Off }; - fn map_stencil_state(state: VkStencilOpState) -> pso::StencilFace { + fn map_stencil_state(state: VkStencilOpState, dyn_states: &[VkDynamicState]) -> pso::StencilFace { // TODO: reference value pso::StencilFace { fun: conv::map_compare_op(state.compareOp), - mask_read: state.compareMask, - mask_write: state.writeMask, + mask_read: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) { + pso::State::Dynamic + } else { + pso::State::Static(state.compareMask) + }, + mask_write: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) { + pso::State::Dynamic + } else { + pso::State::Static(state.writeMask) + }, + reference: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_STENCIL_REFERENCE) { + pso::State::Dynamic + } else { + pso::State::Static(state.reference) + }, op_fail: conv::map_stencil_op(state.failOp), op_depth_fail: conv::map_stencil_op(state.depthFailOp), op_pass: conv::map_stencil_op(state.passOp), @@ -1738,8 +1765,8 @@ pub extern "C" fn gfxCreateGraphicsPipelines( let stencil_test = if state.stencilTestEnable == VK_TRUE { pso::StencilTest::On { - front: map_stencil_state(state.front), - back: map_stencil_state(state.back), + front: map_stencil_state(state.front, &dyn_states), + back: map_stencil_state(state.back, &dyn_states), } } else { pso::StencilTest::Off @@ -1753,9 +1780,10 @@ pub extern "C" fn gfxCreateGraphicsPipelines( stencil: stencil_test, } }) + .unwrap_or_default() } } else { - None + pso::DepthStencilDesc::default() }; let vp_state = if !rasterizer_discard { @@ -1763,13 +1791,6 @@ pub extern "C" fn gfxCreateGraphicsPipelines( } else { None }; - let empty_dyn_states = []; - let dyn_states = match unsafe { info.pDynamicState.as_ref() } { - Some(state) if !rasterizer_discard => unsafe { - slice::from_raw_parts(state.pDynamicStates, state.dynamicStateCount as _) - }, - _ => &empty_dyn_states, - }; let baked_states = pso::BakedStates { viewport: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_VIEWPORT) { None @@ -2260,8 +2281,7 @@ pub extern "C" fn gfxUpdateDescriptorSets( } pso::DescriptorType::InputAttachment | pso::DescriptorType::SampledImage | - pso::DescriptorType::StorageImage | - pso::DescriptorType::UniformImageDynamic => { + pso::DescriptorType::StorageImage => { image_info .into_iter() .map(|image| pso::Descriptor::Image( @@ -2288,7 +2308,8 @@ pub extern "C" fn gfxUpdateDescriptorSets( } pso::DescriptorType::UniformBuffer | pso::DescriptorType::StorageBuffer | - pso::DescriptorType::UniformBufferDynamic => { + pso::DescriptorType::UniformBufferDynamic | + pso::DescriptorType::StorageBufferDynamic => { buffer_info .into_iter() .map(|buffer| { @@ -2470,7 +2491,7 @@ pub extern "C" fn gfxCreateRenderPass( subpass .pDepthStencilAttachment .as_ref() - .map(|attachment| map_attachment_ref(attachment)) + .map(map_attachment_ref) }; let preserve = unsafe { @@ -2781,7 +2802,7 @@ pub extern "C" fn gfxCmdSetStencilCompareMask( _faceMask: VkStencilFaceFlags, _compareMask: u32, ) { - unimplemented!() + error!("gfxCmdSetStencilCompareMask not implemented"); } #[inline] pub extern "C" fn gfxCmdSetStencilWriteMask( @@ -2789,15 +2810,18 @@ pub extern "C" fn gfxCmdSetStencilWriteMask( _faceMask: VkStencilFaceFlags, _writeMask: u32, ) { - unimplemented!() + error!("gfxCmdSetStencilWriteMask not implemented"); } #[inline] pub extern "C" fn gfxCmdSetStencilReference( - _commandBuffer: VkCommandBuffer, - _faceMask: VkStencilFaceFlags, - _reference: u32, + mut commandBuffer: VkCommandBuffer, + faceMask: VkStencilFaceFlags, + reference: u32, ) { - unimplemented!() + commandBuffer.set_stencil_reference( + conv::map_stencil_face(faceMask), + reference, + ); } #[inline] pub extern "C" fn gfxCmdBindDescriptorSets( @@ -2810,14 +2834,14 @@ pub extern "C" fn gfxCmdBindDescriptorSets( dynamicOffsetCount: u32, pDynamicOffsets: *const u32, ) { - assert_eq!(dynamicOffsetCount, 0); // TODO - let _ = pDynamicOffsets; - let descriptor_sets = unsafe { slice::from_raw_parts(pDescriptorSets, descriptorSetCount as _) .into_iter() .map(|set| &**set) }; + let offsets = unsafe { + slice::from_raw_parts(pDynamicOffsets, dynamicOffsetCount as _) + }; match pipelineBindPoint { VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS => { @@ -2825,6 +2849,7 @@ pub extern "C" fn gfxCmdBindDescriptorSets( &*layout, firstSet as _, descriptor_sets, + offsets, ); } VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_COMPUTE => { @@ -2832,6 +2857,7 @@ pub extern "C" fn gfxCmdBindDescriptorSets( &*layout, firstSet as _, descriptor_sets, + offsets, ); } _ => panic!("Unexpected pipeline bind point: {:?}", pipelineBindPoint), @@ -3198,22 +3224,19 @@ pub extern "C" fn gfxCmdClearAttachments( attachments.iter().map(|at| { use VkImageAspectFlagBits::*; if at.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT as u32 != 0 { - com::AttachmentClear::Color( - at.colorAttachment as _, - unsafe { at.clearValue.color.float32 }.into(), //TODO! - ) - } else - if at.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT as u32 != 0 { - com::AttachmentClear::Depth(unsafe { - at.clearValue.depthStencil.depth - }) - } else - if at.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT as u32 != 0 { - com::AttachmentClear::Stencil(unsafe { - at.clearValue.depthStencil.stencil - }) + com::AttachmentClear::Color { + index: at.colorAttachment as _, + value: unsafe { at.clearValue.color.float32 }.into(), //TODO? + } } else { - panic!("Unexpected mask {:?}", at.aspectMask); + com::AttachmentClear::DepthStencil { + depth: if at.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT as u32 != 0 { + Some(unsafe { at.clearValue.depthStencil.depth }) + } else { None }, + stencil: if at.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT as u32 != 0 { + Some(unsafe { at.clearValue.depthStencil.stencil }) + } else { None }, + } } }), rects.iter().map(conv::map_clear_rect),