Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support depth only pass, more thorough attachment merge checking. #81

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 99 additions & 2 deletions examples/multipass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fn main() -> Result<(), DisplayError> {
let depth_stencil_format = best_depth_stencil_format(&event_loop.device);
let mut pool = LazyPool::new(&event_loop.device);
let fill_background = create_fill_background_pipeline(&event_loop.device);
let prepass = create_prepass_pipeline(&event_loop.device);
let pbr = create_pbr_pipeline(&event_loop.device);
let funky_shape = create_funky_shape(&event_loop, &mut pool)?;

Expand Down Expand Up @@ -80,9 +81,28 @@ fn main() -> Result<(), DisplayError> {
let push_const_data = write_push_consts(obj_pos, material);

let mut write = DepthStencilMode::DEPTH_WRITE;

// Depth Prepass
frame
.render_graph
.begin_pass("Depth Prepass")
.bind_pipeline(&prepass)
.set_depth_stencil(write)
.read_descriptor(0, camera_buf)
.access_node(index_buf, AccessType::IndexBuffer)
.access_node(vertex_buf, AccessType::VertexBuffer)
.clear_depth_stencil(depth_stencil)
.store_depth_stencil(depth_stencil)
.record_subpass(move |subpass, _| {
subpass
.bind_index_buffer(index_buf, vk::IndexType::UINT16)
.bind_vertex_buffer(vertex_buf)
.draw_indexed(funky_shape.index_count, 1, 0, 0, 0);
});

write.stencil_test = true;
write.depth_test = false;
write.front.compare_op = vk::CompareOp::ALWAYS;
write.front.compare_op = vk::CompareOp::GREATER_OR_EQUAL;
write.front.compare_mask = 0xff;
write.front.write_mask = 0xff;
write.front.reference = 0x01;
Expand All @@ -101,7 +121,7 @@ fn main() -> Result<(), DisplayError> {
.read_descriptor(1, light_buf)
.access_node(index_buf, AccessType::IndexBuffer)
.access_node(vertex_buf, AccessType::VertexBuffer)
.clear_depth_stencil(depth_stencil)
.load_depth_stencil(depth_stencil)
.store_depth_stencil(depth_stencil)
.store_color(0, frame.swapchain_image)
.record_subpass(move |subpass, _| {
Expand Down Expand Up @@ -330,6 +350,83 @@ fn create_fill_background_pipeline(device: &Arc<Device>) -> Arc<GraphicPipeline>
)
}

fn create_prepass_pipeline(device: &Arc<Device>) -> Arc<GraphicPipeline> {
let vertex_shader = Shader::new_vertex(
inline_spirv!(
r#"
#version 450

layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;

layout (binding = 0) uniform UBO
{
mat4 projection;
mat4 model;
mat4 view;
vec3 camPos;
} ubo;

layout (location = 0) out vec3 outWorldPos;
layout (location = 1) out vec3 outNormal;

layout(push_constant) uniform PushConsts {
vec3 objPos;
} pushConsts;

out gl_PerVertex
{
vec4 gl_Position;
};

void main()
{
vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0));
outWorldPos = locPos + pushConsts.objPos;
outNormal = mat3(ubo.model) * inNormal;
gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);
}
"#,
vert
)
.as_slice(),
);

let fragment_shader = Shader::new_fragment(
inline_spirv!(
r#"
#version 450

layout (location = 0) in vec3 inWorldPos;
layout (location = 1) in vec3 inNormal;

layout (binding = 0) uniform UBO
{
mat4 projection;
mat4 model;
mat4 view;
vec3 camPos;
} ubo;

void main()
{
}
"#,
frag
)
.as_slice(),
);

Arc::new(
GraphicPipeline::create(
device,
GraphicPipelineInfo::default(),
[vertex_shader, fragment_shader],
)
.unwrap(),
)
}

