Add texture generator
This commit is contained in:
parent
8a0e94b99b
commit
49c716e0e4
8 changed files with 251 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,5 +2,6 @@
|
||||||
/Cargo.lock
|
/Cargo.lock
|
||||||
|
|
||||||
*.spv
|
*.spv
|
||||||
|
image_to_file_*.png
|
||||||
|
|
||||||
vk_functions
|
vk_functions
|
2
build.rs
2
build.rs
|
@ -14,6 +14,8 @@ const SHADER: &[&str] = &[
|
||||||
"src/overlay/elements/radar/single_color.frag",
|
"src/overlay/elements/radar/single_color.frag",
|
||||||
"src/overlay/elements/pedals/history.vert",
|
"src/overlay/elements/pedals/history.vert",
|
||||||
"src/overlay/elements/pedals/history.frag",
|
"src/overlay/elements/pedals/history.frag",
|
||||||
|
"src/overlay/elements/leaderboard/generator.frag",
|
||||||
|
"src/overlay/elements/leaderboard/generator.vert",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn query_vulkan_function_typedefs() {
|
fn query_vulkan_function_typedefs() {
|
||||||
|
|
229
src/overlay/elements/leaderboard/bg_generator.rs
Normal file
229
src/overlay/elements/leaderboard/bg_generator.rs
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use cgmath::{ortho, vec2, Deg};
|
||||||
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
mem,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::overlay::elements::PositionOnlyVertex;
|
||||||
|
|
||||||
|
pub struct BackgroundGenerator;
|
||||||
|
|
||||||
|
impl BackgroundGenerator {
|
||||||
|
pub fn generate<const N: usize>(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
queue: &Arc<Mutex<Queue>>,
|
||||||
|
image_infos: [(u32, u32); N],
|
||||||
|
) -> Result<[Arc<Image>; N]> {
|
||||||
|
Ok(image_infos
|
||||||
|
.iter()
|
||||||
|
.map(|(width, height)| {
|
||||||
|
let image = Image::empty(
|
||||||
|
*width as u32,
|
||||||
|
*height as u32,
|
||||||
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||||
|
| VK_IMAGE_USAGE_SAMPLED_BIT
|
||||||
|
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
)
|
||||||
|
.format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||||
|
.attach_sampler(Sampler::nearest_sampler().build(&device)?)
|
||||||
|
.build(&device, &queue)?;
|
||||||
|
|
||||||
|
image.convert_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)?;
|
||||||
|
|
||||||
|
let render_target = RenderTarget::builder()
|
||||||
|
.add_sub_pass(
|
||||||
|
SubPass::builder(image.width(), image.height())
|
||||||
|
.set_prepared_targets(&[image.clone()], 0, [0.0, 0.0, 0.0, 1.0], true)
|
||||||
|
.build(&device, &queue)?,
|
||||||
|
)
|
||||||
|
.build(&device)?;
|
||||||
|
|
||||||
|
let vertex_shader = ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("generator.vert.spv"),
|
||||||
|
ShaderType::Vertex,
|
||||||
|
)?;
|
||||||
|
let fragment_shader = ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("generator.frag.spv"),
|
||||||
|
ShaderType::Fragment,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let viewport = VkViewport {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: image.width() as f32,
|
||||||
|
height: image.height() as f32,
|
||||||
|
minDepth: 0.0,
|
||||||
|
maxDepth: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let scissor = VkRect2D {
|
||||||
|
offset: VkOffset2D { x: 0, y: 0 },
|
||||||
|
extent: VkExtent2D {
|
||||||
|
width: image.width(),
|
||||||
|
height: image.height(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let pipeline = Pipeline::new_graphics()
|
||||||
|
.set_vertex_shader(
|
||||||
|
vertex_shader.clone(),
|
||||||
|
vec![VkVertexInputBindingDescription {
|
||||||
|
binding: 0,
|
||||||
|
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||||
|
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||||
|
}],
|
||||||
|
vec![
|
||||||
|
// position
|
||||||
|
VkVertexInputAttributeDescription {
|
||||||
|
location: 0,
|
||||||
|
binding: 0,
|
||||||
|
format: VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.set_fragment_shader(fragment_shader.clone())
|
||||||
|
.input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false)
|
||||||
|
.default_depth_stencil(false, false)
|
||||||
|
.default_color_blend(vec![VkPipelineColorBlendAttachmentState::default()])
|
||||||
|
.default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE)
|
||||||
|
.default_multisample(VK_SAMPLE_COUNT_1_BIT)
|
||||||
|
.add_viewport(viewport)
|
||||||
|
.add_scissor(scissor)
|
||||||
|
.build(
|
||||||
|
device.clone(),
|
||||||
|
&PipelineLayout::builder().build(device.clone())?,
|
||||||
|
render_target.render_pass(),
|
||||||
|
0,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let ortho = ortho(
|
||||||
|
0.0,
|
||||||
|
image.width() as f32,
|
||||||
|
0.00,
|
||||||
|
image.height() as f32,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let command_buffer =
|
||||||
|
CommandBuffer::new_primary().build(device.clone(), queue.clone())?;
|
||||||
|
|
||||||
|
// let corners = [
|
||||||
|
// vec2(0.0, 0.0),
|
||||||
|
// vec2(0.0, image.height() as f32),
|
||||||
|
// vec2(image.width() as f32, image.height() as f32),
|
||||||
|
// vec2(image.width() as f32, 0.0),
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// angle 70°
|
||||||
|
let angle: Deg<f32> = Deg(70.0);
|
||||||
|
let tan = angle.0.atan();
|
||||||
|
|
||||||
|
let corners = [
|
||||||
|
vec2(0.0, 0.0),
|
||||||
|
vec2((image.height() as f32) / tan, image.height() as f32),
|
||||||
|
vec2(image.width() as f32, image.height() as f32),
|
||||||
|
vec2(image.width() as f32 - (image.height() as f32) / tan, 0.0),
|
||||||
|
];
|
||||||
|
|
||||||
|
println!("width: {} height: {}", image.width(), image.height());
|
||||||
|
|
||||||
|
for corner in corners.iter() {
|
||||||
|
println!("corner: {:?}", corner);
|
||||||
|
}
|
||||||
|
|
||||||
|
let vertices = PositionOnlyVertex::from_2d_corners(ortho, corners);
|
||||||
|
|
||||||
|
let vertex_buffer = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&vertices)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
SingleSubmit::builder(&command_buffer, queue, |recorder| {
|
||||||
|
render_target.begin(recorder, VK_SUBPASS_CONTENTS_INLINE, 0);
|
||||||
|
|
||||||
|
recorder.bind_pipeline(&pipeline)?;
|
||||||
|
|
||||||
|
recorder.bind_vertex_buffer(&vertex_buffer);
|
||||||
|
recorder.draw_complete_single_instance(vertex_buffer.size() as u32);
|
||||||
|
|
||||||
|
render_target.end(recorder);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.wait_for_timeout(Duration::from_secs(1))
|
||||||
|
.submit()?;
|
||||||
|
|
||||||
|
Ok(image)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<Arc<Image>>>>()?
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or_else(|_: Vec<Arc<Image>>| {
|
||||||
|
unreachable!("create array from vec from an array")
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use anyhow::Result;
|
||||||
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use super::BackgroundGenerator;
|
||||||
|
|
||||||
|
fn create_vk_handles() -> Result<(Arc<Device>, Arc<Mutex<Queue>>)> {
|
||||||
|
let instance = Instance::new(
|
||||||
|
VkApplicationInfo::new(
|
||||||
|
&VkString::new("Test: image::to_file"),
|
||||||
|
1,
|
||||||
|
&VkString::new("no name"),
|
||||||
|
1,
|
||||||
|
VK_MAKE_VERSION(1, 3, 0),
|
||||||
|
),
|
||||||
|
VulkanDebugInfo::default(),
|
||||||
|
InstanceExtensions::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let physical_device = PhysicalDevice::new(instance)?;
|
||||||
|
|
||||||
|
let queue_info = Queue::create_non_presentable_request_info(
|
||||||
|
&physical_device,
|
||||||
|
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let device = Device::new(
|
||||||
|
physical_device,
|
||||||
|
DeviceExtensions::default(),
|
||||||
|
&[queue_info.queue_create_info],
|
||||||
|
DeviceFeatures::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let queue = device.get_queue(queue_info.queue_family_index, queue_info.queue_index);
|
||||||
|
|
||||||
|
Ok((device, queue))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_image_test() {
|
||||||
|
let (device, queue) = create_vk_handles().unwrap();
|
||||||
|
|
||||||
|
let images = BackgroundGenerator::generate(&device, &queue, [(120, 40)]).unwrap();
|
||||||
|
|
||||||
|
for (index, image) in images.iter().enumerate() {
|
||||||
|
image
|
||||||
|
.to_file(&format!("image_to_file_{}.png", index))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
src/overlay/elements/leaderboard/generator.frag
Normal file
8
src/overlay/elements/leaderboard/generator.frag
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
out_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
8
src/overlay/elements/leaderboard/generator.vert
Normal file
8
src/overlay/elements/leaderboard/generator.vert
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout (location = 0) in vec4 position;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = position;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod bg_generator;
|
||||||
mod leaderboard_entry;
|
mod leaderboard_entry;
|
||||||
|
|
||||||
use leaderboard_entry::*;
|
use leaderboard_entry::*;
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl Pedals {
|
||||||
history_image.height(),
|
history_image.height(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, -1.0, 1.0);
|
let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, 0.0, 1.0);
|
||||||
|
|
||||||
let descriptor_pool = DescriptorPool::builder()
|
let descriptor_pool = DescriptorPool::builder()
|
||||||
.set_layout(pipeline.descriptor_layout().clone())
|
.set_layout(pipeline.descriptor_layout().clone())
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl Radar {
|
||||||
rendering.swapchain().width() as f32,
|
rendering.swapchain().width() as f32,
|
||||||
0.0,
|
0.0,
|
||||||
rendering.swapchain().height() as f32,
|
rendering.swapchain().height() as f32,
|
||||||
-1.0,
|
0.0,
|
||||||
1.0,
|
1.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue