Created
August 29, 2024 20:07
-
-
Save DGriffin91/d792f15c1d0ae0c323f3b64e50968abf to your computer and use it in GitHub Desktop.
SYNC-HAZARD-WRITE-AFTER-WRITE when writing to multiple mips
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mod profile_with_puffin; | |
use { | |
bytemuck::cast_slice, inline_spirv::inline_spirv, screen_13::prelude::*, | |
screen_13_window::Window, std::sync::Arc, winit::dpi::PhysicalSize, | |
}; | |
// A Vulkan triangle using a graphic pipeline, vertex/fragment shaders, and index/vertex buffers. | |
fn main() -> anyhow::Result<()> { | |
pretty_env_logger::init(); | |
profile_with_puffin::init(); | |
let width = 512; | |
let height = 512; | |
let window = Window::builder() | |
.window(|builder| builder.with_inner_size(PhysicalSize::new(width as f64, height as f64))) | |
.build()?; | |
let triangle_pipeline = Arc::new(GraphicPipeline::create( | |
&window.device, | |
GraphicPipelineInfo::default(), | |
[ | |
Shader::new_vertex( | |
inline_spirv!( | |
r#" | |
#version 460 core | |
layout(location = 0) in vec3 position; | |
layout(location = 1) in vec3 color; | |
layout(location = 0) out vec3 vk_Color; | |
void main() { | |
gl_Position = vec4(position, 1); | |
vk_Color = color; | |
} | |
"#, | |
vert | |
) | |
.as_slice(), | |
), | |
Shader::new_fragment( | |
inline_spirv!( | |
r#" | |
#version 460 core | |
layout(location = 0) in vec3 color; | |
layout(location = 0) out vec4 vk_Color; | |
void main() { | |
vk_Color = vec4(color, 1); | |
} | |
"#, | |
frag | |
) | |
.as_slice(), | |
), | |
], | |
)?); | |
let index_buf = Arc::new(Buffer::create_from_slice( | |
&window.device, | |
vk::BufferUsageFlags::INDEX_BUFFER, | |
cast_slice(&[0u16, 1, 2]), | |
)?); | |
let vertex_buf = Arc::new(Buffer::create_from_slice( | |
&window.device, | |
vk::BufferUsageFlags::VERTEX_BUFFER, | |
cast_slice(&[ | |
1.0f32, 1.0, 0.0, // v1 | |
1.0, 0.0, 0.0, // red | |
0.0, -1.0, 0.0, // v2 | |
0.0, 1.0, 0.0, // green | |
-1.0, 1.0, 0.0, // v3 | |
0.0, 0.0, 1.0, // blue | |
]), | |
)?); | |
// ------------------------ | |
// MIP | |
// ------------------------ | |
let mip_compute_pipeline = Arc::new(ComputePipeline::create( | |
&window.device, | |
ComputePipelineInfo::default(), | |
Shader::new_compute( | |
inline_spirv!( | |
r#" | |
#version 460 core | |
layout(binding = 0) uniform sampler2D inputTexture; | |
layout(binding = 1, rgba8) uniform writeonly image2D output_mip0; | |
layout(binding = 2, rgba8) uniform writeonly image2D output_mip1; | |
layout(binding = 3, rgba8) uniform writeonly image2D output_mip2; | |
layout (local_size_x = 8, local_size_y = 8) in; | |
void main() { | |
ivec2 texSize = textureSize(inputTexture, 0); | |
ivec2 gid = ivec2(gl_GlobalInvocationID.xy); | |
if (gid.x >= texSize.x || gid.y >= texSize.y) return; | |
vec4 color = texelFetch(inputTexture, gid, 0); | |
if (gid.x < texSize.x / 2 && gid.y < texSize.y / 2) { | |
imageStore(output_mip0, gid, color); | |
} | |
if (gid.x % 2 == 0 && gid.y % 2 == 0) { | |
imageStore(output_mip1, gid / 2, color); | |
} | |
if (gid.x % 4 == 0 && gid.y % 4 == 0) { | |
imageStore(output_mip2, gid / 4, color); | |
} | |
} | |
"#, | |
comp | |
) | |
.as_slice(), | |
), | |
)?); | |
let mut info = ImageInfo::image_2d( | |
width, | |
height, | |
vk::Format::R8G8B8A8_UNORM, | |
vk::ImageUsageFlags::TRANSFER_SRC | |
| vk::ImageUsageFlags::TRANSFER_DST | |
| vk::ImageUsageFlags::STORAGE | |
| vk::ImageUsageFlags::SAMPLED, | |
); | |
info.mip_level_count = 3; | |
let mip_image = Arc::new(Image::create(&window.device, info).unwrap()); | |
// ------------------------ | |
// BLIT | |
// ------------------------ | |
let blit_pipeline = Arc::new(GraphicPipeline::create( | |
&window.device, | |
GraphicPipelineInfo::default(), | |
[ | |
Shader::new_vertex( | |
inline_spirv!( | |
r#" | |
#version 460 core | |
layout(location = 0) out vec2 uv; | |
void main() | |
{ | |
uint vertexID = uint(gl_VertexIndex); | |
uv = vec2(float(vertexID >> 1), float(vertexID & 1)) * 2.0; | |
gl_Position = vec4(uv * vec2(2.0, 2.0) + vec2(-1.0, -1.0), 0.0, 1.0); | |
} | |
"#, | |
vert | |
) | |
.as_slice(), | |
), | |
Shader::new_fragment( | |
inline_spirv!( | |
r#" | |
#version 460 core | |
layout(binding = 0) uniform sampler2D tex; | |
layout(location = 0) in vec2 inUV; | |
layout(location = 0) out vec4 outColor; | |
void main() { outColor = textureLod(tex, inUV, 2.0); } | |
"#, | |
frag | |
) | |
.as_slice(), | |
), | |
], | |
)?); | |
Ok(window.run(|frame| { | |
let index_node = frame.render_graph.bind_node(&index_buf); | |
let vertex_node = frame.render_graph.bind_node(&vertex_buf); | |
frame | |
.render_graph | |
.begin_pass("Triangle Example") | |
.bind_pipeline(&triangle_pipeline) | |
.access_node(index_node, AccessType::IndexBuffer) | |
.access_node(vertex_node, AccessType::VertexBuffer) | |
.clear_color(0, frame.swapchain_image) | |
.store_color(0, frame.swapchain_image) | |
.record_subpass(move |subpass, _| { | |
subpass.bind_index_buffer(index_node, vk::IndexType::UINT16); | |
subpass.bind_vertex_buffer(vertex_node); | |
subpass.draw_indexed(3, 1, 0, 0, 0); | |
}); | |
// ------------------------ | |
// MIP | |
// ------------------------ | |
let mip_image_node = frame.render_graph.bind_node(mip_image.clone()); | |
let mut mip0_view = mip_image.info.default_view_info(); | |
mip0_view.mip_level_count = Some(1); | |
mip0_view.base_mip_level = 0; | |
let mut mip1_view = mip_image.info.default_view_info(); | |
mip1_view.mip_level_count = Some(1); | |
mip1_view.base_mip_level = 1; | |
let mut mip2_view = mip_image.info.default_view_info(); | |
mip2_view.mip_level_count = Some(1); | |
mip2_view.base_mip_level = 2; | |
frame | |
.render_graph | |
.begin_pass("write_to_mips") | |
.bind_pipeline(&mip_compute_pipeline) | |
.read_descriptor(0, frame.swapchain_image) | |
.access_descriptor_as(1, mip_image_node, AccessType::General, mip0_view) | |
.access_descriptor_as(2, mip_image_node, AccessType::General, mip1_view) | |
.access_descriptor_as(3, mip_image_node, AccessType::General, mip2_view) | |
.record_compute(move |compute, _bindings| { | |
compute.dispatch(width / 8 + 1, height / 8 + 1, 1); | |
}); | |
// ------------------------ | |
// BLIT | |
// ------------------------ | |
// Uncomment to display mip | |
// Intrestingly the WRITE-AFTER-WRITE goes away if this is run. | |
//frame | |
// .render_graph | |
// .begin_pass("blit_to_swapchain") | |
// .bind_pipeline(&blit_pipeline) | |
// .read_descriptor(0, mip_image_node) | |
// .load_color(0, frame.swapchain_image) | |
// .store_color(0, frame.swapchain_image) | |
// .record_subpass(move |subpass, _| { | |
// subpass.draw_indexed(3, 1, 0, 0, 0); | |
// }); | |
})?) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment