75: Use rasterizer discard r=kvark a=grovesNL

Stop setting the fragment shader and other states as stated in the spec when rasterizer discard is set. (Should anything else be disabled?)

Fixes segfaults in `dEQP-VK.api.descriptor_set.descriptor_set_layout_lifetime.graphics` on Metal (with gfx-rs/gfx#2035 fix)

Co-authored-by: Joshua Groves <josh@joshgroves.com>
This commit is contained in:
bors[bot] 2018-05-17 14:37:58 +00:00
commit fa5a78d60c

View file

@ -1485,6 +1485,29 @@ pub extern "C" fn gfxCreateGraphicsPipelines(
let mut cur_shader_stage = 0; let mut cur_shader_stage = 0;
let descs = infos.into_iter().map(|info| { let descs = infos.into_iter().map(|info| {
let (rasterizer, rasterizer_discard) = {
let state = unsafe { &*info.pRasterizationState };
let rasterizer = pso::Rasterizer {
polygon_mode: conv::map_polygon_mode(state.polygonMode, state.lineWidth),
cull_face: conv::map_cull_face(state.cullMode),
front_face: conv::map_front_face(state.frontFace),
depth_clamping: state.depthClampEnable == VK_TRUE,
depth_bias: if state.depthBiasEnable == VK_TRUE {
Some(pso::DepthBias {
const_factor: state.depthBiasConstantFactor,
clamp: state.depthBiasClamp,
slope_factor: state.depthBiasSlopeFactor,
})
} else {
None
},
conservative: false,
};
(rasterizer, state.rasterizerDiscardEnable == VK_TRUE)
};
let shaders = { let shaders = {
let mut set: pso::GraphicsShaderSet<_> = unsafe { mem::zeroed() }; let mut set: pso::GraphicsShaderSet<_> = unsafe { mem::zeroed() };
@ -1509,7 +1532,7 @@ pub extern "C" fn gfxCreateGraphicsPipelines(
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT => { set.hull = Some(entry_point); } VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT => { set.hull = Some(entry_point); }
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT => { set.domain = Some(entry_point); } VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT => { set.domain = Some(entry_point); }
VK_SHADER_STAGE_GEOMETRY_BIT => { set.geometry = Some(entry_point); } VK_SHADER_STAGE_GEOMETRY_BIT => { set.geometry = Some(entry_point); }
VK_SHADER_STAGE_FRAGMENT_BIT => { set.fragment = Some(entry_point); } VK_SHADER_STAGE_FRAGMENT_BIT if !rasterizer_discard => { set.fragment = Some(entry_point); }
stage => panic!("Unexpected shader stage: {:?}", stage), stage => panic!("Unexpected shader stage: {:?}", stage),
} }
} }
@ -1517,31 +1540,6 @@ pub extern "C" fn gfxCreateGraphicsPipelines(
set set
}; };
let (rasterizer, rasterizer_discard) = {
let state = unsafe { &*info.pRasterizationState };
assert_eq!(state.rasterizerDiscardEnable, VK_FALSE); // TODO
let rasterizer = pso::Rasterizer {
polygon_mode: conv::map_polygon_mode(state.polygonMode, state.lineWidth),
cull_face: conv::map_cull_face(state.cullMode),
front_face: conv::map_front_face(state.frontFace),
depth_clamping: state.depthClampEnable == VK_TRUE,
depth_bias: if state.depthBiasEnable == VK_TRUE {
Some(pso::DepthBias {
const_factor: state.depthBiasConstantFactor,
clamp: state.depthBiasClamp,
slope_factor: state.depthBiasSlopeFactor,
})
} else {
None
},
conservative: false,
};
(rasterizer, state.rasterizerDiscardEnable == VK_TRUE)
};
let (vertex_buffers, attributes) = { let (vertex_buffers, attributes) = {
let input_state = unsafe { &*info.pVertexInputState }; let input_state = unsafe { &*info.pVertexInputState };
@ -1676,69 +1674,79 @@ pub extern "C" fn gfxCreateGraphicsPipelines(
// TODO: `pDepthStencilState` could contain garbage, but implementations // TODO: `pDepthStencilState` could contain garbage, but implementations
// can ignore it in some circumstances. How to handle it? // can ignore it in some circumstances. How to handle it?
let depth_stencil = unsafe { info let depth_stencil = if !rasterizer_discard {
.pDepthStencilState unsafe { info
.as_ref() .pDepthStencilState
.map(|state| { .as_ref()
let depth_test = if state.depthTestEnable == VK_TRUE { .map(|state| {
pso::DepthTest::On { let depth_test = if state.depthTestEnable == VK_TRUE {
fun: conv::map_compare_op(state.depthCompareOp), pso::DepthTest::On {
write: state.depthWriteEnable == VK_TRUE, fun: conv::map_compare_op(state.depthCompareOp),
write: state.depthWriteEnable == VK_TRUE,
}
} else {
pso::DepthTest::Off
};
fn map_stencil_state(state: VkStencilOpState) -> pso::StencilFace {
// TODO: reference value
pso::StencilFace {
fun: conv::map_compare_op(state.compareOp),
mask_read: state.compareMask,
mask_write: state.writeMask,
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),
}
} }
} else {
pso::DepthTest::Off
};
fn map_stencil_state(state: VkStencilOpState) -> pso::StencilFace { let stencil_test = if state.stencilTestEnable == VK_TRUE {
// TODO: reference value pso::StencilTest::On {
pso::StencilFace { front: map_stencil_state(state.front),
fun: conv::map_compare_op(state.compareOp), back: map_stencil_state(state.back),
mask_read: state.compareMask, }
mask_write: state.writeMask, } else {
op_fail: conv::map_stencil_op(state.failOp), pso::StencilTest::Off
op_depth_fail: conv::map_stencil_op(state.depthFailOp), };
op_pass: conv::map_stencil_op(state.passOp),
// TODO: depth bounds
pso::DepthStencilDesc {
depth: depth_test,
depth_bounds: state.depthBoundsTestEnable == VK_TRUE,
stencil: stencil_test,
} }
} })
}
let stencil_test = if state.stencilTestEnable == VK_TRUE { } else {
pso::StencilTest::On { None
front: map_stencil_state(state.front),
back: map_stencil_state(state.back),
}
} else {
pso::StencilTest::Off
};
// TODO: depth bounds
pso::DepthStencilDesc {
depth: depth_test,
depth_bounds: state.depthBoundsTestEnable == VK_TRUE,
stencil: stencil_test,
}
})
}; };
let vp_state = unsafe { &*info.pViewportState }; let vp_state = if !rasterizer_discard {
unsafe { info.pViewportState.as_ref() }
} else {
None
};
let empty_dyn_states = []; let empty_dyn_states = [];
let dyn_states = match unsafe { info.pDynamicState.as_ref() } { let dyn_states = match unsafe { info.pDynamicState.as_ref() } {
Some(state) => unsafe { Some(state) if !rasterizer_discard => unsafe {
slice::from_raw_parts(state.pDynamicStates, state.dynamicStateCount as _) slice::from_raw_parts(state.pDynamicStates, state.dynamicStateCount as _)
}, },
None => &empty_dyn_states, _ => &empty_dyn_states,
}; };
let baked_states = pso::BakedStates { let baked_states = pso::BakedStates {
viewport: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_VIEWPORT) { viewport: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_VIEWPORT) {
None None
} else { } else {
unsafe { vp_state.pViewports.as_ref() } vp_state
.and_then(|vp| unsafe { vp.pViewports.as_ref() })
.map(conv::map_viewport) .map(conv::map_viewport)
}, },
scissor: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_SCISSOR) { scissor: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_SCISSOR) {
None None
} else { } else {
unsafe { vp_state.pScissors.as_ref() } vp_state
.and_then(|vp| unsafe { vp.pScissors.as_ref() })
.map(conv::map_rect) .map(conv::map_rect)
}, },
blend_color: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_BLEND_CONSTANTS) { blend_color: if dyn_states.iter().any(|&ds| ds == VkDynamicState::VK_DYNAMIC_STATE_BLEND_CONSTANTS) {