Compare commits

...

7 commits

13 changed files with 390 additions and 229 deletions

View file

@ -2,6 +2,7 @@
xtask = "run --package xtask --" xtask = "run --package xtask --"
[profile.dev] [profile.dev]
opt-level = 1
lto = false lto = false
[profile.release] [profile.release]

89
Cargo.lock generated
View file

@ -740,6 +740,15 @@ dependencies = [
"target-lexicon", "target-lexicon",
] ]
[[package]]
name = "cfg-expr"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8"
dependencies = [
"smallvec",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.10" version = "0.1.10"
@ -1441,6 +1450,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]]
name = "duct"
version = "0.13.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c"
dependencies = [
"libc",
"once_cell",
"os_pipe",
"shared_child",
]
[[package]] [[package]]
name = "dunce" name = "dunce"
version = "1.0.4" version = "1.0.4"
@ -3618,6 +3639,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "os_pipe"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.6.1" version = "6.6.1"
@ -3689,6 +3720,17 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pbr"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514"
dependencies = [
"crossbeam-channel",
"libc",
"winapi",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -4344,9 +4386,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.122" version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@ -4393,6 +4435,16 @@ dependencies = [
"syn 2.0.71", "syn 2.0.71",
] ]
[[package]]
name = "shared_child"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
@ -4558,7 +4610,7 @@ version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
dependencies = [ dependencies = [
"cfg-expr", "cfg-expr 0.15.8",
"heck", "heck",
"pkg-config", "pkg-config",
"toml 0.8.15", "toml 0.8.15",
@ -4571,7 +4623,7 @@ version = "7.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c81f13d9a334a6c242465140bd262fae382b752ff2011c4f7419919a9c97922" checksum = "6c81f13d9a334a6c242465140bd262fae382b752ff2011c4f7419919a9c97922"
dependencies = [ dependencies = [
"cfg-expr", "cfg-expr 0.15.8",
"heck", "heck",
"pkg-config", "pkg-config",
"toml 0.8.15", "toml 0.8.15",
@ -5527,6 +5579,15 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.42.2" version = "0.42.2"
@ -5855,32 +5916,20 @@ version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"
[[package]]
name = "xshell"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
dependencies = [
"xshell-macros",
]
[[package]]
name = "xshell-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
[[package]] [[package]]
name = "xtask" name = "xtask"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cargo_metadata", "cargo_metadata",
"cfg-expr 0.16.0",
"clap", "clap",
"duct",
"env_logger", "env_logger",
"log", "log",
"nih_plug_xtask", "nih_plug_xtask",
"pbr",
"serde_json",
"strum", "strum",
"xshell",
] ]
[[package]] [[package]]

View file

@ -122,6 +122,15 @@ impl From<Args> for frontend_common::RunOptions {
} }
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
unsafe {
if std::env::var_os("RUST_BACKTRACE").is_none() {
std::env::set_var("RUST_BACKTRACE", "1");
}
if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "cli=info,frontend_common=info,gb_emu_lib=info");
}
}
env_logger::init(); env_logger::init();
let args = Args::parse(); let args = Args::parse();

View file

