diff --git a/gb-emu/src/renderer/vulkan/types.rs b/gb-emu/src/renderer/vulkan/types.rs index 8f848ad..31ee2fc 100644 --- a/gb-emu/src/renderer/vulkan/types.rs +++ b/gb-emu/src/renderer/vulkan/types.rs @@ -12,6 +12,8 @@ use super::{ RendererBackendManager, }; +pub(super) const SHADER_INPUT_FORMAT: vk::Format = vk::Format::R8G8B8A8_UNORM; + #[derive(Clone, Debug, Copy)] pub(super) struct Vertex(pub(super) f32, pub(super) f32); @@ -247,20 +249,21 @@ pub(super) struct SwapchainData { pub(super) viewports: [vk::Viewport; 1], pub(super) scissors: [vk::Rect2D; 1], pub(super) sampler: vk::Sampler, - pub(super) texture_memory: vk::DeviceMemory, - pub(super) tex_image_view: vk::ImageView, - pub(super) image_buffer: vk::Buffer, - pub(super) image_buffer_memory: vk::DeviceMemory, - pub(super) image_buffer_memory_req: vk::MemoryRequirements, - pub(super) image_extent: vk::Extent2D, - pub(super) texture_image: vk::Image, + pub(super) shader_input_texture_memory: vk::DeviceMemory, + pub(super) shader_input_tex_image_view: vk::ImageView, + pub(super) shader_input_image_buffer: vk::Buffer, + pub(super) shader_input_image_buffer_memory: vk::DeviceMemory, + pub(super) shader_input_image_buffer_memory_req: vk::MemoryRequirements, + pub(super) shader_input_image_extent: vk::Extent2D, + pub(super) shader_input_texture: vk::Image, + pub(super) present_images: Vec, + pub(super) shader_output_image_extent: vk::Extent2D, } impl SwapchainData { pub(super) unsafe fn new( resolutions: ResolutionData, manager: &RendererBackendManager, - surface: &SurfaceData, vulkan: &VulkanData, ) -> (Self, vk::PipelineViewportStateCreateInfo) { @@ -367,12 +370,16 @@ impl SwapchainData { .viewports(&viewports) .build(); - let image_extent = vk::Extent2D { + let shader_input_image_extent = vk::Extent2D { width: resolutions.scaled_width, height: resolutions.scaled_height, }; + let shader_output_image_extent = vk::Extent2D { + width: resolutions.real_width, + height: resolutions.real_height, + }; - let image_buffer_info = vk::BufferCreateInfo { + let shader_input_image_buffer_info = vk::BufferCreateInfo { size: (std::mem::size_of::() * (resolutions.scaled_width * resolutions.scaled_height * 4) as usize) as u64, @@ -380,37 +387,43 @@ impl SwapchainData { sharing_mode: vk::SharingMode::EXCLUSIVE, ..Default::default() }; - let image_buffer = vulkan + let shader_input_image_buffer = vulkan .device - .create_buffer(&image_buffer_info, None) + .create_buffer(&shader_input_image_buffer_info, None) .unwrap(); - let image_buffer_memory_req = vulkan.device.get_buffer_memory_requirements(image_buffer); - let image_buffer_memory_index = find_memorytype_index( - &image_buffer_memory_req, + let shader_input_image_buffer_memory_req = vulkan + .device + .get_buffer_memory_requirements(shader_input_image_buffer); + let shader_input_image_buffer_memory_index = find_memorytype_index( + &shader_input_image_buffer_memory_req, &vulkan.device_memory_properties, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, ) .expect("Unable to find suitable memorytype for the image buffer."); - let image_buffer_allocate_info = vk::MemoryAllocateInfo { - allocation_size: image_buffer_memory_req.size, - memory_type_index: image_buffer_memory_index, + let shader_input_image_buffer_allocate_info = vk::MemoryAllocateInfo { + allocation_size: shader_input_image_buffer_memory_req.size, + memory_type_index: shader_input_image_buffer_memory_index, ..Default::default() }; - let image_buffer_memory = vulkan + let shader_input_image_buffer_memory = vulkan .device - .allocate_memory(&image_buffer_allocate_info, None) + .allocate_memory(&shader_input_image_buffer_allocate_info, None) .unwrap(); vulkan .device - .bind_buffer_memory(image_buffer, image_buffer_memory, 0) + .bind_buffer_memory( + shader_input_image_buffer, + shader_input_image_buffer_memory, + 0, + ) .unwrap(); - let texture_create_info = vk::ImageCreateInfo { + let shader_input_texture_create_info = vk::ImageCreateInfo { image_type: vk::ImageType::TYPE_2D, - format: vk::Format::R8G8B8A8_UNORM, - extent: image_extent.into(), + format: SHADER_INPUT_FORMAT, + extent: shader_input_image_extent.into(), mip_levels: 1, array_layers: 1, samples: vk::SampleCountFlags::TYPE_1, @@ -419,30 +432,32 @@ impl SwapchainData { sharing_mode: vk::SharingMode::EXCLUSIVE, ..Default::default() }; - let texture_image = vulkan + let shader_input_texture = vulkan .device - .create_image(&texture_create_info, None) + .create_image(&shader_input_texture_create_info, None) .unwrap(); - let texture_memory_req = vulkan.device.get_image_memory_requirements(texture_image); - let texture_memory_index = find_memorytype_index( - &texture_memory_req, + let shader_input_texture_memory_req = vulkan + .device + .get_image_memory_requirements(shader_input_texture); + let shader_input_texture_memory_index = find_memorytype_index( + &shader_input_texture_memory_req, &vulkan.device_memory_properties, vk::MemoryPropertyFlags::DEVICE_LOCAL, ) .expect("Unable to find suitable memory index for depth image."); - let texture_allocate_info = vk::MemoryAllocateInfo { - allocation_size: texture_memory_req.size, - memory_type_index: texture_memory_index, + let shader_input_texture_allocate_info = vk::MemoryAllocateInfo { + allocation_size: shader_input_texture_memory_req.size, + memory_type_index: shader_input_texture_memory_index, ..Default::default() }; - let texture_memory = vulkan + let shader_input_texture_memory = vulkan .device - .allocate_memory(&texture_allocate_info, None) + .allocate_memory(&shader_input_texture_allocate_info, None) .unwrap(); vulkan .device - .bind_image_memory(texture_image, texture_memory, 0) + .bind_image_memory(shader_input_texture, shader_input_texture_memory, 0) .expect("Unable to bind depth image memory"); record_submit_commandbuffer( @@ -457,7 +472,7 @@ impl SwapchainData { let texture_barrier = vk::ImageMemoryBarrier { dst_access_mask: vk::AccessFlags::TRANSFER_WRITE, new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, - image: texture_image, + image: shader_input_texture, subresource_range: vk::ImageSubresourceRange { aspect_mask: vk::ImageAspectFlags::COLOR, level_count: 1, @@ -482,13 +497,13 @@ impl SwapchainData { .layer_count(1) .build(), ) - .image_extent(image_extent.into()) + .image_extent(shader_input_image_extent.into()) .build(); device.cmd_copy_buffer_to_image( texture_command_buffer, - image_buffer, - texture_image, + shader_input_image_buffer, + shader_input_texture, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &[buffer_copy_regions], ); @@ -497,7 +512,7 @@ impl SwapchainData { dst_access_mask: vk::AccessFlags::SHADER_READ, old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - image: texture_image, + image: shader_input_texture, subresource_range: vk::ImageSubresourceRange { aspect_mask: vk::ImageAspectFlags::COLOR, level_count: 1, @@ -518,9 +533,9 @@ impl SwapchainData { }, ); - let tex_image_view_info = vk::ImageViewCreateInfo { + let shader_input_tex_image_view_info = vk::ImageViewCreateInfo { view_type: vk::ImageViewType::TYPE_2D, - format: texture_create_info.format, + format: shader_input_texture_create_info.format, components: vk::ComponentMapping { r: vk::ComponentSwizzle::R, g: vk::ComponentSwizzle::G, @@ -533,7 +548,7 @@ impl SwapchainData { layer_count: 1, ..Default::default() }, - image: texture_image, + image: shader_input_texture, ..Default::default() }; @@ -552,14 +567,14 @@ impl SwapchainData { let sampler = vulkan.device.create_sampler(&sampler_info, None).unwrap(); - let tex_image_view = vulkan + let shader_input_tex_image_view = vulkan .device - .create_image_view(&tex_image_view_info, None) + .create_image_view(&shader_input_tex_image_view_info, None) .unwrap(); - let tex_descriptor = vk::DescriptorImageInfo { + let shader_input_tex_descriptor = vk::DescriptorImageInfo { image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - image_view: tex_image_view, + image_view: shader_input_tex_image_view, sampler, }; @@ -568,7 +583,7 @@ impl SwapchainData { dst_binding: 1, descriptor_count: 1, descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, - p_image_info: &tex_descriptor, + p_image_info: &shader_input_tex_descriptor, ..Default::default() }]; vulkan.device.update_descriptor_sets(&write_desc_sets, &[]); @@ -583,25 +598,34 @@ impl SwapchainData { viewports, scissors, sampler, - texture_memory, - tex_image_view, - - image_buffer, - image_buffer_memory, - image_buffer_memory_req, - image_extent, - texture_image, + shader_input_texture_memory, + shader_input_tex_image_view, + shader_input_image_buffer, + shader_input_image_buffer_memory, + shader_input_image_buffer_memory_req, + shader_input_image_extent, + shader_input_texture, + present_images, + shader_output_image_extent, }, viewport_state_info, ) } pub(super) unsafe fn manual_drop(&mut self, vulkan: &VulkanData) { - vulkan.device.free_memory(self.image_buffer_memory, None); - vulkan.device.destroy_buffer(self.image_buffer, None); - vulkan.device.free_memory(self.texture_memory, None); - vulkan.device.destroy_image_view(self.tex_image_view, None); - vulkan.device.destroy_image(self.texture_image, None); + vulkan + .device + .free_memory(self.shader_input_image_buffer_memory, None); + vulkan + .device + .destroy_buffer(self.shader_input_image_buffer, None); + vulkan + .device + .free_memory(self.shader_input_texture_memory, None); + vulkan + .device + .destroy_image_view(self.shader_input_tex_image_view, None); + vulkan.device.destroy_image(self.shader_input_texture, None); vulkan.device.destroy_sampler(self.sampler, None); diff --git a/gb-emu/src/renderer/vulkan/utils.rs b/gb-emu/src/renderer/vulkan/utils.rs index e76f114..96bef6c 100644 --- a/gb-emu/src/renderer/vulkan/utils.rs +++ b/gb-emu/src/renderer/vulkan/utils.rs @@ -11,7 +11,8 @@ pub(super) unsafe fn record_submit_commandbuffer( +pub(super) unsafe fn begin_commandbuffer( device: &Device, command_buffer: vk::CommandBuffer, command_buffer_reuse_fence: vk::Fence, - f: F, ) { device .wait_for_fences(&[command_buffer_reuse_fence], true, std::u64::MAX) @@ -52,7 +52,6 @@ pub(super) unsafe fn record_commandbuffer device .begin_command_buffer(command_buffer, &command_buffer_begin_info) .expect("Begin commandbuffer"); - f(device, command_buffer); } pub(super) unsafe fn submit_commandbuffer( diff --git a/gb-emu/src/renderer/vulkan/vulkan.rs b/gb-emu/src/renderer/vulkan/vulkan.rs index eb12ad6..06849f8 100644 --- a/gb-emu/src/renderer/vulkan/vulkan.rs +++ b/gb-emu/src/renderer/vulkan/vulkan.rs @@ -7,9 +7,9 @@ use raw_window_handle::RawDisplayHandle; use winit::window::Window; use self::{ - types::{FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData}, + types::{FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData, SHADER_INPUT_FORMAT}, utils::{ - find_memorytype_index, record_commandbuffer, record_submit_commandbuffer, + begin_commandbuffer, find_memorytype_index, record_submit_commandbuffer, submit_commandbuffer, }, }; @@ -79,12 +79,12 @@ impl Drop for RendererBackendManager { pub struct RendererBackend { inner: VulkanWindowInner, - filter_chain: FilterChain, + filter_chain: Option, manager: Arc, } pub struct WindowOptions { - pub shader_path: PathBuf, + pub shader_path: Option, } impl RendererBackend { @@ -96,23 +96,23 @@ impl RendererBackend { ) -> Self { let inner = unsafe { VulkanWindowInner::new(resolutions, window, manager.as_ref()) }; - let filter_chain_options = FilterChainOptions { - frames_in_flight: 0, - force_no_mipmaps: false, - use_render_pass: true, - disable_cache: false, - }; + let filter_chain = options.shader_path.map(|path| { + let filter_chain_options = FilterChainOptions { + frames_in_flight: 0, + force_no_mipmaps: false, + use_render_pass: true, + disable_cache: false, + }; - let vulkan = VulkanObjects::try_from(( - inner.vulkan_data.pdevice, - manager.instance.clone(), - inner.vulkan_data.device.clone(), - )) - .unwrap(); - let filter_chain = unsafe { - FilterChain::load_from_path(options.shader_path, vulkan, Some(&filter_chain_options)) - } - .unwrap(); + let vulkan = VulkanObjects::try_from(( + inner.vulkan_data.pdevice, + manager.instance.clone(), + inner.vulkan_data.device.clone(), + )) + .unwrap(); + unsafe { FilterChain::load_from_path(path, vulkan, Some(&filter_chain_options)) } + .unwrap() + }); Self { inner, @@ -253,41 +253,6 @@ impl VulkanWindowInner { .bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0) .unwrap(); - // let shader_texture_create_info = vk::ImageCreateInfo { - // image_type: vk::ImageType::TYPE_2D, - // format: vk::Format::R8G8B8A8_UNORM, - // extent: image_extent.into(), - // mip_levels: 1, - // array_layers: 1, - // samples: vk::SampleCountFlags::TYPE_1, - // tiling: vk::ImageTiling::OPTIMAL, - // usage: vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED, - // sharing_mode: vk::SharingMode::EXCLUSIVE, - // ..Default::default() - // }; - // let shader_texture_image = device - // .create_image(&shader_texture_create_info, None) - // .unwrap(); - // let shader_texture_memory_req = device.get_image_memory_requirements(shader_texture_image); - // let shader_texture_memory_index = find_memorytype_index( - // &shader_texture_memory_req, - // &device_memory_properties, - // vk::MemoryPropertyFlags::DEVICE_LOCAL, - // ) - // .expect("Unable to find suitable memory index for depth image."); - - // let shader_texture_allocate_info = vk::MemoryAllocateInfo { - // allocation_size: shader_texture_memory_req.size, - // memory_type_index: shader_texture_memory_index, - // ..Default::default() - // }; - // let shader_texture_memory = device - // .allocate_memory(&shader_texture_allocate_info, None) - // .unwrap(); - // device - // .bind_image_memory(shader_texture_image, shader_texture_memory, 0) - // .expect("Unable to bind depth image memory"); - let shader = ash::util::read_spv(&mut std::io::Cursor::new(SHADER)).unwrap(); let shader_info = vk::ShaderModuleCreateInfo::builder().code(&shader).build(); @@ -428,28 +393,28 @@ impl VulkanWindowInner { .vulkan_data .device .map_memory( - self.swapchain.image_buffer_memory, + self.swapchain.shader_input_image_buffer_memory, 0, - self.swapchain.image_buffer_memory_req.size, + self.swapchain.shader_input_image_buffer_memory_req.size, vk::MemoryMapFlags::empty(), ) .unwrap(); let mut image_slice: Align = Align::new( image_ptr, std::mem::align_of::() as u64, - self.swapchain.image_buffer_memory_req.size, + self.swapchain.shader_input_image_buffer_memory_req.size, ); image_slice.copy_from_slice(bytemuck::cast_slice(buffer)); self.vulkan_data .device - .unmap_memory(self.swapchain.image_buffer_memory); + .unmap_memory(self.swapchain.shader_input_image_buffer_memory); self.vulkan_data .device .bind_buffer_memory( - self.swapchain.image_buffer, - self.swapchain.image_buffer_memory, + self.swapchain.shader_input_image_buffer, + self.swapchain.shader_input_image_buffer_memory, 0, ) .unwrap(); @@ -466,7 +431,7 @@ impl VulkanWindowInner { let texture_barrier = vk::ImageMemoryBarrier { dst_access_mask: vk::AccessFlags::TRANSFER_WRITE, new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, - image: self.swapchain.texture_image, + image: self.swapchain.shader_input_texture, subresource_range: vk::ImageSubresourceRange { aspect_mask: vk::ImageAspectFlags::COLOR, level_count: 1, @@ -491,13 +456,13 @@ impl VulkanWindowInner { .layer_count(1) .build(), ) - .image_extent(self.swapchain.image_extent.into()) + .image_extent(self.swapchain.shader_input_image_extent.into()) .build(); device.cmd_copy_buffer_to_image( texture_command_buffer, - self.swapchain.image_buffer, - self.swapchain.texture_image, + self.swapchain.shader_input_image_buffer, + self.swapchain.shader_input_texture, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &[buffer_copy_regions], ); @@ -506,7 +471,7 @@ impl VulkanWindowInner { dst_access_mask: vk::AccessFlags::SHADER_READ, old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, - image: self.swapchain.texture_image, + image: self.swapchain.shader_input_texture, subresource_range: vk::ImageSubresourceRange { aspect_mask: vk::ImageAspectFlags::COLOR, level_count: 1, @@ -531,7 +496,7 @@ impl VulkanWindowInner { #[allow(unused_variables, clippy::needless_pass_by_ref_mut)] unsafe fn render( &mut self, - filter_chain: &mut FilterChain, + filter_chain: &mut Option, resolutions: ResolutionData, manager: &RendererBackendManager, ) { @@ -562,67 +527,84 @@ impl VulkanWindowInner { .clear_values(&clear_values) .build(); - record_commandbuffer( + begin_commandbuffer( &self.vulkan_data.device, self.vulkan_data.draw_command_buffer, self.vulkan_data.draw_commands_reuse_fence, - |device, draw_command_buffer| { - device.cmd_begin_render_pass( - draw_command_buffer, + ); + + match filter_chain { + Some(filter_chain) => { + filter_chain + .frame( + &librashader::runtime::vk::VulkanImage { + image: self.swapchain.shader_input_texture, + size: self.swapchain.shader_input_image_extent.into(), + format: SHADER_INPUT_FORMAT, + }, + &librashader::runtime::Viewport { + x: 0., + y: 0., + mvp: None, + output: librashader::runtime::vk::VulkanImage { + image: self.swapchain.present_images[present_index as usize], + size: self.swapchain.shader_output_image_extent.into(), + format: self.swapchain.format.format, + }, + }, + self.vulkan_data.draw_command_buffer, + 1, + None, + ) + .unwrap(); + } + None => { + self.vulkan_data.device.cmd_begin_render_pass( + self.vulkan_data.draw_command_buffer, &render_pass_begin_info, vk::SubpassContents::INLINE, ); - device.cmd_bind_descriptor_sets( - draw_command_buffer, + self.vulkan_data.device.cmd_bind_descriptor_sets( + self.vulkan_data.draw_command_buffer, vk::PipelineBindPoint::GRAPHICS, self.pipeline_layout, 0, &self.vulkan_data.descriptor_sets[..], &[], ); - device.cmd_bind_pipeline( - draw_command_buffer, + self.vulkan_data.device.cmd_bind_pipeline( + self.vulkan_data.draw_command_buffer, vk::PipelineBindPoint::GRAPHICS, self.graphics_pipelines[0], ); - device.cmd_set_viewport(draw_command_buffer, 0, &self.swapchain.viewports); - device.cmd_set_scissor(draw_command_buffer, 0, &self.swapchain.scissors); - device.cmd_bind_vertex_buffers( - draw_command_buffer, + self.vulkan_data.device.cmd_set_viewport( + self.vulkan_data.draw_command_buffer, + 0, + &self.swapchain.viewports, + ); + self.vulkan_data.device.cmd_set_scissor( + self.vulkan_data.draw_command_buffer, + 0, + &self.swapchain.scissors, + ); + self.vulkan_data.device.cmd_bind_vertex_buffers( + self.vulkan_data.draw_command_buffer, 0, &[self.vertex_input_buffer], &[0], ); - device.cmd_draw(draw_command_buffer, VERTICES.len() as u32, 1, 0, 1); - device.cmd_end_render_pass(draw_command_buffer); - }, - ); - - // filter_chain - // .frame( - // &librashader::runtime::vk::VulkanImage { - // image: self.texture_image, - // size: self.image_extent.into(), - // format: self.swapchain.format.format, - // }, - // &librashader::runtime::Viewport { - // x: 0., - // y: 0., - // mvp: None, - // output: librashader::runtime::vk::VulkanImage { - // image: self.texture_image, - // size: self.image_extent.into(), - // format: self.swapchain.format.format, - // }, - // }, - // self.draw_command_buffer, - // 1, - // Some(&librashader::runtime::vk::FrameOptions { - // clear_history: true, - // frame_direction: 0, - // }), - // ) - // .expect("fucked it"); + self.vulkan_data.device.cmd_draw( + self.vulkan_data.draw_command_buffer, + VERTICES.len() as u32, + 1, + 0, + 1, + ); + self.vulkan_data + .device + .cmd_end_render_pass(self.vulkan_data.draw_command_buffer); + } + } submit_commandbuffer( &self.vulkan_data.device, diff --git a/gb-emu/src/window.rs b/gb-emu/src/window.rs index 52d8ce1..c031a12 100644 --- a/gb-emu/src/window.rs +++ b/gb-emu/src/window.rs @@ -160,9 +160,9 @@ impl WindowRenderer { #[cfg(feature = "vulkan")] let options = WindowOptions { - shader_path: std::path::PathBuf::from( + shader_path: Some(std::path::PathBuf::from( "./test-roms/shaders/slang-shaders/bilinear.slangp", - ), + )), }; #[cfg(feature = "pixels")] let options = WindowOptions {};