From d672e147db0df6186c528262367770dcde9d75fc Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Sun, 9 Aug 2026 17:36:41 -0700 Subject: rename and reexport a bunch of graphics state types the word "graphics" is part of the module name, so it does not need to be part of the struct name the fact that an object holds state is... not strictly implied by the fact it's a struct, but it happens that ALL our objects exist primarily to hold state, so we remove that word as well Force-Push: yes Change-Id: I1b3e2ac0f1c29304e75a190172463aabfba4b3a4 --- src/graphics/render_state.rs | 504 ------------------------------------------- 1 file changed, 504 deletions(-) delete mode 100644 src/graphics/render_state.rs (limited to 'src/graphics/render_state.rs') diff --git a/src/graphics/render_state.rs b/src/graphics/render_state.rs deleted file mode 100644 index 5848ac8..0000000 --- a/src/graphics/render_state.rs +++ /dev/null @@ -1,504 +0,0 @@ -#![deny(unsafe_code)] -use crate::error::*; -use crate::graphics::permanent::{ - PermanentGraphicsState, GraphicsStateForReinit -}; -use crate::graphics::model::Model; -use crate::graphics::texture::Texture; -use crate::graphics::window_dressing::WindowDressing; -use crate::shader_data::{ Vertex, UniformBlock, VertexPushBlock }; - -use std::mem::size_of; - -use vulkanalia::Device; -use vulkanalia::vk::{ self, Handle, HasBuilder, DeviceV1_0 }; - - -// The RenderState collects the Vulkan graphics objects which need to be -// regenerated or modified when the window changes, as with WindowDressing, -// and which are also used as part of rendering. -#[derive(Debug)] -pub struct RenderState { - pub render_pass: vk::RenderPass, - - pub pipeline: vk::Pipeline, - pub pipeline_layout: vk::PipelineLayout, - - pub model: Option, - - pub framebuffers: Vec, - pub command_buffers: Vec, - pub descriptor_sets: Vec, -} - - -impl RenderState { - pub fn new(permanent: &PermanentGraphicsState, - for_reinit: &GraphicsStateForReinit, - window_dressing: &WindowDressing, texture: &Texture) - -> Result - { - let device = &permanent.device; - let primary_command_pool = &permanent.primary_command_pool; - let sample_count = for_reinit.sample_count; - let descriptor_set_layout = &for_reinit.descriptor_set_layout; - let swapchain = &window_dressing.swapchain; - let depth_format = &window_dressing.depth_format; - let color_image_view = &window_dressing.color_image_view; - let depth_image_view = &window_dressing.depth_image_view; - let uniform_buffers = &window_dressing.uniform_buffers; - let descriptor_pool = &window_dressing.descriptor_pool; - let sampler = &window_dressing.sampler; - - let render_pass = init_render_pass(device, sample_count, - &swapchain.format, &depth_format)?; - - let (pipeline_layout, pipeline) - = init_pipeline(device, descriptor_set_layout, &swapchain.extent, - sample_count, &render_pass)?; - - let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, - &color_image_view, &depth_image_view, &render_pass)?; - - let command_buffers = init_command_buffers(device, &framebuffers, - primary_command_pool)?; - - let descriptor_sets - = init_descriptor_sets(device, descriptor_set_layout, - &uniform_buffers, &descriptor_pool, - swapchain.images.len(), - &texture.image_view, &sampler)?; - - let model = None; - - Ok(RenderState { - render_pass, - pipeline, - pipeline_layout, - model, - framebuffers, - command_buffers, - descriptor_sets, - }) - } - - // This relies on its caller to have already waited for the device to be - // idle. - pub fn reinit(&mut self, permanent: &PermanentGraphicsState, - for_reinit: &GraphicsStateForReinit, - window_dressing: &WindowDressing, texture: &Texture) - -> Result<()> - { - self.destroy_replaceable(permanent); - - let device = &permanent.device; - let primary_command_pool = &permanent.primary_command_pool; - let sample_count = for_reinit.sample_count; - let descriptor_set_layout = &for_reinit.descriptor_set_layout; - let swapchain = &window_dressing.swapchain; - let depth_format = &window_dressing.depth_format; - let color_image_view = &window_dressing.color_image_view; - let depth_image_view = &window_dressing.depth_image_view; - let uniform_buffers = &window_dressing.uniform_buffers; - let descriptor_pool = &window_dressing.descriptor_pool; - let sampler = &window_dressing.sampler; - - let render_pass = init_render_pass(device, sample_count, - &swapchain.format, &depth_format)?; - - let (pipeline_layout, pipeline) - = init_pipeline(device, descriptor_set_layout, &swapchain.extent, - sample_count, &render_pass)?; - - let framebuffers = init_framebuffers( - device, &swapchain.extent, &swapchain.image_views, - &color_image_view, &depth_image_view, &render_pass)?; - - // Notice that we reused the command pool. - let command_buffers = init_command_buffers(device, &framebuffers, - primary_command_pool)?; - - let descriptor_sets - = init_descriptor_sets(device, descriptor_set_layout, - &uniform_buffers, &descriptor_pool, - swapchain.images.len(), - &texture.image_view, sampler)?; - - self.render_pass = render_pass; - self.pipeline = pipeline; - self.pipeline_layout = pipeline_layout; - self.framebuffers = framebuffers; - self.command_buffers = command_buffers; - self.descriptor_sets = descriptor_sets; - - Ok(()) - } - - // This relies on its caller to have already waited for the device to be - // idle. - #[allow(unsafe_code)] - pub fn destroy(mut self, permanent: &PermanentGraphicsState) - { - self.destroy_replaceable(permanent); - - if let Some(model) = self.model { - model.destroy(&permanent.device); - } - } - - #[allow(unsafe_code)] - fn destroy_replaceable(&mut self, permanent: &PermanentGraphicsState) - { - let device = &permanent.device; - - for framebuffer in &self.framebuffers { - unsafe { device.destroy_framebuffer(*framebuffer, None) }; - } - - // Notice that we free the buffers in the pool, but do not destroy the - // pool itself. Notice also that we only do this for the primary command - // pool, because that's the only one where we've kept track of the - // buffers. We promise ourselves to free buffers in the transient pool - // immediately after using them. - unsafe { - device.free_command_buffers(permanent.primary_command_pool, - &self.command_buffers) - }; - - unsafe { device.destroy_pipeline(self.pipeline, None) }; - unsafe { device.destroy_pipeline_layout(self.pipeline_layout, None) }; - unsafe { device.destroy_render_pass(self.render_pass, None) }; - } - - pub fn set_model(&mut self, model: Model) { - self.model = Some(model); - } -} - - -#[allow(unsafe_code)] -fn init_render_pass(device: &Device, sample_count: vk::SampleCountFlags, - color_format: &vk::Format, depth_format: &vk::Format) - -> Result -{ - let color_attachment = vk::AttachmentDescription::builder() - .format(*color_format) - .samples(sample_count) - .load_op(vk::AttachmentLoadOp::CLEAR) - .store_op(vk::AttachmentStoreOp::STORE) - .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) - .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) - .initial_layout(vk::ImageLayout::UNDEFINED) - .final_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); - - let color_attachment_reference = vk::AttachmentReference::builder() - .attachment(0) - .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); - - let depth_attachment = vk::AttachmentDescription::builder() - .format(*depth_format) - .samples(sample_count) - .load_op(vk::AttachmentLoadOp::CLEAR) - .store_op(vk::AttachmentStoreOp::DONT_CARE) - .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) - .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) - .initial_layout(vk::ImageLayout::UNDEFINED) - .final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - let depth_attachment_reference = vk::AttachmentReference::builder() - .attachment(1) - .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - let color_resolve_attachment = vk::AttachmentDescription::builder() - .format(*color_format) - .samples(vk::SampleCountFlags::_1) - .load_op(vk::AttachmentLoadOp::DONT_CARE) - .store_op(vk::AttachmentStoreOp::STORE) - .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) - .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) - .initial_layout(vk::ImageLayout::UNDEFINED) - .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); - - let color_resolve_attachment_reference = vk::AttachmentReference::builder() - .attachment(2) - .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); - - let color_attachments = [color_attachment_reference]; - let resolve_attachments = [color_resolve_attachment_reference]; - let subpass = vk::SubpassDescription::builder() - .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) - .color_attachments(&color_attachments) - .depth_stencil_attachment(&depth_attachment_reference) - .resolve_attachments(&resolve_attachments); - - let dependency = vk::SubpassDependency::builder() - .src_subpass(vk::SUBPASS_EXTERNAL) - .src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT - | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS) - .src_access_mask(vk::AccessFlags::empty()) - .dst_subpass(0) - .dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT - | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS) - .dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE - | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE); - - let render_attachments = [color_attachment, - depth_attachment, - color_resolve_attachment]; - let subpasses = [subpass]; - let dependencies = [dependency]; - let render_pass_info = vk::RenderPassCreateInfo::builder() - .attachments(&render_attachments) - .subpasses(&subpasses) - .dependencies(&dependencies); - - let render_pass = unsafe { - device.create_render_pass(&render_pass_info, None) - }?; - - Ok(render_pass) -} - - -#[allow(unsafe_code)] -fn init_pipeline(device: &Device, - descriptor_set_layout: &vk::DescriptorSetLayout, - extent: &vk::Extent2D, sample_count: vk::SampleCountFlags, - render_pass: &vk::RenderPass) - -> Result<(vk::PipelineLayout, vk::Pipeline)> -{ - let vertex_binary = include_bytes!( - concat!(env!("OUT_DIR"), "/shader.vert.spv")); - let fragment_binary = include_bytes!( - concat!(env!("OUT_DIR"), "/shader.frag.spv")); - - let vertex_module = PermanentGraphicsState::load_spirv_shader_module( - device, vertex_binary)?; - let fragment_module = PermanentGraphicsState::load_spirv_shader_module( - device, fragment_binary)?; - - let vertex_stage_info = vk::PipelineShaderStageCreateInfo::builder() - .stage(vk::ShaderStageFlags::VERTEX) - .module(vertex_module) - .name(b"main\0"); - - let fragment_stage_info = vk::PipelineShaderStageCreateInfo::builder() - .stage(vk::ShaderStageFlags::FRAGMENT) - .module(fragment_module) - .name(b"main\0"); - - let binding_descriptions = [Vertex::::binding_description()]; - let attribute_descriptions = Vertex::::attribute_descriptions(); - let vertex_input_state_info - = vk::PipelineVertexInputStateCreateInfo::builder() - .vertex_binding_descriptions(&binding_descriptions) - .vertex_attribute_descriptions(&attribute_descriptions); - - let input_assembly_state_info - = vk::PipelineInputAssemblyStateCreateInfo::builder() - .topology(vk::PrimitiveTopology::TRIANGLE_LIST) - .primitive_restart_enable(false); - - let viewport = vk::Viewport::builder() - .x(0.0) - .y(0.0) - .width(extent.width as f32) - .height(extent.height as f32) - .min_depth(0.0) - .max_depth(1.0); - let viewports = [viewport]; - - let scissor = vk::Rect2D::builder() - .offset(vk::Offset2D { x: 0, y: 0 }) - .extent(*extent); - let scissor_list = [scissor]; - - let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder() - .viewports(&viewports) - .scissors(&scissor_list); - - let rasterizer_state_info = vk::PipelineRasterizationStateCreateInfo::builder() - .depth_clamp_enable(false) - .rasterizer_discard_enable(false) - .polygon_mode(vk::PolygonMode::FILL) - .line_width(1.0) - .cull_mode(vk::CullModeFlags::BACK) - .front_face(vk::FrontFace::CLOCKWISE) - .depth_bias_enable(false); - - let multisample_state_info - = vk::PipelineMultisampleStateCreateInfo::builder() - .sample_shading_enable(false) - .rasterization_samples(sample_count); - - let depth_state_info = vk::PipelineDepthStencilStateCreateInfo::builder() - .depth_test_enable(true) - .depth_write_enable(true) - .depth_compare_op(vk::CompareOp::LESS) - .depth_bounds_test_enable(false) - .min_depth_bounds(0.0) - .max_depth_bounds(1.0) - .stencil_test_enable(false); - - let blend_attachment_info = vk::PipelineColorBlendAttachmentState::builder() - .color_write_mask(vk::ColorComponentFlags::all()) - .blend_enable(false) - .src_color_blend_factor(vk::BlendFactor::ONE) - .dst_color_blend_factor(vk::BlendFactor::ZERO) - .color_blend_op(vk::BlendOp::ADD) - .src_alpha_blend_factor(vk::BlendFactor::ONE) - .dst_alpha_blend_factor(vk::BlendFactor::ZERO) - .alpha_blend_op(vk::BlendOp::ADD); - let blend_attachments = [blend_attachment_info]; - - let blend_info = vk::PipelineColorBlendStateCreateInfo::builder() - .logic_op_enable(false) - .logic_op(vk::LogicOp::COPY) - .attachments(&blend_attachments) - .blend_constants([0.0, 0.0, 0.0, 0.0]); - - let vertex_push_constant_range = vk::PushConstantRange::builder() - .stage_flags(vk::ShaderStageFlags::VERTEX) - .offset(0) - .size(size_of::>() as u32); - - let layouts = [*descriptor_set_layout]; - let push_constant_ranges = [vertex_push_constant_range]; - let pipeline_layout_info = vk::PipelineLayoutCreateInfo::builder() - .set_layouts(&layouts) - .push_constant_ranges(&push_constant_ranges); - - let pipeline_layout = unsafe { - device.create_pipeline_layout(&pipeline_layout_info, None) - }?; - - let stages = [vertex_stage_info, fragment_stage_info]; - let pipeline_info = vk::GraphicsPipelineCreateInfo::builder() - .stages(&stages) - .vertex_input_state(&vertex_input_state_info) - .input_assembly_state(&input_assembly_state_info) - .viewport_state(&viewport_state_info) - .rasterization_state(&rasterizer_state_info) - .multisample_state(&multisample_state_info) - .depth_stencil_state(&depth_state_info) - .color_blend_state(&blend_info) - .layout(pipeline_layout) - .render_pass(*render_pass) - .subpass(0); - - let pipeline = unsafe { - device.create_graphics_pipelines(vk::PipelineCache::null(), - &[pipeline_info], None) - }?.0[0]; - - unsafe { - device.destroy_shader_module(vertex_module, None); - device.destroy_shader_module(fragment_module, None); - }; - - Ok((pipeline_layout, pipeline)) -} - - -#[allow(unsafe_code)] -fn init_framebuffers(device: &Device, extent: &vk::Extent2D, - swapchain_image_views: &Vec, - color_image_view: &vk::ImageView, - depth_image_view: &vk::ImageView, - render_pass: &vk::RenderPass) - -> Result> -{ - let mut framebuffers = Vec::new(); - - for color_resolve_image_view in swapchain_image_views { - let attachments = [*color_image_view, - *depth_image_view, - *color_resolve_image_view]; - - let framebuffer_info = vk::FramebufferCreateInfo::builder() - .render_pass(*render_pass) - .attachments(&attachments) - .width(extent.width) - .height(extent.height) - .layers(1); - - let framebuffer = unsafe { - device.create_framebuffer(&framebuffer_info, None) - }?; - - framebuffers.push(framebuffer); - } - - Ok(framebuffers) -} - - -#[allow(unsafe_code)] -fn init_command_buffers(device: &Device, - framebuffers: &Vec, - command_pool: &vk::CommandPool) - -> Result> -{ - let command_buffer_allocation_info - = vk::CommandBufferAllocateInfo::builder() - .command_pool(*command_pool) - .level(vk::CommandBufferLevel::PRIMARY) - .command_buffer_count(framebuffers.len() as u32); - let command_buffers = unsafe { - device.allocate_command_buffers(&command_buffer_allocation_info) - }?; - - Ok(command_buffers) -} - - -#[allow(unsafe_code)] -fn init_descriptor_sets(device: &Device, layout: &vk::DescriptorSetLayout, - buffers: &Vec, pool: &vk::DescriptorPool, - count: usize, texture_image_view: &vk::ImageView, - sampler: &vk::Sampler) - -> Result> -{ - let layouts = vec![*layout; count]; - let set_info = vk::DescriptorSetAllocateInfo::builder() - .descriptor_pool(*pool) - .set_layouts(&layouts); - let sets = unsafe { device.allocate_descriptor_sets(&set_info) }?; - - for index in 0 .. count { - let buffer_info = vk::DescriptorBufferInfo::builder() - .buffer(buffers[index]) - .offset(0) - .range(size_of::>() as vk::DeviceSize); - - let buffer_info_list = [buffer_info]; - let uniform_block_write_info = vk::WriteDescriptorSet::builder() - .dst_set(sets[index]) - .dst_binding(0) - .dst_array_element(0) - .descriptor_type(vk::DescriptorType::UNIFORM_BUFFER) - .buffer_info(&buffer_info_list); - - let image_info = vk::DescriptorImageInfo::builder() - .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL) - .image_view(*texture_image_view) - .sampler(*sampler); - let image_info_list = [image_info]; - let sampler_write_info = vk::WriteDescriptorSet::builder() - .dst_set(sets[index]) - .dst_binding(1) - .dst_array_element(0) - .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER) - .image_info(&image_info_list); - - let write_info_list = [uniform_block_write_info, sampler_write_info]; - let copy_info_list: [vk::CopyDescriptorSet; 0] = []; - - unsafe { - device.update_descriptor_sets(&write_info_list, ©_info_list) - }; - } - - Ok(sets) -} -- cgit 1.4.1