@ -297,6 +297,7 @@ where
factor: usize, factor: usize,
queued_buf: QueuedBuf, queued_buf: QueuedBuf,
recording: Option<RecordInfo>, recording: Option<RecordInfo>,
awaiting_resize: bool,
} }
struct QueuedBuf { struct QueuedBuf {
@ -379,6 +380,7 @@ where
factor, factor,
queued_buf: Default::default(), queued_buf: Default::default(),
recording, recording,
awaiting_resize: false,
}, },
sender, sender,
)) ))
@ -426,6 +428,7 @@ where
let real_width = (width as u32) * real_factor; let real_width = (width as u32) * real_factor;
let real_height = (height as u32) * real_factor; let real_height = (height as u32) * real_factor;
self.awaiting_resize = true;
if let Some(size) = self if let Some(size) = self
.window .window
@ -436,6 +439,7 @@ where
} }
fn on_resize(&mut self, size: PhysicalSize<u32>) { fn on_resize(&mut self, size: PhysicalSize<u32>) {
self.awaiting_resize = false;
let resolutions = ResolutionData { let resolutions = ResolutionData {
real_width: size.width, real_width: size.width,
real_height: size.height, real_height: size.height,
@ -451,6 +455,13 @@ where
} }
fn display(&mut self, buffer: Vec<[u8; 4]>) { fn display(&mut self, buffer: Vec<[u8; 4]>) {
if self.awaiting_resize {
log::warn!(
"window {}: received buffer before resize complete",
self.window.title()
);
return;
}
self.queued_buf.update(buffer); self.queued_buf.update(buffer);
self.window.request_redraw(); self.window.request_redraw();

View file

@ -4,7 +4,7 @@ version = "0.5.1"
edition = "2021" edition = "2021"
[features] [features]
default = ["config", "librashader", "wgpu-renderer"] default = ["config"]
clocked-serial = [] clocked-serial = []
librashader = [ librashader = [
"dep:librashader", "dep:librashader",

View file

@ -1,13 +1,13 @@
use ash::{extensions::ext::DebugUtils, vk, Entry, Instance}; use ash::{ext::debug_utils, vk, Entry, Instance};
pub(super) struct VulkanDebug { pub(super) struct VulkanDebug {
debug_utils_loader: DebugUtils, debug_utils_loader: debug_utils::Instance,
debug_call_back: vk::DebugUtilsMessengerEXT, debug_call_back: vk::DebugUtilsMessengerEXT,
} }
impl VulkanDebug { impl VulkanDebug {
pub(super) fn new(entry: &Entry, instance: &Instance) -> Self { pub(super) fn new(entry: &Entry, instance: &Instance) -> Self {
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder() let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default()
.message_severity( .message_severity(
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
@ -19,10 +19,9 @@ impl VulkanDebug {
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE, | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
) )
.pfn_user_callback(Some(vulkan_debug_callback)) .pfn_user_callback(Some(vulkan_debug_callback));
.build();
let debug_utils_loader = DebugUtils::new(entry, instance); let debug_utils_loader = debug_utils::Instance::new(entry, instance);
let debug_call_back = let debug_call_back =
unsafe { debug_utils_loader.create_debug_utils_messenger(&debug_info, None) }.unwrap(); unsafe { debug_utils_loader.create_debug_utils_messenger(&debug_info, None) }.unwrap();

View file

@ -4,13 +4,10 @@ use librashader::runtime::vk::{FilterChain, FilterChainOptions, FrameOptions, Vu
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle}; use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
use std::{mem::ManuallyDrop, path::PathBuf, sync::Arc}; use std::{mem::ManuallyDrop, path::PathBuf, sync::Arc};
use crate::connect::ResolutionData; use crate::{connect::ResolutionData, error::VulkanError};
use self::{ use self::{
types::{ types::{FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData, SHADER_INPUT_FORMAT},
FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData, VulkanError,
SHADER_INPUT_FORMAT,
},
utils::{ utils::{
begin_commandbuffer, find_memorytype_index, record_submit_commandbuffer, begin_commandbuffer, find_memorytype_index, record_submit_commandbuffer,
submit_commandbuffer, submit_commandbuffer,
@ -53,22 +50,22 @@ impl RendererBackendManager for VulkanBackendManager {
.to_vec(); .to_vec();
#[cfg(all(debug_assertions, feature = "vulkan-debug"))] #[cfg(all(debug_assertions, feature = "vulkan-debug"))]
extension_names.push(ash::extensions::ext::DebugUtils::name().as_ptr()); extension_names.push(ash::ext::debug_utils::NAME.as_ptr());
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
{ {
#[cfg(not(feature = "vulkan-static"))] #[cfg(not(feature = "vulkan-static"))]
extension_names.push(vk::KhrPortabilityEnumerationFn::name().as_ptr()); extension_names.push(vk::KHR_PORTABILITY_ENUMERATION_NAME.as_ptr());
extension_names.push(vk::KhrGetPhysicalDeviceProperties2Fn::name().as_ptr());
extension_names.push(vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_NAME.as_ptr());
} }
let appinfo = vk::ApplicationInfo::builder() let appinfo = vk::ApplicationInfo::default()
.application_name(&name) .application_name(&name)
.engine_name(&name) .engine_name(&name)
.application_version(0) .application_version(0)
.engine_version(0) .engine_version(0)
.api_version(vk::make_api_version(0, 1, 0, 0)) .api_version(vk::make_api_version(0, 1, 0, 0));
.build();
let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) { let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) {
vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR
@ -76,11 +73,10 @@ impl RendererBackendManager for VulkanBackendManager {
vk::InstanceCreateFlags::default() vk::InstanceCreateFlags::default()
}; };
let create_info = vk::InstanceCreateInfo::builder() let create_info = vk::InstanceCreateInfo::default()
.application_info(&appinfo) .application_info(&appinfo)
.enabled_extension_names(&extension_names) .enabled_extension_names(&extension_names)
.flags(create_flags) .flags(create_flags);
.build();
let instance = unsafe { entry.create_instance(&create_info, None) }.unwrap(); let instance = unsafe { entry.create_instance(&create_info, None) }.unwrap();
@ -135,8 +131,8 @@ impl RendererBackend for VulkanBackend {
let filter_chain_options = FilterChainOptions { let filter_chain_options = FilterChainOptions {
frames_in_flight: 0, frames_in_flight: 0,
force_no_mipmaps: false, force_no_mipmaps: false,
use_render_pass: true,
disable_cache: false, disable_cache: false,
use_dynamic_rendering: false,
}; };
let vulkan = VulkanObjects::try_from(( let vulkan = VulkanObjects::try_from((
@ -213,8 +209,7 @@ impl VulkanWindowInner {
let vulkan_data = VulkanData::new(manager, &surface); let vulkan_data = VulkanData::new(manager, &surface);
let (swapchain, _viewport_state_info) = let swapchain = SwapchainData::new(resolutions, manager, &surface, &vulkan_data);
SwapchainData::new(resolutions, manager, &surface, &vulkan_data);
let renderpass_attachments = [vk::AttachmentDescription { let renderpass_attachments = [vk::AttachmentDescription {
format: swapchain.format.format, format: swapchain.format.format,
@ -237,16 +232,14 @@ impl VulkanWindowInner {
..Default::default() ..Default::default()
}]; }];
let subpass = vk::SubpassDescription::builder() let subpass = vk::SubpassDescription::default()
.color_attachments(&color_attachment_refs) .color_attachments(&color_attachment_refs)
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS);
.build();
let renderpass_create_info = vk::RenderPassCreateInfo::builder() let renderpass_create_info = vk::RenderPassCreateInfo::default()
.attachments(&renderpass_attachments) .attachments(&renderpass_attachments)
.subpasses(std::slice::from_ref(&subpass)) .subpasses(std::slice::from_ref(&subpass))
.dependencies(&dependencies) .dependencies(&dependencies);
.build();
let renderpass = vulkan_data let renderpass = vulkan_data
.device .device
@ -339,8 +332,7 @@ impl VulkanWindowInner {
.device .device
.destroy_framebuffer(*framebuffer, None); .destroy_framebuffer(*framebuffer, None);
} }
(self.swapchain, _) = self.swapchain = SwapchainData::new(resolutions, manager, &self.surface, &self.vulkan_data);
SwapchainData::new(resolutions, manager, &self.surface, &self.vulkan_data);
self.framebuffers = self.framebuffers =
FramebufferData::new(&self.swapchain, &self.vulkan_data, self.renderpass); FramebufferData::new(&self.swapchain, &self.vulkan_data, self.renderpass);
@ -395,15 +387,13 @@ impl VulkanWindowInner {
&[], &[],
&[texture_barrier], &[texture_barrier],
); );
let buffer_copy_regions = vk::BufferImageCopy::builder() let buffer_copy_regions = vk::BufferImageCopy::default()
.image_subresource( .image_subresource(
vk::ImageSubresourceLayers::builder() vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR) .aspect_mask(vk::ImageAspectFlags::COLOR)
.layer_count(1) .layer_count(1),
.build(),
) )
.image_extent(self.swapchain.shader_input_image_extent.into()) .image_extent(self.swapchain.shader_input_image_extent.into());
.build();
device.cmd_copy_buffer_to_image( device.cmd_copy_buffer_to_image(
texture_command_buffer, texture_command_buffer,
@ -450,7 +440,7 @@ impl VulkanWindowInner {
.swapchain_loader .swapchain_loader
.acquire_next_image( .acquire_next_image(
self.swapchain.swapchain, self.swapchain.swapchain,
std::u64::MAX, u64::MAX,
self.vulkan_data.present_complete_semaphore, self.vulkan_data.present_complete_semaphore,
vk::Fence::null(), vk::Fence::null(),
) )
@ -488,6 +478,9 @@ impl VulkanWindowInner {
Some(&FrameOptions { Some(&FrameOptions {
clear_history: true, clear_history: true,
frame_direction: 0, frame_direction: 0,
rotation: 0,
total_subframes: 0,
current_subframe: 0,
}), }),
) )
.unwrap(); .unwrap();

View file

@ -1,10 +1,5 @@
use ash::{ use ash::{khr::swapchain, vk, Device};
extensions::khr::{Surface, Swapchain}, use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
vk, Device,
};
#[allow(deprecated)]
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use thiserror::Error;
use crate::connect::ResolutionData; use crate::connect::ResolutionData;
@ -24,10 +19,8 @@ pub(super) struct VulkanData {
pub(super) pdevice: vk::PhysicalDevice, pub(super) pdevice: vk::PhysicalDevice,
pub(super) device: Device, pub(super) device: Device,
pub(super) device_memory_properties: vk::PhysicalDeviceMemoryProperties, pub(super) device_memory_properties: vk::PhysicalDeviceMemoryProperties,
// pub(super) desc_set_layouts: [vk::DescriptorSetLayout; 1],
pub(super) present_queue: vk::Queue, pub(super) present_queue: vk::Queue,
// pub(super) pool: vk::CommandPool,
pub(super) draw_command_buffer: vk::CommandBuffer, pub(super) draw_command_buffer: vk::CommandBuffer,
pub(super) setup_command_buffer: vk::CommandBuffer, pub(super) setup_command_buffer: vk::CommandBuffer,
pub(super) texture_copy_command_buffer: vk::CommandBuffer, pub(super) texture_copy_command_buffer: vk::CommandBuffer,
@ -38,7 +31,6 @@ pub(super) struct VulkanData {
pub(super) draw_commands_reuse_fence: vk::Fence, pub(super) draw_commands_reuse_fence: vk::Fence,
pub(super) setup_commands_reuse_fence: vk::Fence, pub(super) setup_commands_reuse_fence: vk::Fence,
pub(super) texture_copy_commands_reuse_fence: vk::Fence, pub(super) texture_copy_commands_reuse_fence: vk::Fence,
// pub(super) descriptor_pool: vk::DescriptorPool,
} }
impl VulkanData { impl VulkanData {
@ -76,9 +68,9 @@ impl VulkanData {
.expect("Couldn't find suitable device."); .expect("Couldn't find suitable device.");
let queue_family_index = queue_family_index as u32; let queue_family_index = queue_family_index as u32;
let device_extension_names_raw = [ let device_extension_names_raw = [
Swapchain::name().as_ptr(), swapchain::NAME.as_ptr(),
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
vk::KhrPortabilitySubsetFn::name().as_ptr(), vk::KHR_PORTABILITY_SUBSET_NAME.as_ptr(),
]; ];
let features = vk::PhysicalDeviceFeatures { let features = vk::PhysicalDeviceFeatures {
shader_clip_distance: 1, shader_clip_distance: 1,
@ -86,16 +78,14 @@ impl VulkanData {
}; };
let priorities = [1.0]; let priorities = [1.0];
let queue_info = vk::DeviceQueueCreateInfo::builder() let queue_info = vk::DeviceQueueCreateInfo::default()
.queue_family_index(queue_family_index) .queue_family_index(queue_family_index)
.queue_priorities(&priorities) .queue_priorities(&priorities);
.build();
let device_create_info = vk::DeviceCreateInfo::builder() let device_create_info = vk::DeviceCreateInfo::default()
.queue_create_infos(std::slice::from_ref(&queue_info)) .queue_create_infos(std::slice::from_ref(&queue_info))
.enabled_extension_names(&device_extension_names_raw) .enabled_extension_names(&device_extension_names_raw)
.enabled_features(&features) .enabled_features(&features);
.build();
let device = manager let device = manager
.instance .instance
@ -104,18 +94,16 @@ impl VulkanData {
let present_queue = device.get_device_queue(queue_family_index, 0); let present_queue = device.get_device_queue(queue_family_index, 0);
let pool_create_info = vk::CommandPoolCreateInfo::builder() let pool_create_info = vk::CommandPoolCreateInfo::default()
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER) .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
.queue_family_index(queue_family_index) .queue_family_index(queue_family_index);
.build();
let pool = device.create_command_pool(&pool_create_info, None).unwrap(); let pool = device.create_command_pool(&pool_create_info, None).unwrap();
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::builder() let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::default()
.command_buffer_count(3) .command_buffer_count(3)
.command_pool(pool) .command_pool(pool)
.level(vk::CommandBufferLevel::PRIMARY) .level(vk::CommandBufferLevel::PRIMARY);
.build();
let command_buffers = device let command_buffers = device
.allocate_command_buffers(&command_buffer_allocate_info) .allocate_command_buffers(&command_buffer_allocate_info)
@ -128,9 +116,8 @@ impl VulkanData {
.instance .instance
.get_physical_device_memory_properties(pdevice); .get_physical_device_memory_properties(pdevice);
let fence_create_info = vk::FenceCreateInfo::builder() let fence_create_info =
.flags(vk::FenceCreateFlags::SIGNALED) vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED);
.build();
let draw_commands_reuse_fence = device let draw_commands_reuse_fence = device
.create_fence(&fence_create_info, None) .create_fence(&fence_create_info, None)
@ -151,38 +138,6 @@ impl VulkanData {
.create_semaphore(&semaphore_create_info, None) .create_semaphore(&semaphore_create_info, None)
.unwrap(); .unwrap();
// let descriptor_sizes = [
// vk::DescriptorPoolSize {
// ty: vk::DescriptorType::UNIFORM_BUFFER,
// descriptor_count: 1,
// },
// vk::DescriptorPoolSize {
// ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: 1,
// },
// ];
// let descriptor_pool_info = vk::DescriptorPoolCreateInfo::builder()
// .pool_sizes(&descriptor_sizes)
// .max_sets(1)
// .build();
// let descriptor_pool = device
// .create_descriptor_pool(&descriptor_pool_info, None)
// .unwrap();
// let desc_layout_bindings = [vk::DescriptorSetLayoutBinding {
// descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: 1,
// stage_flags: vk::ShaderStageFlags::FRAGMENT,
// ..Default::default()
// }];
// let descriptor_info = vk::DescriptorSetLayoutCreateInfo::builder()
// .bindings(&desc_layout_bindings)
// .build();
// let desc_set_layouts = [device
// .create_descriptor_set_layout(&descriptor_info, None)
// .unwrap()];
Self { Self {
pdevice, pdevice,
device, device,
@ -197,33 +152,30 @@ impl VulkanData {
draw_commands_reuse_fence, draw_commands_reuse_fence,
setup_commands_reuse_fence, setup_commands_reuse_fence,
texture_copy_commands_reuse_fence, texture_copy_commands_reuse_fence,
// desc_set_layouts,
// descriptor_pool,
} }
} }
} }
pub(super) struct SurfaceData { pub(super) struct SurfaceData {
pub(super) surface: vk::SurfaceKHR, pub(super) surface: vk::SurfaceKHR,
pub(super) surface_loader: Surface, pub(super) surface_loader: ash::khr::surface::Instance,
} }
impl SurfaceData { impl SurfaceData {
#[allow(deprecated)] pub(super) unsafe fn new<W: HasDisplayHandle + HasWindowHandle>(
pub(super) unsafe fn new<W: HasRawDisplayHandle + HasRawWindowHandle>(
window: &W, window: &W,
manager: &VulkanBackendManager, manager: &VulkanBackendManager,
) -> Self { ) -> Self {
let surface = ash_window::create_surface( let surface = ash_window::create_surface(
&manager.entry, &manager.entry,
&manager.instance, &manager.instance,
window.raw_display_handle().unwrap(), window.display_handle().unwrap().as_raw(),
window.raw_window_handle().unwrap(), window.window_handle().unwrap().as_raw(),
None, None,
) )
.unwrap(); .unwrap();
let surface_loader = Surface::new(&manager.entry, &manager.instance); let surface_loader = ash::khr::surface::Instance::new(&manager.entry, &manager.instance);
Self { Self {
surface, surface,
@ -233,7 +185,7 @@ impl SurfaceData {
} }
pub(super) struct SwapchainData { pub(super) struct SwapchainData {
pub(super) swapchain_loader: Swapchain, pub(super) swapchain_loader: swapchain::Device,
pub(super) swapchain: vk::SwapchainKHR, pub(super) swapchain: vk::SwapchainKHR,
pub(super) format: vk::SurfaceFormatKHR, pub(super) format: vk::SurfaceFormatKHR,
pub(super) surface_resolution: vk::Extent2D, pub(super) surface_resolution: vk::Extent2D,
@ -255,7 +207,7 @@ impl SwapchainData {
manager: &VulkanBackendManager, manager: &VulkanBackendManager,
surface: &SurfaceData, surface: &SurfaceData,
vulkan: &VulkanData, vulkan: &VulkanData,
) -> (Self, vk::PipelineViewportStateCreateInfo) { ) -> Self {
let format = surface let format = surface
.surface_loader .surface_loader
.get_physical_device_surface_formats(vulkan.pdevice, surface.surface) .get_physical_device_surface_formats(vulkan.pdevice, surface.surface)
@ -295,9 +247,9 @@ impl SwapchainData {
.cloned() .cloned()
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX) .find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
.unwrap_or(vk::PresentModeKHR::FIFO); .unwrap_or(vk::PresentModeKHR::FIFO);
let swapchain_loader = Swapchain::new(&manager.instance, &vulkan.device); let swapchain_loader = swapchain::Device::new(&manager.instance, &vulkan.device);
let swapchain_create_info = vk::SwapchainCreateInfoKHR::builder() let swapchain_create_info = vk::SwapchainCreateInfoKHR::default()
.surface(surface.surface) .surface(surface.surface)
.min_image_count(desired_image_count) .min_image_count(desired_image_count)
.image_color_space(format.color_space) .image_color_space(format.color_space)
@ -309,8 +261,7 @@ impl SwapchainData {
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
.present_mode(present_mode) .present_mode(present_mode)
.clipped(true) .clipped(true)
.image_array_layers(1) .image_array_layers(1);
.build();
let swapchain = swapchain_loader let swapchain = swapchain_loader
.create_swapchain(&swapchain_create_info, None) .create_swapchain(&swapchain_create_info, None)
@ -320,7 +271,7 @@ impl SwapchainData {
let present_image_views: Vec<vk::ImageView> = present_images let present_image_views: Vec<vk::ImageView> = present_images
.iter() .iter()
.map(|&image| { .map(|&image| {
let create_view_info = vk::ImageViewCreateInfo::builder() let create_view_info = vk::ImageViewCreateInfo::default()
.view_type(vk::ImageViewType::TYPE_2D) .view_type(vk::ImageViewType::TYPE_2D)
.format(format.format) .format(format.format)
.components(vk::ComponentMapping { .components(vk::ComponentMapping {
@ -336,8 +287,7 @@ impl SwapchainData {
base_array_layer: 0, base_array_layer: 0,
layer_count: 1, layer_count: 1,
}) })
.image(image) .image(image);
.build();
vulkan vulkan
.device .device
.create_image_view(&create_view_info, None) .create_image_view(&create_view_info, None)
@ -345,20 +295,6 @@ impl SwapchainData {
}) })
.collect(); .collect();
let viewports = [vk::Viewport {
x: 0.0,
y: 0.0,
width: surface_resolution.width as f32,
height: surface_resolution.height as f32,
min_depth: 0.0,
max_depth: 1.0,
}];
let scissors = [surface_resolution.into()];
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
.scissors(&scissors)
.viewports(&viewports)
.build();
let shader_input_image_extent = vk::Extent2D { let shader_input_image_extent = vk::Extent2D {
width: resolutions.scaled_width, width: resolutions.scaled_width,
height: resolutions.scaled_height, height: resolutions.scaled_height,
@ -475,15 +411,13 @@ impl SwapchainData {
&[], &[],
&[texture_barrier], &[texture_barrier],
); );
let buffer_copy_regions = vk::BufferImageCopy::builder() let buffer_copy_regions = vk::BufferImageCopy::default()
.image_subresource( .image_subresource(
vk::ImageSubresourceLayers::builder() vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR) .aspect_mask(vk::ImageAspectFlags::COLOR)
.layer_count(1) .layer_count(1),
.build(),
) )
.image_extent(shader_input_image_extent.into()) .image_extent(shader_input_image_extent.into());
.build();
device.cmd_copy_buffer_to_image( device.cmd_copy_buffer_to_image(
texture_command_buffer, texture_command_buffer,
@ -557,25 +491,22 @@ impl SwapchainData {
.create_image_view(&shader_input_tex_image_view_info, None) .create_image_view(&shader_input_tex_image_view_info, None)
.unwrap(); .unwrap();
( Self {
Self { swapchain_loader,
swapchain_loader, swapchain,
swapchain, format,
format, surface_resolution,
surface_resolution, present_image_views,
present_image_views, sampler,
sampler, shader_input_texture_memory,
shader_input_texture_memory, shader_input_tex_image_view,
shader_input_tex_image_view, shader_input_image_buffer,
shader_input_image_buffer, shader_input_image_buffer_memory,
shader_input_image_buffer_memory, shader_input_image_buffer_memory_req,
shader_input_image_buffer_memory_req, shader_input_image_extent,
shader_input_image_extent, shader_input_texture,
shader_input_texture, present_images,
present_images, }
},
viewport_state_info,
)
} }
pub(super) unsafe fn manual_drop(&mut self, vulkan: &VulkanData) { pub(super) unsafe fn manual_drop(&mut self, vulkan: &VulkanData) {
@ -619,13 +550,12 @@ impl FramebufferData {
.iter() .iter()
.map(|&present_image_view| { .map(|&present_image_view| {
let framebuffer_attachments = [present_image_view]; let framebuffer_attachments = [present_image_view];
let frame_buffer_create_info = vk::FramebufferCreateInfo::builder() let frame_buffer_create_info = vk::FramebufferCreateInfo::default()
.render_pass(renderpass) .render_pass(renderpass)
.attachments(&framebuffer_attachments) .attachments(&framebuffer_attachments)
.width(swapchain.surface_resolution.width) .width(swapchain.surface_resolution.width)
.height(swapchain.surface_resolution.height) .height(swapchain.surface_resolution.height)
.layers(1) .layers(1);
.build();
vulkan vulkan
.device .device

View file

@ -30,7 +30,7 @@ pub(super) unsafe fn begin_commandbuffer(
command_buffer_reuse_fence: vk::Fence, command_buffer_reuse_fence: vk::Fence,
) { ) {
device device
.wait_for_fences(&[command_buffer_reuse_fence], true, std::u64::MAX) .wait_for_fences(&[command_buffer_reuse_fence], true, u64::MAX)
.expect("Wait for fence failed."); .expect("Wait for fence failed.");
device device
@ -44,9 +44,8 @@ pub(super) unsafe fn begin_commandbuffer(
) )
.expect("Reset command buffer failed."); .expect("Reset command buffer failed.");
let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder() let command_buffer_begin_info =
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT) vk::CommandBufferBeginInfo::default().flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
.build();
device device
.begin_command_buffer(command_buffer, &command_buffer_begin_info) .begin_command_buffer(command_buffer, &command_buffer_begin_info)
@ -68,12 +67,11 @@ pub(super) unsafe fn submit_commandbuffer(
let command_buffers = vec![command_buffer]; let command_buffers = vec![command_buffer];
let submit_info = vk::SubmitInfo::builder() let submit_info = vk::SubmitInfo::default()
.wait_semaphores(wait_semaphores) .wait_semaphores(wait_semaphores)
.wait_dst_stage_mask(wait_mask) .wait_dst_stage_mask(wait_mask)
.command_buffers(&command_buffers) .command_buffers(&command_buffers)
.signal_semaphores(signal_semaphores) .signal_semaphores(signal_semaphores);
.build();
device device
.queue_submit(submit_queue, &[submit_info], command_buffer_reuse_fence) .queue_submit(submit_queue, &[submit_info], command_buffer_reuse_fence)

View file

@ -8,8 +8,11 @@ edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.15", features = ["derive"] } clap = { version = "4.5.15", features = ["derive"] }
strum = { version = "0.26.3", features = ["derive"] } strum = { version = "0.26.3", features = ["derive"] }
xshell = "0.2.6" duct = "0.13.7"
cargo_metadata = "0.18.1" cargo_metadata = "0.18.1"
cfg-expr = "0.16.0"
pbr = "1.1.1"
serde_json = "1.0.125"
nih_plug_xtask = { workspace = true } nih_plug_xtask = { workspace = true }
log = { workspace = true } log = { workspace = true }
env_logger = { workspace = true } env_logger = { workspace = true }

View file

@ -31,12 +31,18 @@ pub enum Commands {
#[derive(clap::Args, Debug)] #[derive(clap::Args, Debug)]
#[command(group(clap::ArgGroup::new("platforms").args(["platform","all_platforms"]).required(true)))] #[command(group(clap::ArgGroup::new("platforms").args(["platform","all_platforms"]).required(true)))]
#[command(group(clap::ArgGroup::new("binaries").args(["binary","all_binaries"]).required(true)))] #[command(group(clap::ArgGroup::new("binaries").args(["binary","all_binaries"]).required(true)))]
#[command(group(clap::ArgGroup::new("architectures").args(["architecture","all_architectures"]).required(true)))]
pub struct BuildArgs { pub struct BuildArgs {
#[arg(long, short)] #[arg(long, short)]
pub platform: Vec<Platform>, pub platform: Vec<Platform>,
#[arg(long)] #[arg(long)]
pub all_platforms: bool, pub all_platforms: bool,
#[arg(long, short)]
pub architecture: Vec<Architecture>,
#[arg(long)]
pub all_architectures: bool,
#[arg(long, short)] #[arg(long, short)]
pub binary: Vec<Binary>, pub binary: Vec<Binary>,
#[arg(long)] #[arg(long)]
@ -51,6 +57,8 @@ pub struct RunArgs {
#[arg(long, short)] #[arg(long, short)]
pub platform: Option<Platform>, pub platform: Option<Platform>,
#[arg(long, short)] #[arg(long, short)]
pub architecture: Option<Architecture>,
#[arg(long, short)]
pub binary: Option<Binary>, pub binary: Option<Binary>,
#[arg(long, short)] #[arg(long, short)]
pub renderer: Option<Renderer>, pub renderer: Option<Renderer>,

View file

@ -1,6 +1,5 @@
use clap::Parser; use clap::Parser;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use xshell::Shell;
use args::*; use args::*;
use types::*; use types::*;
@ -10,18 +9,20 @@ mod types;
static METADATA: std::sync::OnceLock<cargo_metadata::Metadata> = std::sync::OnceLock::new(); static METADATA: std::sync::OnceLock<cargo_metadata::Metadata> = std::sync::OnceLock::new();
static OUTPUT_DIR: std::sync::OnceLock<std::path::PathBuf> = std::sync::OnceLock::new(); static OUTPUT_DIR: std::sync::OnceLock<std::path::PathBuf> = std::sync::OnceLock::new();
fn executable_dir(binary: Binary, platform: Platform, renderer: Renderer) -> String { fn executable_dir(
format!( binary: Binary,
"{}_{}_{}", triple: &cfg_expr::targets::Triple,
binary.name(), renderer: Renderer,
platform.as_target(), ) -> String {
renderer.as_feature() format!("{}_{}_{}", binary.name(), triple, renderer.as_feature())
)
} }
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
if std::env::var("RUST_LOG").is_err() { if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "info"); std::env::set_var(
"RUST_LOG",
"cli=info,frontend_common=info,gb_emu_lib=info,xtask=info",
);
} }
env_logger::init(); env_logger::init();
let args = Args::parse(); let args = Args::parse();
@ -55,27 +56,28 @@ fn build(args: BuildArgs, debug: bool) -> Result<(), Box<dyn std::error::Error>>
} else { } else {
args.platform args.platform
}; };
log::info!("platforms: {platforms:?}");
let architectures = if args.all_architectures {
Architecture::iter().collect()
} else {
args.architecture
};
let binaries = if args.all_binaries { let binaries = if args.all_binaries {
Binary::iter().collect() Binary::iter().collect()
} else { } else {
args.binary args.binary
}; };
log::info!("binaries: {binaries:?}");
let renderers = if args.renderer.is_empty() { let renderers = if args.renderer.is_empty() {
vec![Renderer::Wgpu] vec![Renderer::Wgpu]
} else { } else {
args.renderer args.renderer
}; };
log::info!("renderers: {renderers:?}");
for binary in binaries { for binary in binaries {
for platform in &platforms { for renderer in &renderers {
for renderer in &renderers { build_binary(binary, &platforms, &architectures, *renderer, debug)?;
build_binary(binary, *platform, *renderer, debug)?;
}
} }
} }
@ -84,11 +86,16 @@ fn build(args: BuildArgs, debug: bool) -> Result<(), Box<dyn std::error::Error>>
fn run(args: RunArgs, debug: bool) -> Result<(), Box<dyn std::error::Error>> { fn run(args: RunArgs, debug: bool) -> Result<(), Box<dyn std::error::Error>> {
let platform = args.platform.unwrap_or(Platform::host_platform()); let platform = args.platform.unwrap_or(Platform::host_platform());
let architecture = args
.architecture
.unwrap_or(Architecture::host_architecture());
let triple = get_triple(platform, architecture).unwrap().triple;
let binary = args.binary.unwrap_or(Binary::get_default()); let binary = args.binary.unwrap_or(Binary::get_default());
let renderer = args.renderer.unwrap_or(Renderer::Wgpu); let renderer = args.renderer.unwrap_or(Renderer::Wgpu);
match binary { match binary {
Binary::Gui => run_gui(platform, renderer, debug), Binary::Gui => run_gui(platform, &triple, renderer, debug),
Binary::Cli => run_cli(platform, renderer, debug), Binary::Cli => run_cli(platform, &triple, renderer, debug),
Binary::Vst => { Binary::Vst => {
eprintln!("twinc_emu_vst doesn't support standalone usage!"); eprintln!("twinc_emu_vst doesn't support standalone usage!");
std::process::exit(1); std::process::exit(1);
@ -98,26 +105,81 @@ fn run(args: RunArgs, debug: bool) -> Result<(), Box<dyn std::error::Error>> {
fn build_binary( fn build_binary(
binary: Binary, binary: Binary,
platform: Platform, platforms: &[Platform],
architectures: &[Architecture],
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let output_dir = OUTPUT_DIR
.get()
.unwrap()
.join(executable_dir(binary, platform, renderer));
std::fs::create_dir_all(&output_dir)?;
match binary { match binary {
Binary::Gui => build_gui(output_dir, platform, renderer, debug), Binary::Gui => {
Binary::Cli => build_cli(output_dir, platform, renderer, debug), for (platform, triple) in platforms_and_triples(platforms, architectures) {
Binary::Vst => build_vst(platform, renderer, debug), let output_dir = OUTPUT_DIR
.get()
.unwrap()
.join(executable_dir(binary, &triple, renderer));
std::fs::create_dir_all(&output_dir)?;
build_gui(output_dir, platform, &triple, renderer, debug)?;
}
}
Binary::Cli => {
for (platform, triple) in platforms_and_triples(platforms, architectures) {
let output_dir = OUTPUT_DIR
.get()
.unwrap()
.join(executable_dir(binary, &triple, renderer));
std::fs::create_dir_all(&output_dir)?;
build_cli(output_dir, platform, &triple, renderer, debug)?;
}
}
Binary::Vst => {
log::warn!("TODO: handle vst builds more smarter");
for platform in platforms {
if *platform == Platform::Mac {
build_vst(*platform, None, renderer, debug)?;
} else {
for triple in platform_triples(platform, architectures) {
build_vst(*platform, Some(&triple), renderer, debug)?;
}
}
}
}
} }
Ok(())
}
fn platform_triples<'a>(
platform: &'a Platform,
architectures: &'a [Architecture],
) -> impl Iterator<Item = cfg_expr::targets::Triple> + 'a {
architectures
.iter()
.filter_map(|architecture| get_triple(*platform, *architecture).map(|v| v.triple))
.filter(|triple| {
if is_toolchain_installed(triple) {
true
} else {
log::warn!("toolchain not installed for {triple} - skipping");
false
}
})
}
fn platforms_and_triples(
platforms: &[Platform],
architectures: &[Architecture],
) -> Vec<(Platform, cfg_expr::targets::Triple)> {
platforms
.iter()
.flat_map(|platform| platform_triples(platform, architectures).map(|v| (*platform, v)))
.collect()
} }
fn build_gui( fn build_gui(
output_dir: std::path::PathBuf, output_dir: std::path::PathBuf,
platform: Platform, platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
@ -126,6 +188,7 @@ fn build_gui(
run_build( run_build(
"gui", "gui",
platform, platform,
triple,
renderer, renderer,
debug, debug,
Some(["-F", ui].into_iter().map(String::from).collect()), Some(["-F", ui].into_iter().map(String::from).collect()),
@ -135,6 +198,7 @@ fn build_gui(
fn run_gui( fn run_gui(
platform: Platform, platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
@ -144,6 +208,7 @@ fn run_gui(
"run", "run",
"gui", "gui",
platform, platform,
triple,
renderer, renderer,
debug, debug,
Some(["-F", ui].into_iter().map(String::from).collect()), Some(["-F", ui].into_iter().map(String::from).collect()),
@ -154,14 +219,16 @@ fn run_gui(
fn build_cli( fn build_cli(
output_dir: std::path::PathBuf, output_dir: std::path::PathBuf,
platform: Platform, platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
run_build("cli", platform, renderer, debug, None, output_dir) run_build("cli", platform, triple, renderer, debug, None, output_dir)
} }
fn run_cli( fn run_cli(
platform: Platform, platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
@ -171,13 +238,22 @@ fn run_cli(
.position(|arg| arg == "--") .position(|arg| arg == "--")
.map(|extra_args_index| args[extra_args_index..].to_vec()); .map(|extra_args_index| args[extra_args_index..].to_vec());
let _ = cargo_exec("run", "cli", platform, renderer, debug, additional_flags)?; let _ = cargo_exec(
"run",
"cli",
platform,
triple,
renderer,
debug,
additional_flags,
)?;
Ok(()) Ok(())
} }
fn run_build( fn run_build(
package: &str, package: &str,
platform: Platform, platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
additional_flags: Option<Vec<String>>, additional_flags: Option<Vec<String>>,
@ -187,6 +263,7 @@ fn run_build(
"build", "build",
package, package,
platform, platform,
triple,
renderer, renderer,
debug, debug,
additional_flags, additional_flags,
@ -200,10 +277,25 @@ fn run_build(
Ok(()) Ok(())
} }
static INSTALLED_TRIPLES: std::sync::LazyLock<Vec<String>> = std::sync::LazyLock::new(|| {
match duct::cmd!("rustup", "target", "list", "--installed").read() {
Ok(output) => output.lines().map(String::from).collect(),
Err(e) => {
log::error!("Error listing installed targets: {e:?}");
std::process::exit(0);
}
}
});
fn is_toolchain_installed(triple: &cfg_expr::targets::Triple) -> bool {
INSTALLED_TRIPLES.contains(&triple.to_string())
}
fn cargo_exec( fn cargo_exec(
verb: &str, verb: &str,
package: &str, package: &str,
platform: Platform, _platform: Platform,
triple: &cfg_expr::targets::Triple,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
additional_flags: Option<Vec<String>>, additional_flags: Option<Vec<String>>,
@ -211,12 +303,13 @@ fn cargo_exec(
impl Iterator<Item = std::io::Result<cargo_metadata::Message>>, impl Iterator<Item = std::io::Result<cargo_metadata::Message>>,
Box<dyn std::error::Error>, Box<dyn std::error::Error>,
> { > {
let sh = Shell::new()?;
let target = platform.as_target();
let release = if debug { "" } else { "--release" }; let release = if debug { "" } else { "--release" };
let renderer = renderer.as_feature(); let renderer = renderer.as_feature();
let args=format!("{verb} -p {package} --target {target} {release} --no-default-features -F {renderer} --message-format=json");
println!("Building {package} with {renderer} renderer for target {triple}");
let args=format!("{verb} -q -p {package} --target {triple} {release} --no-default-features -F {renderer} --message-format=json");
let args = args.split_whitespace().map(|s| s.to_string()); let args = args.split_whitespace().map(|s| s.to_string());
let args = if let Some(additional_flags) = additional_flags { let args = if let Some(additional_flags) = additional_flags {
args.chain(additional_flags).collect::<Vec<_>>() args.chain(additional_flags).collect::<Vec<_>>()
@ -224,11 +317,32 @@ fn cargo_exec(
args.collect::<Vec<_>>() args.collect::<Vec<_>>()
}; };
let output = sh.cmd("cargo").args(args).read()?; let build_plan: serde_json::Value = {
let mut args = args.clone();
args.extend_from_slice(&["-Zunstable-options".into(), "--build-plan".into()]);
let output = duct::cmd("cargo", args).read()?;
serde_json::from_str(output.lines().nth(1).unwrap())?
};
Ok(cargo_metadata::Message::parse_stream(std::io::Cursor::new( let num_invocations = build_plan["invocations"].as_array().unwrap().len();
output,
))) let output = duct::cmd("cargo", args).stdout_capture().reader()?;
let mut pb = pbr::ProgressBar::new(num_invocations.try_into().unwrap());
pb.message("Building crate ");
pb.show_time_left = false;
pb.show_speed = false;
Ok(
cargo_metadata::Message::parse_stream(std::io::BufReader::new(output)).inspect(move |v| {
match v {
Ok(cargo_metadata::Message::BuildScriptExecuted(_))
| Ok(cargo_metadata::Message::CompilerArtifact(_)) => {
pb.inc();
}
_ => {}
}
}),
)
} }
fn as_artifact(message: cargo_metadata::Message) -> Option<cargo_metadata::Artifact> { fn as_artifact(message: cargo_metadata::Message) -> Option<cargo_metadata::Artifact> {
@ -241,13 +355,15 @@ fn as_artifact(message: cargo_metadata::Message) -> Option<cargo_metadata::Artif
fn build_vst( fn build_vst(
platform: Platform, platform: Platform,
triple: Option<&cfg_expr::targets::Triple>,
renderer: Renderer, renderer: Renderer,
debug: bool, debug: bool,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let triple_str = triple.map(|t| t.to_string());
let mut args = if platform == Platform::Mac { let mut args = if platform == Platform::Mac {
vec!["bundle-universal"] vec!["bundle-universal"]
} else { } else {
vec!["bundle", "--target", platform.as_target()] vec!["bundle", "--target", triple_str.as_ref().unwrap().as_str()]
}; };
if !debug { if !debug {
args.push("--release"); args.push("--release");

View file

@ -1,3 +1,5 @@
use cfg_expr::expr::TargetMatcher;
#[derive(clap::ValueEnum, Clone, Copy, Debug, strum::EnumIter, PartialEq, Eq)] #[derive(clap::ValueEnum, Clone, Copy, Debug, strum::EnumIter, PartialEq, Eq)]
pub enum Platform { pub enum Platform {
Windows, Windows,
@ -6,11 +8,11 @@ pub enum Platform {
} }
impl Platform { impl Platform {
pub fn as_target(&self) -> &str { pub fn as_cargo(&self) -> cfg_expr::targets::Os {
match self { match self {
Platform::Windows => "x86_64-pc-windows-gnu", Platform::Windows => cfg_expr::targets::Os::windows,
Platform::Linux => "x86_64-unknown-linux-gnu", Platform::Linux => cfg_expr::targets::Os::linux,
Platform::Mac => "aarch64-apple-darwin", Platform::Mac => cfg_expr::targets::Os::macos,
} }
} }
@ -29,7 +31,49 @@ impl Platform {
} else if cfg!(target_os = "linux") { } else if cfg!(target_os = "linux") {
Self::Linux Self::Linux
} else { } else {
todo!() unimplemented!()
}
}
}
pub fn get_triple(
platform: Platform,
architecture: Architecture,
) -> Option<cfg_expr::targets::TargetInfo> {
cfg_expr::targets::ALL_BUILTINS
.iter()
.find(|b| {
b.matches(&cfg_expr::TargetPredicate::Arch(architecture.as_cargo()))
&& b.matches(&cfg_expr::TargetPredicate::Os(platform.as_cargo()))
})
.cloned()
}
#[derive(clap::ValueEnum, Clone, Copy, Debug, strum::EnumIter, PartialEq, Eq)]
pub enum Architecture {
Aarch64,
X86,
X86_64,
}
impl Architecture {
pub fn as_cargo(&self) -> cfg_expr::targets::Arch {
match self {
Architecture::Aarch64 => cfg_expr::targets::Arch::aarch64,
Architecture::X86_64 => cfg_expr::targets::Arch::x86_64,
Architecture::X86 => cfg_expr::targets::Arch::x86,
}
}
pub fn host_architecture() -> Self {
if cfg!(target_arch = "x86_64") {
Self::X86_64
} else if cfg!(target_arch = "aarch64") {
Self::Aarch64
} else if cfg!(target_arch = "x86") {
Self::X86
} else {
unimplemented!()
} }
} }
} }