fn create_pbr_pipeline(device: &Arc<Device>) -> Arc<GraphicPipeline> {
// See: https://github.com/SaschaWillems/Vulkan/blob/master/data/shaders/glsl/pbrbasic/pbr.vert
let vertex_shader = Shader::new_vertex(
Expand Down
171 changes: 96 additions & 75 deletions src/graph/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,24 +218,11 @@ impl Resolver {
}

let rhs_exec = rhs.execs.first().unwrap();
let rhs_depth_stencil = rhs_exec
.depth_stencil_attachment
.or(rhs_exec.depth_stencil_load)
.or(rhs_exec.depth_stencil_store)
.or_else(|| {
rhs_exec
.depth_stencil_resolve
.map(|(attachment, ..)| attachment)
})
.or_else(|| {
rhs_exec
.depth_stencil_clear
.map(|(attachment, _)| attachment)
});

// Now we need to know what the subpasses (we may have prior merges) wrote
for lhs_exec in lhs.execs.iter().rev() {
let mut common_color_attachment = false;
let mut common_depth_attachment = false;

// Multiview subpasses cannot be combined with non-multiview subpasses
if (lhs_exec.view_mask == 0 && rhs_exec.view_mask != 0)
Expand All @@ -246,81 +233,101 @@ impl Resolver {
return false;
}

// Compare individual color attachments for compatibility
for (attachment_idx, lhs_attachment) in lhs_exec
.color_attachments
.iter()
.chain(lhs_exec.color_loads.iter())
.chain(lhs_exec.color_stores.iter())
.chain(
lhs_exec
.color_clears
.iter()
.map(|(attachment_idx, (attachment, _))| (attachment_idx, attachment)),
)
.chain(
lhs_exec
.color_resolves
.iter()
.map(|(attachment_idx, (attachment, _))| (attachment_idx, attachment)),
)
{
let rhs_attachment = rhs_exec
// Check attachment compatibility both ways since one may have a different quantity than the other
for (a_exec, b_exec) in [(lhs_exec, rhs_exec), (rhs_exec, lhs_exec)] {
// Compare individual color attachments for compatibility
for (attachment_idx, a_attachment) in a_exec
.color_attachments
.get(attachment_idx)
.or_else(|| rhs_exec.color_loads.get(attachment_idx))
.or_else(|| rhs_exec.color_stores.get(attachment_idx))
.or_else(|| {
rhs_exec
.iter()
.chain(a_exec.color_loads.iter())
.chain(a_exec.color_stores.iter())
.chain(
a_exec
.color_clears
.get(attachment_idx)
.map(|(attachment, _)| attachment)
.iter()
.map(|(attachment_idx, (attachment, _))| (attachment_idx, attachment)),
)
.chain(
a_exec
.color_resolves
.iter()
.map(|(attachment_idx, (attachment, _))| (attachment_idx, attachment)),
)
{
let b_attachment = b_exec
.color_attachments
.get(attachment_idx)
.or_else(|| b_exec.color_loads.get(attachment_idx))
.or_else(|| b_exec.color_stores.get(attachment_idx))
.or_else(|| {
b_exec
.color_clears
.get(attachment_idx)
.map(|(attachment, _)| attachment)
})
.or_else(|| {
b_exec
.color_resolves
.get(attachment_idx)
.map(|(attachment, _)| attachment)
});

if b_attachment.is_none() {
trace!(" incompatible color attachments");

return false;
}

if !Attachment::are_compatible(Some(*a_attachment), b_attachment.copied()) {
trace!(" incompatible color attachments");

return false;
} else {
common_color_attachment = true;
}
}

// Compare depth/stencil attachments for compatibility
let a_depth_stencil = a_exec
.depth_stencil_attachment
.or(a_exec.depth_stencil_load)
.or(a_exec.depth_stencil_store)
.or_else(|| {
a_exec
.depth_stencil_resolve
.map(|(attachment, ..)| attachment)
})
.or_else(|| a_exec.depth_stencil_clear.map(|(attachment, _)| attachment));

let b_depth_stencil = b_exec
.depth_stencil_attachment
.or(b_exec.depth_stencil_load)
.or(b_exec.depth_stencil_store)
.or_else(|| {
rhs_exec
.color_resolves
.get(attachment_idx)
.map(|(attachment, _)| attachment)
});
b_exec
.depth_stencil_resolve
.map(|(attachment, ..)| attachment)
})
.or_else(|| b_exec.depth_stencil_clear.map(|(attachment, _)| attachment));

if !Attachment::are_compatible(Some(*lhs_attachment), rhs_attachment.copied()) {
trace!(" incompatible color attachments");
if !Attachment::are_compatible(a_depth_stencil, b_depth_stencil) {
trace!(" incompatible depth/stencil attachments");

return false;
} else {
common_color_attachment = true;
}
}

// Compare depth/stencil attachments for compatibility
let lhs_depth_stencil = lhs_exec
.depth_stencil_attachment
.or(lhs_exec.depth_stencil_load)
.or(lhs_exec.depth_stencil_store)
.or_else(|| {
lhs_exec
.depth_stencil_resolve
.map(|(attachment, ..)| attachment)
})
.or_else(|| {
lhs_exec
.depth_stencil_clear
.map(|(attachment, _)| attachment)
});
if !Attachment::are_compatible(lhs_depth_stencil, rhs_depth_stencil) {
trace!(" incompatible depth/stencil attachments");

return false;
if a_depth_stencil.is_some() && b_depth_stencil.is_some() {
common_depth_attachment = true;
} else {
return false;
}
}

let common_depth_attachment =
lhs_depth_stencil.is_some() && rhs_depth_stencil.is_some();

// Keep color and depth on tile.
if common_color_attachment || common_depth_attachment {
if common_color_attachment && common_depth_attachment {
trace!(" merging due to common image");

return true;
return true; // TODO is this returning true prematurely?
}
}

Expand Down Expand Up @@ -2451,6 +2458,20 @@ impl Resolver {
height = height.min(attachment_height);
}

if let Some((attachment_width, attachment_height)) =
first_exec.depth_stencil_clear.map(|(attachment, _)| {
let info = bindings[attachment.target].as_driver_image().unwrap().info;
(info.width, info.height)
})
{
if (width, height) != (u32::MAX, u32::MAX) {
assert_eq!(width, attachment_width);
assert_eq!(height, attachment_height);
}
width = width.min(attachment_width);
height = height.min(attachment_height);
}

Area {
height,
width,
Expand Down
Loading