Fix generator
This commit is contained in:
parent
e777af9758
commit
cfd079b370
3 changed files with 303 additions and 267 deletions
|
@ -13,19 +13,17 @@ layout (location = 0) out vec4 out_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 st = gl_FragCoord.xy/vec2((float)descriptor.width, (float)descriptor.height);
|
uint s = uint(gl_FragCoord.x);
|
||||||
|
uint t = uint(gl_FragCoord.y);
|
||||||
|
|
||||||
if ((uint)st.x <= descriptor.border_thickness ||
|
if (s < descriptor.border_thickness ||
|
||||||
(uint)st.x >= (descriptor.width - descriptor.border_thickness))
|
s >= (descriptor.width - descriptor.border_thickness) ||
|
||||||
|
t < descriptor.border_thickness ||
|
||||||
|
t >= (descriptor.height - descriptor.border_thickness))
|
||||||
{
|
{
|
||||||
out_color = descriptor.border_color;
|
out_color = descriptor.border_color;
|
||||||
}
|
}
|
||||||
else if (
|
else {
|
||||||
(uint)st.y <= descriptor.border_thickness ||
|
|
||||||
(uint)st.y >= (descriptor.height - descriptor.border_thickness)
|
|
||||||
) {
|
|
||||||
out_color = descriptor.border_color;
|
|
||||||
} else {
|
|
||||||
out_color = descriptor.background_color;
|
out_color = descriptor.background_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
290
src/element_creator/generator.rs
Normal file
290
src/element_creator/generator.rs
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
use std::{
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use utilities::{impl_reprc, prelude::cgmath::vec2};
|
||||||
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
use super::{position_only::PositionOnlyVertex, ElementDefinition};
|
||||||
|
|
||||||
|
impl_reprc!(
|
||||||
|
pub struct FragmentShaderInfo {
|
||||||
|
#[assume_reprc]
|
||||||
|
background_color: [f32; 4],
|
||||||
|
#[assume_reprc]
|
||||||
|
border_color: [f32; 4],
|
||||||
|
|
||||||
|
#[assume_reprc]
|
||||||
|
width: u32,
|
||||||
|
#[assume_reprc]
|
||||||
|
height: u32,
|
||||||
|
#[assume_reprc]
|
||||||
|
border_thickness: u32,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl FragmentShaderInfo {
|
||||||
|
fn color_conversion(c: Color) -> [f32; 4] {
|
||||||
|
let a: [f32; 3] = c.into();
|
||||||
|
|
||||||
|
[a[0], a[1], a[2], 1.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ElementDefinition> for FragmentShaderInfo {
|
||||||
|
fn from(value: ElementDefinition) -> Self {
|
||||||
|
Self {
|
||||||
|
background_color: Self::color_conversion(value.background_color),
|
||||||
|
border_color: Self::color_conversion(value.border_color),
|
||||||
|
width: value.width,
|
||||||
|
height: value.height,
|
||||||
|
border_thickness: value.border_thickness,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Generator {
|
||||||
|
device: Arc<Device>,
|
||||||
|
queue: Arc<Mutex<Queue>>,
|
||||||
|
|
||||||
|
max_supported_sample_count: VkSampleCountFlags,
|
||||||
|
vertex_shader: Arc<ShaderModule<shader_type::Vertex>>,
|
||||||
|
fragment_shader: Arc<ShaderModule<shader_type::Fragment>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Generator {
|
||||||
|
pub fn new(device: Arc<Device>, queue: Arc<Mutex<Queue>>) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
max_supported_sample_count: device.max_supported_sample_count(VK_SAMPLE_COUNT_16_BIT),
|
||||||
|
|
||||||
|
vertex_shader: ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("generator.vert.spv"),
|
||||||
|
)?,
|
||||||
|
fragment_shader: ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("generator.frag.spv"),
|
||||||
|
)?,
|
||||||
|
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate(&self, definition: ElementDefinition) -> Result<Arc<Image>> {
|
||||||
|
// create image
|
||||||
|
let image = self.create_image(definition.width, definition.height)?;
|
||||||
|
|
||||||
|
// create fragment shader info
|
||||||
|
let fragment_info = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&[FragmentShaderInfo::from(definition)])
|
||||||
|
.build(self.device.clone())?;
|
||||||
|
|
||||||
|
// create descriptor set
|
||||||
|
let descriptor_layout = DescriptorSetLayout::builder()
|
||||||
|
.add_layout_binding(
|
||||||
|
0,
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.build(self.device.clone())?;
|
||||||
|
|
||||||
|
let desc_pool = DescriptorPool::builder()
|
||||||
|
.set_layout(descriptor_layout.clone())
|
||||||
|
.build(self.device.clone())?;
|
||||||
|
|
||||||
|
let descriptor_set = desc_pool.prepare_set().allocate()?;
|
||||||
|
descriptor_set.update(&[DescriptorWrite::uniform_buffers(0, &[&fragment_info])])?;
|
||||||
|
|
||||||
|
// create render target
|
||||||
|
let render_target = self.render_target(&image)?;
|
||||||
|
|
||||||
|
// create pipeline
|
||||||
|
let pipeline = self.pipeline(
|
||||||
|
&descriptor_layout,
|
||||||
|
&render_target,
|
||||||
|
definition.width,
|
||||||
|
definition.height,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let vertex_buffer = self.vertex_buffer(definition.width, definition.height)?;
|
||||||
|
|
||||||
|
let command_buffer =
|
||||||
|
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
|
||||||
|
|
||||||
|
SingleSubmit::builder(&command_buffer, &self.queue, |recorder| {
|
||||||
|
render_target.begin(recorder, VK_SUBPASS_CONTENTS_INLINE, 0);
|
||||||
|
|
||||||
|
recorder.bind_pipeline(&pipeline)?;
|
||||||
|
|
||||||
|
recorder.bind_descriptor_sets_minimal(&[&descriptor_set]);
|
||||||
|
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(5))
|
||||||
|
.submit()?;
|
||||||
|
|
||||||
|
Ok(image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Generator {
|
||||||
|
fn create_image(&self, width: u32, height: u32) -> Result<Arc<Image>> {
|
||||||
|
let image = Image::empty(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
)
|
||||||
|
.format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||||
|
.attach_sampler(Sampler::nearest_sampler().build(&self.device)?)
|
||||||
|
.build(&self.device, &self.queue)?;
|
||||||
|
|
||||||
|
image.convert_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)?;
|
||||||
|
|
||||||
|
Ok(image)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_target(&self, image: &Arc<Image>) -> Result<RenderTarget> {
|
||||||
|
RenderTarget::builder()
|
||||||
|
.add_sub_pass(
|
||||||
|
SubPass::builder(image.width(), image.height())
|
||||||
|
.add_target_info(CustomTarget {
|
||||||
|
usage: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.into(),
|
||||||
|
format: image.vk_format(),
|
||||||
|
clear_on_load: true,
|
||||||
|
store_on_save: true,
|
||||||
|
attach_sampler: false,
|
||||||
|
use_as_input: false,
|
||||||
|
clear_value: ClearValue::Color([0.0, 0.0, 0.0, 0.0]),
|
||||||
|
})
|
||||||
|
.set_sample_count(self.max_supported_sample_count)
|
||||||
|
.add_resolve_targets((vec![image.clone()], true))
|
||||||
|
.use_queue(image.queue().clone())
|
||||||
|
.build(image.device())?,
|
||||||
|
)
|
||||||
|
.build(image.device())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pipeline(
|
||||||
|
&self,
|
||||||
|
descriptor_layout: &Arc<DescriptorSetLayout>,
|
||||||
|
render_target: &RenderTarget,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> Result<Arc<Pipeline>> {
|
||||||
|
let viewport = VkViewport {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: width as f32,
|
||||||
|
height: height as f32,
|
||||||
|
minDepth: 0.0,
|
||||||
|
maxDepth: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let scissor = VkRect2D {
|
||||||
|
offset: VkOffset2D { x: 0, y: 0 },
|
||||||
|
extent: VkExtent2D { width, height },
|
||||||
|
};
|
||||||
|
|
||||||
|
Pipeline::new_graphics()
|
||||||
|
.set_vertex_shader::<PositionOnlyVertex>(self.vertex_shader.clone())
|
||||||
|
.set_fragment_shader(self.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(self.max_supported_sample_count)
|
||||||
|
.add_viewport(viewport)
|
||||||
|
.add_scissor(scissor)
|
||||||
|
.build(
|
||||||
|
self.device.clone(),
|
||||||
|
&PipelineLayout::builder()
|
||||||
|
.add_descriptor_set_layout(&descriptor_layout)
|
||||||
|
.build(self.device.clone())?,
|
||||||
|
render_target.render_pass(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertex_buffer(&self, width: u32, height: u32) -> Result<Arc<Buffer<PositionOnlyVertex>>> {
|
||||||
|
let ortho = cgmath::ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0);
|
||||||
|
|
||||||
|
let vertices = PositionOnlyVertex::from_2d_corners(
|
||||||
|
ortho,
|
||||||
|
[
|
||||||
|
vec2(0.0, height as f32),
|
||||||
|
vec2(0.0, 0.0),
|
||||||
|
vec2(width as f32, 0.0),
|
||||||
|
vec2(width as f32, height as f32),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&vertices)
|
||||||
|
.build(self.device.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use utilities::color::Color;
|
||||||
|
use vulkan_rs::create_vk_handles;
|
||||||
|
|
||||||
|
use super::{ElementDefinition, Generator};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_example() -> anyhow::Result<()> {
|
||||||
|
let (device, queue) = create_vk_handles()?;
|
||||||
|
let generator = Generator::new(device, queue)?;
|
||||||
|
|
||||||
|
let image = generator.generate(ElementDefinition {
|
||||||
|
width: 120,
|
||||||
|
height: 40,
|
||||||
|
background_color: Color::try_from("#935615")?,
|
||||||
|
border_color: Color::try_from("#61401c")?,
|
||||||
|
border_thickness: 3,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
image.to_file("example.png")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shader_simulator() {
|
||||||
|
let width: u32 = 120;
|
||||||
|
let height: u32 = 40;
|
||||||
|
let border_thickness: u32 = 5;
|
||||||
|
|
||||||
|
let points = [(0.0, 0.0), (0.5, 0.5), (0.96, 0.5)];
|
||||||
|
|
||||||
|
for (x, y) in points {
|
||||||
|
let s = (x * width as f32) as u32;
|
||||||
|
let t = (y * height as f32) as u32;
|
||||||
|
|
||||||
|
println!("st: ({s}, {t})");
|
||||||
|
|
||||||
|
if s <= border_thickness
|
||||||
|
|| s >= (width - border_thickness)
|
||||||
|
|| t <= border_thickness
|
||||||
|
|| t >= (height - border_thickness)
|
||||||
|
{
|
||||||
|
println!("\t border");
|
||||||
|
} else {
|
||||||
|
println!("\t background");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
|
mod generator;
|
||||||
mod position_only;
|
mod position_only;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use utilities::{color::Color, impl_reprc, prelude::cgmath::vec2};
|
use utilities::color::Color;
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use self::position_only::PositionOnlyVertex;
|
use self::generator::Generator;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ElementBorderThickness {
|
pub enum ElementBorderThickness {
|
||||||
|
@ -32,10 +32,10 @@ impl From<f32> for ElementBorderThickness {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct ElementDescriptor {
|
pub struct ElementDescriptor {
|
||||||
pub background_color: Color,
|
background_color: Color,
|
||||||
pub border_color: Color,
|
border_color: Color,
|
||||||
|
|
||||||
pub border_thickness: ElementBorderThickness,
|
border_thickness: ElementBorderThickness,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementDescriptor {
|
impl ElementDescriptor {
|
||||||
|
@ -52,42 +52,6 @@ impl ElementDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_reprc!(
|
|
||||||
pub(crate) struct FragmentShaderInfo {
|
|
||||||
#[assume_reprc]
|
|
||||||
background_color: [f32; 4],
|
|
||||||
#[assume_reprc]
|
|
||||||
border_color: [f32; 4],
|
|
||||||
|
|
||||||
#[assume_reprc]
|
|
||||||
width: u32,
|
|
||||||
#[assume_reprc]
|
|
||||||
height: u32,
|
|
||||||
#[assume_reprc]
|
|
||||||
border_thickness: u32,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl FragmentShaderInfo {
|
|
||||||
fn color_conversion(c: Color) -> [f32; 4] {
|
|
||||||
let a: [f32; 3] = c.into();
|
|
||||||
|
|
||||||
[a[0], a[1], a[2], 1.0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ElementDefinition> for FragmentShaderInfo {
|
|
||||||
fn from(value: ElementDefinition) -> Self {
|
|
||||||
Self {
|
|
||||||
background_color: Self::color_conversion(value.background_color),
|
|
||||||
border_color: Self::color_conversion(value.border_color),
|
|
||||||
width: value.width,
|
|
||||||
height: value.height,
|
|
||||||
border_thickness: value.border_thickness,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||||
struct ElementDefinition {
|
struct ElementDefinition {
|
||||||
width: u32,
|
width: u32,
|
||||||
|
@ -143,219 +107,3 @@ impl ElementCreator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Generator {
|
|
||||||
device: Arc<Device>,
|
|
||||||
queue: Arc<Mutex<Queue>>,
|
|
||||||
|
|
||||||
max_supported_sample_count: VkSampleCountFlags,
|
|
||||||
vertex_shader: Arc<ShaderModule<shader_type::Vertex>>,
|
|
||||||
fragment_shader: Arc<ShaderModule<shader_type::Fragment>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Generator {
|
|
||||||
fn new(device: Arc<Device>, queue: Arc<Mutex<Queue>>) -> Result<Self> {
|
|
||||||
Ok(Self {
|
|
||||||
max_supported_sample_count: device.max_supported_sample_count(VK_SAMPLE_COUNT_16_BIT),
|
|
||||||
|
|
||||||
vertex_shader: ShaderModule::from_slice(
|
|
||||||
device.clone(),
|
|
||||||
include_bytes!("generator.vert.spv"),
|
|
||||||
)?,
|
|
||||||
fragment_shader: ShaderModule::from_slice(
|
|
||||||
device.clone(),
|
|
||||||
include_bytes!("generator.frag.spv"),
|
|
||||||
)?,
|
|
||||||
|
|
||||||
device,
|
|
||||||
queue,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate(&self, definition: ElementDefinition) -> Result<Arc<Image>> {
|
|
||||||
// create image
|
|
||||||
let image = self.create_image(definition.width, definition.height)?;
|
|
||||||
|
|
||||||
// create fragment shader info
|
|
||||||
let fragment_info = Buffer::builder()
|
|
||||||
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
|
||||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
|
||||||
.set_data(&[FragmentShaderInfo::from(definition)])
|
|
||||||
.build(self.device.clone())?;
|
|
||||||
|
|
||||||
// create descriptor set
|
|
||||||
let descriptor_layout = DescriptorSetLayout::builder()
|
|
||||||
.add_layout_binding(
|
|
||||||
0,
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.build(self.device.clone())?;
|
|
||||||
|
|
||||||
let desc_pool = DescriptorPool::builder()
|
|
||||||
.set_layout(descriptor_layout.clone())
|
|
||||||
.build(self.device.clone())?;
|
|
||||||
|
|
||||||
let descriptor_set = desc_pool.prepare_set().allocate()?;
|
|
||||||
descriptor_set.update(&[DescriptorWrite::uniform_buffers(0, &[&fragment_info])])?;
|
|
||||||
|
|
||||||
// create render target
|
|
||||||
let render_target = self.render_target(&image)?;
|
|
||||||
|
|
||||||
// create pipeline
|
|
||||||
let pipeline = self.pipeline(
|
|
||||||
&descriptor_layout,
|
|
||||||
&render_target,
|
|
||||||
definition.width,
|
|
||||||
definition.height,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let vertex_buffer = self.vertex_buffer(definition.width, definition.height)?;
|
|
||||||
|
|
||||||
let command_buffer =
|
|
||||||
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
|
|
||||||
|
|
||||||
SingleSubmit::builder(&command_buffer, &self.queue, |recorder| {
|
|
||||||
render_target.begin(recorder, VK_SUBPASS_CONTENTS_INLINE, 0);
|
|
||||||
|
|
||||||
recorder.bind_pipeline(&pipeline)?;
|
|
||||||
|
|
||||||
recorder.bind_descriptor_sets_minimal(&[&descriptor_set]);
|
|
||||||
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(5))
|
|
||||||
.submit()?;
|
|
||||||
|
|
||||||
Ok(image)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_image(&self, width: u32, height: u32) -> Result<Arc<Image>> {
|
|
||||||
let image = Image::empty(
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
)
|
|
||||||
.format(VK_FORMAT_R8G8B8A8_UNORM)
|
|
||||||
.attach_sampler(Sampler::nearest_sampler().build(&self.device)?)
|
|
||||||
.build(&self.device, &self.queue)?;
|
|
||||||
|
|
||||||
image.convert_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)?;
|
|
||||||
|
|
||||||
Ok(image)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_target(&self, image: &Arc<Image>) -> Result<RenderTarget> {
|
|
||||||
RenderTarget::builder()
|
|
||||||
.add_sub_pass(
|
|
||||||
SubPass::builder(image.width(), image.height())
|
|
||||||
.add_target_info(CustomTarget {
|
|
||||||
usage: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.into(),
|
|
||||||
format: image.vk_format(),
|
|
||||||
clear_on_load: true,
|
|
||||||
store_on_save: true,
|
|
||||||
attach_sampler: false,
|
|
||||||
use_as_input: false,
|
|
||||||
clear_value: ClearValue::Color([0.0, 0.0, 0.0, 0.0]),
|
|
||||||
})
|
|
||||||
.set_sample_count(self.max_supported_sample_count)
|
|
||||||
.add_resolve_targets((vec![image.clone()], true))
|
|
||||||
.use_queue(image.queue().clone())
|
|
||||||
.build(image.device())?,
|
|
||||||
)
|
|
||||||
.build(image.device())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pipeline(
|
|
||||||
&self,
|
|
||||||
descriptor_layout: &Arc<DescriptorSetLayout>,
|
|
||||||
render_target: &RenderTarget,
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
) -> Result<Arc<Pipeline>> {
|
|
||||||
let viewport = VkViewport {
|
|
||||||
x: 0.0,
|
|
||||||
y: 0.0,
|
|
||||||
width: width as f32,
|
|
||||||
height: height as f32,
|
|
||||||
minDepth: 0.0,
|
|
||||||
maxDepth: 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let scissor = VkRect2D {
|
|
||||||
offset: VkOffset2D { x: 0, y: 0 },
|
|
||||||
extent: VkExtent2D { width, height },
|
|
||||||
};
|
|
||||||
|
|
||||||
Pipeline::new_graphics()
|
|
||||||
.set_vertex_shader::<PositionOnlyVertex>(self.vertex_shader.clone())
|
|
||||||
.set_fragment_shader(self.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(self.max_supported_sample_count)
|
|
||||||
.add_viewport(viewport)
|
|
||||||
.add_scissor(scissor)
|
|
||||||
.build(
|
|
||||||
self.device.clone(),
|
|
||||||
&PipelineLayout::builder()
|
|
||||||
.add_descriptor_set_layout(&descriptor_layout)
|
|
||||||
.build(self.device.clone())?,
|
|
||||||
render_target.render_pass(),
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertex_buffer(&self, width: u32, height: u32) -> Result<Arc<Buffer<PositionOnlyVertex>>> {
|
|
||||||
let ortho = cgmath::ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0);
|
|
||||||
|
|
||||||
let vertices = PositionOnlyVertex::from_2d_corners(
|
|
||||||
ortho,
|
|
||||||
[
|
|
||||||
vec2(0.0, height as f32),
|
|
||||||
vec2(0.0, 0.0),
|
|
||||||
vec2(width as f32, 0.0),
|
|
||||||
vec2(width as f32, height as f32),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
Buffer::builder()
|
|
||||||
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
|
||||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
|
||||||
.set_data(&vertices)
|
|
||||||
.build(self.device.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use utilities::color::Color;
|
|
||||||
use vulkan_rs::create_vk_handles;
|
|
||||||
|
|
||||||
use super::{ElementDefinition, Generator};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn generate_example() -> anyhow::Result<()> {
|
|
||||||
let (device, queue) = create_vk_handles()?;
|
|
||||||
let generator = Generator::new(device, queue)?;
|
|
||||||
|
|
||||||
let image = generator.generate(ElementDefinition {
|
|
||||||
width: 120,
|
|
||||||
height: 40,
|
|
||||||
background_color: Color::try_from("#935615")?,
|
|
||||||
border_color: Color::try_from("#61401c")?,
|
|
||||||
border_thickness: 5,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
image.to_file("example.png")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue