I have a problem with this code:
extern crate piston_window;
extern crate find_folder;
extern crate gfx_graphics;
extern crate gfx;
extern crate gfx_device_gl;
use piston_window::*;
use gfx_device_gl::{Resources, Output, CommandBuffer};
use gfx_graphics::GfxGraphics;
struct Object {
x: f64,
y: f64,
sprite: Option<Texture<Resources>>,
}
impl Object {
fn new() -> Object {
Object {
x: 0.0,
y: 0.0,
sprite: None,
}
}
fn mov(&mut self, x: f64, y: f64) {
self.x = x;
self.y = y;
}
fn render(&self,
g: &mut GfxGraphics<Resources, CommandBuffer<Resources>, Output>,
view: math::Matrix2d) {
let square = rectangle::square(0.0, 0.0, 100.0);
let red = [1.0, 0.0, 0.0, 1.0];
match self.sprite {
None => {
rectangle(red,
square,
view.trans(self.x, self.y).trans(-50.0, -50.0),
g);
}
Some(ref sprite) => {
image(sprite, view.trans(self.x, self.y).trans(-50.0, -50.0), g);
}
}
}
fn setSprite(&mut self, sprite: Texture<Resources>) {
self.sprite = Some(sprite);
}
}
struct Game {
position: f64,
one: bool,
two: bool,
three: bool,
four: bool,
five: bool,
six: bool,
seven: bool,
eight: bool,
nine: bool,
player: Object,
}
impl Game {
fn new() -> Game {
Game {
rotation: 0.0,
player: Object::new(),
one: false,
two: false,
three: false,
four: false,
five: false,
six: false,
seven: false,
eight: false,
nine: false,
}
}
fn on_load(&mut self, w: &PistonWindow) {
let assets = find_folder::Search::ParentsThenKids(3, 3) //Cerca la cartella assets
.for_folder("assets").unwrap();
let tris = assets.join("x.png");
let tris = Texture::from_path(&mut *w.factory, &tris, Flip::None, &TextureSettings::new())
.unwrap();
self.player.setSprite(tris);
}
fn on_update(&mut self, upd: UpdateArgs) {
self.position += 3.0 * upd.dt;
if self.one {
self.player.mov(100.0, 100.0);
}
if self.two {
self.player.mov(100.0, 200.0);
}
if self.three {
self.player.mov(100.0, 300.0);
}
if self.four {
self.player.mov(200.0, 100.0);
}
if self.five {
self.player.mov(300.0, 100.0);
}
if self.six {
self.player.mov(200.0, 200.0);
}
if self.seven {
self.player.mov(200.0, 300.0);
}
if self.eight {
self.player.mov(300.0, 200.0);
}
if self.nine {
self.player.mov(300.0, 300.0);
}
}
fn on_draw(&mut self, ren: RenderArgs, e: PistonWindow) {
e.draw_2d(|c, g| {
clear([0.0, 0.0, 0.0], g);
let center = c.transf((ren.width / 2) as f64, (ren.eight / 2) as f64);
self.player.render(g, center);
});
}
fn on_input(&mut self, inp: Input) {
match inp {
Input::Press(but) => {
match but {
Button::Keyboard(Key::D1) => {
self.one = true;
}
Button::Keyboard(Key::D2) => {
self.two = true;
}
Button::Keyboard(Key::D3) => {
self.three = true;
}
Button::Keyboard(Key::D4) => {
self.four = true;
}
Button::Keyboard(Key::D5) => {
self.five = true;
}
Button::Keyboard(Key::D6) => {
self.six = true;
}
Button::Keyboard(Key::D7) => {
self.seven = true;
}
Button::Keyboard(Key::D8) => {
self.eight = true;
}
Button::Keyboard(Key::D9) => {
self.nine = true;
}
_ => {}
}
}
}
}
}
fn main() {
let title = "Tris"; //Titolo della finestra
let mut window: PistonWindow = WindowSettings::new(title, [800, 600]) //Crea la finestra
.exit_on_esc(true)
.build()
.unwrap_or_else(|e| { panic!("Failed to build PistonWindow: {}", e) });
let mut game = Game::new();
game.on_load(&window);
let assets = find_folder::Search::ParentsThenKids(3, 3) //Cerca la cartella assets
.for_folder("assets").unwrap();
let tris = assets.join("tris.png");
let tris = Texture::from_path(&mut window.factory,
&tris,
Flip::None,
&TextureSettings::new())
.unwrap();
let x = assets.join("x.png");
let x = Texture::from_path(&mut window.factory, &x, Flip::None, &TextureSettings::new())
.unwrap();
let o = assets.join("o.png");
let o = Texture::from_path(&mut window.factory, &o, Flip::None, &TextureSettings::new())
.unwrap();
while let Some(e) = window.next() {
// Inizia il ciclo e disegna la roba sotto
window.draw_2d(&e, |c, g| {
clear([0.0, 0.0, 0.0, 0.0], g);
image(&tris, c.transform, g);
});
match e.event {
Some(Event::Update(upd)) => {
game.on_update(upd);
}
Some(Event::Render(ren)) => {
game.on_draw(ren, e);
}
Some(Event::Input(inp)) => {
game.on_input(inp);
}
_ => {}
}
}
}
(Playground)
When I try to compile it, it says the error:
the trait bound `gfx_device_gl::Resources: gfx_core::Resources` is not
satisfied [E0277]
src/main.rs:14 sprite: Option<Texture<Resources>>,
And the second error:
error: the trait bound `gfx_device_gl::Resources: gfx_core::Resources`
is not satisfied [E0277]
src/main.rs:39 fn setSprite(&mut self, sprite: Texture<Resources>) {
src/main.rs:40 self.sprite = Some(sprite);
src/main.rs:41 }
How should I fix it? I looked online but found nothing about it.
I was getting an identical compile error on very similar code and setting
gfx_device_gl = "=0.9.0"
in Cargo.toml caused it to stop happening for me. Previously, I was using 0.11.0.
After changing this, I get other (I believe separate/independent) compilation errors, but perhaps this solves your predicament.
Related
I have a Companion trait that encompasses a base trait for Components such as Health. I store a list of Companion using trait objects because all companions must at least implement the Companion trait. However not all companions will use the subtype Health trait.
Now the heal command only accepts a list of Health traits, so I need to filter out, remap and downcast all the base Companion traits so that it supports the Health traits.
I understand this is bad design. How can I implement the same behavior without having to downcast the trait objects to a specific component? Note: I cannot have a large struct which includes all the subtypes into one type.
Here's the code I have so far:
type CompanionId = Uuid;
fn main() {
let mut companion_storage: HashMap<CompanionId, Box<dyn Companion>> = HashMap::new();
let companion_id: CompanionId = Uuid::new_v4();
companion_storage.insert(
companion_id,
Box::new(Cheetah {
...
}),
);
let mut player = Player {
...,
companions: Vec::new(),
};
player.companions.push(companion_id);
'GameLoop: loop {
let input = poll_input().trim().to_lowercase();
match input.as_str() {
// TODO: Extract healing component here.
"heal" => heal_command(companion_id, companion_storage.into_iter().filter(|(companion_id, companion)| {
// QUESTION: How do I filter out Companions without the Health trait here so they can automatically be downcasted and mapped?
}).collect()),
"q" => {
break 'GameLoop;
}
"s" => {
status_command(&player, &companion_storage); // SAME PROBLEM HERE
}
_ => println!("Unknown command"),
}
}
}
struct Player {
id: u8,
name: String,
companions: Vec<CompanionId>,
}
trait Companion {
...
}
trait Health: Companion {
...
}
trait Status: Health {}
struct Cheetah {
id: CompanionId,
name: String,
current_health: f32,
max_health: f32,
}
impl Companion for Cheetah {
...
}
impl Health for Cheetah {
...
}
fn heal_command(
companion_id: CompanionId,
companion_storage: &mut HashMap<CompanionId, Box<dyn Health>>,
) {
let companion = companion_storage.get_mut(&companion_id).unwrap();
companion.heal_max();
println!("Healed to max.");
}
fn status_command(player: &Player, companion_storage: &mut HashMap<CompanionId, Box<dyn Status>>) {
println!("Status for {}: ", player.name);
println!("===============================");
print!("Companions: ");
for companion_id in &player.companions {
let companion = companion_storage.get(companion_id).unwrap();
print!(
"{} [{}/{}], ",
companion.name(),
companion.health(),
companion.max_health()
);
}
println!();
println!("===============================");
}
Is this code a better alternative?
type CompanionId = Uuid;
fn main() {
let mut companion_storage: HashMap<CompanionId, Companion> = HashMap::new();
let companion_id: CompanionId = Uuid::new_v4();
companion_storage.insert(
companion_id,
Companion {
id: companion_id,
name: "Cheetah".to_string(),
health: Some(Box::new(RegularHealth {
current_health: 50.0,
max_health: 50.0,
})),
},
);
let mut player = Player {
id: 0,
name: "FyiaR".to_string(),
companions: Vec::new(),
};
player.companions.push(companion_id);
'GameLoop: loop {
let input = poll_input().trim().to_lowercase();
match input.as_str() {
// TODO: Extract healing component here.
"heal" => {
let companion = companion_storage.get_mut(&companion_id).unwrap();
match companion.health_mut() {
None => {
println!("The selected companion doesn't have health associated with it.");
}
Some(health) => {
heal_command(health);
println!("{} was healed to max.", companion.name);
}
}
}
"q" => {
break 'GameLoop;
}
"s" => {
status_command(&player, &companion_storage); // SAME PROBLEM HERE
}
_ => println!("Unknown command"),
}
}
}
struct Player {
id: u8,
name: String,
companions: Vec<CompanionId>,
}
struct Companion {
id: CompanionId,
name: String,
health: Option<Box<dyn Health>>,
}
struct RegularHealth {
current_health: f32,
max_health: f32,
}
trait Health {
...
}
impl Companion {
fn health_mut(&mut self) -> Option<&mut dyn Health> {
match self.health.as_mut() {
None => None,
Some(health) => Some(health.as_mut()),
}
}
fn health(&self) -> Option<&dyn Health> {
match self.health.as_ref() {
None => None,
Some(health) => Some(health.as_ref()),
}
}
}
impl Health for RegularHealth {
...
}
fn heal_command(health: &mut dyn Health) {
health.heal_max();
}
fn status_command(player: &Player, companion_storage: &HashMap<CompanionId, Companion>) {
println!("Status for {}: ", player.name);
println!("===============================");
print!("Companions: ");
for companion_id in &player.companions {
let companion = companion_storage.get(companion_id).unwrap();
match companion.health.as_ref() {
None => {}
Some(health) => {
print!(
"{} [{}/{}], ",
companion.name,
health.health(),
health.max_health()
);
}
}
}
println!();
println!("===============================");
}
Don't ask why I'm learning Rust using linked lists. I want to mutably iterate down a recursive structure of Option<Rc<RefCell<Node>>> while keeping the ability to swap out nodes and unwrap them. I have a singly-linked list type with a tail pointer to the last node.
pub struct List<T> {
maybe_head: Option<Rc<RefCell<Node<T>>>>,
maybe_tail: Option<Rc<RefCell<Node<T>>>>,
length: usize,
}
struct Node<T> {
value: T,
maybe_next: Option<Rc<RefCell<Node<T>>>>,
}
Let's say we have a constructor and an append function:
impl<T> List<T> {
pub fn new() -> Self {
List {
maybe_head: None,
maybe_tail: None,
length: 0,
}
}
pub fn put_first(&mut self, t: T) -> &mut Self {
let new_node_rc = Rc::new(RefCell::new(Node {
value: t,
maybe_next: mem::replace(&mut self.maybe_head, None),
}));
match self.length == 0 {
true => {
let new_node_rc_clone = new_node_rc.clone();
self.maybe_head = Some(new_node_rc);
self.maybe_tail = Some(new_node_rc_clone);
},
false => {
self.maybe_head = Some(new_node_rc);
},
}
self.length += 1;
self
}
}
I want to remove and return the final node by moving the tail pointer to its predecessor, then returning the old tail. After iterating down the list using RefCell::borrow() and Rc::clone(), the first version of remove_last() below panics when trying to unwrap the tail's Rc. How do I iterate down this recursive structure without incrementing each node's strongcount?
PANICKING VERSION
pub fn remove_last(&mut self) -> Option<T> {
let mut opt: Option<Rc<RefCell<Node<T>>>>;
if let Some(rc) = &self.maybe_head {
opt = Some(Rc::clone(rc))
} else {
return None;
};
let mut rc: Rc<RefCell<Node<T>>>;
let mut countdown_to_penultimate: i32 = self.length as i32 - 2;
loop {
rc = match opt {
None => panic!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
match RefCell::borrow(&rc).maybe_next {
Some(ref next_rc) => {
if countdown_to_penultimate == 0 {
self.maybe_tail = Some(Rc::clone(x));
}
opt = Some(Rc::clone(next_rc));
countdown_to_penultimate -= 1;
},
None => {
let grab_tail = match Rc::try_unwrap(opt.take().unwrap()) {
Ok(something) => {
return Some(something.into_inner().value);
}
Err(_) => panic!(),
};
},
}
}
If all I do during iteration is move the tail pointer and enclose the iteration code in a {...} block to drop cloned references, I can then safely swap out and return the old tail, but this is obviously unsatisfying.
UNSATISFYING WORKING VERSION
pub fn remove_last(&mut self) -> Option<T> {
{let mut opt: Option<Rc<RefCell<Node<T>>>>;
if let Some(rc) = &self.maybe_head {
opt = Some(Rc::clone(rc))
} else {
return None;
};
let mut rc: Rc<RefCell<Node<T>>>;
let mut countdown_to_penultimate: i32 = self.length as i32 - 2;
loop {
rc = match opt {
None => panic!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
match RefCell::borrow(&rc).maybe_next {
Some(ref next_rc) => {
if countdown_to_penultimate == 0 {
self.maybe_tail = Some(Rc::clone(&rc));
}
opt = Some(Rc::clone(next_rc));
countdown_to_penultimate -= 1;
},
None => {
break;
},
}
}}
match self.maybe_tail {
None => panic!(),
Some(ref rc) => {
let tail = mem::replace(&mut RefCell::borrow_mut(rc).maybe_next, None);
return Some(Rc::try_unwrap(tail.unwrap()).ok().unwrap().into_inner().value);
}
};
}
I wrote a List::remove_last() that I can live with, although I'd still like to know what more idiomatic Rust code here might look like. I find that this traversal idiom also extends naturally into things like removing the n-th node or removing the first node that matches some predicate.
fn remove_last(&mut self) -> Option<T> {
let mut opt: Option<Rc<RefCell<Node<T>>>>;
let mut rc: Rc<RefCell<Node<T>>>;
#[allow(unused_must_use)]
match self.length {
0 => {
return None;
}
1 => {
let head = mem::replace(&mut self.maybe_head, None);
mem::replace(&mut self.maybe_tail, None);
self.length -= 1;
return Some(
Rc::try_unwrap(head.unwrap())
.ok()
.unwrap()
.into_inner()
.value,
);
}
_ => {
opt = Some(Rc::clone(self.maybe_head.as_ref().unwrap()));
}
}
loop {
rc = match opt {
None => unreachable!(),
Some(ref wrapped_rc) => Rc::clone(wrapped_rc),
};
let mut borrowed_node = RefCell::borrow_mut(&rc);
let maybe_next = &mut borrowed_node.maybe_next;
match maybe_next {
None => unreachable!(),
Some(_)
if std::ptr::eq(
maybe_next.as_ref().unwrap().as_ptr(),
self.maybe_tail.as_ref().unwrap().as_ptr(),
) =>
{
borrowed_node.maybe_next = None;
let old_tail = self.maybe_tail.replace(Rc::clone(&rc));
self.length -= 1;
return Some(
Rc::try_unwrap(old_tail.unwrap())
.ok()
.unwrap()
.into_inner()
.value,
);
}
Some(ref next_rc) => {
opt = Some(Rc::clone(next_rc));
}
}
}
}
I'm using Rust and the Rust-based Vulkan wrapper Erupt.
Everything in this code runs fine until the device.map_memory call. No VulkanValidation warnings or errors are raised. Just a segmentation fault. I have offsets set to zero, but this is the only memory usage of this buffer, so I'm not sure if the issue is offsets or something else.
use memoffset::offset_of;
use simple_logger::SimpleLogger;
use winit::{
event::{
Event, KeyboardInput, WindowEvent,
ElementState, StartCause, VirtualKeyCode
},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
window::Window
};
// use winit::event::{ElementState, StartCause, VirtualKeyCode};
use structopt::StructOpt;
use erupt::{
cstr,
utils::{self, surface},
vk, DeviceLoader, EntryLoader, InstanceLoader,
};
use std::{
ffi::{c_void, CStr, CString},
mem::*,
os::raw::c_char,
ptr,
result::Result,
result::Result::*,
string::String,
thread,
time,
};
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
const TITLE: &str = "Peregrine Ray-Trace";
const FRAMES_IN_FLIGHT: usize = 2;
const LAYER_KHRONOS_VALIDATION: *const c_char = cstr!("VK_LAYER_KHRONOS_validation");
#[derive(Debug, StructOpt)]
struct Opt {
/// Use validation layers
#[structopt(short, long)]
validation_layers: bool,
}
unsafe extern "system" fn debug_callback(
_message_severity: vk::DebugUtilsMessageSeverityFlagBitsEXT,
_message_types: vk::DebugUtilsMessageTypeFlagsEXT,
p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
_p_user_data: *mut c_void,
) -> vk::Bool32 {
eprintln!(
"Vulkan: {}",
CStr::from_ptr((*p_callback_data).p_message).to_string_lossy()
);
vk::FALSE
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
struct VertexV3 {
pos: [f32; 4],
color: [f32; 4],
}
impl VertexV3 {
fn get_binding_descriptions() -> [vk::VertexInputBindingDescription; 1] {
[vk::VertexInputBindingDescription {
binding: 0,
stride: std::mem::size_of::<Self>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}]
}
pub fn get_attribute_descriptions() -> [vk::VertexInputAttributeDescription; 2] {
[
vk::VertexInputAttributeDescription {
binding: 0,
location: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: offset_of!(Self, pos) as u32,
},
vk::VertexInputAttributeDescription {
binding: 0,
location: 1,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: offset_of!(Self, color) as u32,
},
]
}
}
fn main() {
println!("Ray-Peregrine Lab 24::::!!!!");
let mut vulkan_output = String::from("");
println!("Ray-EE-Oct-12");
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_title("Peregrine Ray-Trace")
.build(&event_loop)
.unwrap();
let entry = EntryLoader::new().unwrap();
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
let application_name = CString::new("Peregrine Ray-Trace").unwrap();
let engine_name = CString::new("Vulkan Engine").unwrap();
let app_info = vk::ApplicationInfoBuilder::new()
.application_name(&application_name)
.application_version(vk::make_api_version(0, 1, 0, 0))
.engine_name(&engine_name)
.engine_version(vk::make_api_version(0, 1, 0, 0))
.api_version(vk::make_api_version(0, 1, 0, 0));
let mut instance_extensions = surface::enumerate_required_extensions(&window).unwrap();
instance_extensions.push(vk::EXT_DEBUG_UTILS_EXTENSION_NAME);
let mut instance_layers = Vec::new();
instance_layers.push(LAYER_KHRONOS_VALIDATION);
let device_extensions = vec![
vk::KHR_SWAPCHAIN_EXTENSION_NAME,
vk::KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,
vk::KHR_RAY_QUERY_EXTENSION_NAME,
vk::KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,
vk::KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
vk::KHR_SPIRV_1_4_EXTENSION_NAME,
];
let mut device_layers = Vec::new();
device_layers.push(LAYER_KHRONOS_VALIDATION);
let instance_info = vk::InstanceCreateInfoBuilder::new()
.application_info(&app_info)
.enabled_extension_names(&instance_extensions)
.enabled_layer_names(&instance_layers);
let instance = unsafe { InstanceLoader::new(&entry, &instance_info, None) }.unwrap();
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers
// if opt.validation_layers ...
let messenger = {
let messenger_info = vk::DebugUtilsMessengerCreateInfoEXTBuilder::new()
.message_severity(
vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE_EXT
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT
| vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT,
)
.message_type(
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL_EXT
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION_EXT
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE_EXT,
)
.pfn_user_callback(Some(debug_callback));
unsafe { instance.create_debug_utils_messenger_ext(&messenger_info, None) }.unwrap()
};
let surface = unsafe { surface::create_surface(&instance, &window, None) }.unwrap();
let (physical_device, queue_family, format, present_mode, device_properties) =
unsafe { instance.enumerate_physical_devices(None) }
.unwrap()
.into_iter()
.filter_map(|physical_device| unsafe {
// println!("Physical Device: {:?}", physical_device);
// println!("Phyisical Device Queue Family Properties: {:?}", instance.get_physical_device_properties(physical_device));
let queue_family = match instance
.get_physical_device_queue_family_properties(physical_device, None)
.into_iter()
.enumerate()
.position(|(i, queue_family_properties)| {
queue_family_properties
.queue_flags
.contains(vk::QueueFlags::GRAPHICS)
&& instance
.get_physical_device_surface_support_khr(
physical_device,
i as u32,
surface,
)
.unwrap()
}) {
Some(queue_family) => queue_family as u32,
None => return None,
};
let formats = instance
.get_physical_device_surface_formats_khr(physical_device, surface, None)
.unwrap();
let format = match formats
.iter()
.find(|surface_format| {
surface_format.format == vk::Format::B8G8R8A8_SRGB
&& surface_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR_KHR
})
.or_else(|| formats.get(0))
{
Some(surface_format) => *surface_format,
None => return None,
};
let present_mode = instance
.get_physical_device_surface_present_modes_khr(physical_device, surface, None)
.unwrap()
.into_iter()
.find(|present_mode| present_mode == &vk::PresentModeKHR::MAILBOX_KHR)
.unwrap_or(vk::PresentModeKHR::FIFO_KHR);
let supported_device_extensions = instance
.enumerate_device_extension_properties(physical_device, None, None)
.unwrap();
let device_extensions_supported =
device_extensions.iter().all(|device_extension| {
let device_extension = CStr::from_ptr(*device_extension);
supported_device_extensions.iter().any(|properties| {
CStr::from_ptr(properties.extension_name.as_ptr()) == device_extension
})
});
if !device_extensions_supported {
return None;
}
let device_properties = instance.get_physical_device_properties(physical_device);
Some((
physical_device,
queue_family,
format,
present_mode,
device_properties,
))
})
.max_by_key(|(_, _, _, _, properties)| match properties.device_type {
vk::PhysicalDeviceType::DISCRETE_GPU => 2,
vk::PhysicalDeviceType::INTEGRATED_GPU => 1,
_ => 0,
})
.expect("No suitable physical device found");
//end of declaration of enum (physical_device, queue_family, format, present_mode, device_properties)
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Logical_device_and_queues
let queue_info = vec![vk::DeviceQueueCreateInfoBuilder::new()
.queue_family_index(queue_family)
.queue_priorities(&[1.0])];
let features = vk::PhysicalDeviceFeaturesBuilder::new();
let device_info = vk::DeviceCreateInfoBuilder::new()
.queue_create_infos(&queue_info)
.enabled_features(&features)
.enabled_extension_names(&device_extensions)
.enabled_layer_names(&device_layers);
let device =
unsafe { DeviceLoader::new(&instance, physical_device, &device_info, None) }.unwrap();
// let queue2 = unsafe { device2.get_device_queue(queue_family, 0) };
let queue = unsafe { device.get_device_queue(queue_family, 0) };
println!("\n \n");
let model_path: &'static str = "assets/terrain__002__.obj";
let (models, materials) = tobj::load_obj(&model_path, &tobj::LoadOptions::default()).expect("Failed to load model object!");
let model = models[0].clone();
let materials = materials.unwrap();
let material = materials.clone().into_iter().nth(0).unwrap();
let mut vertices = vec![];
let mut indices = vec![];
let mesh = model.mesh;
let total_vertices_count = mesh.positions.len() / 3;
for i in 0..total_vertices_count {
let vertex = VertexV3 {
pos: [
mesh.positions[i * 3],
mesh.positions[i * 3 + 1],
mesh.positions[i * 3 + 2],
1.0,
],
color: [1.0, 1.0, 1.0, 1.0],
};
vertices.push(vertex);
};
indices = mesh.indices.clone();
println!("Starting buffer and memory allocation/mapping processes... \n");
let vertex_buffer_size = ::std::mem::size_of_val(&vertices) as vk::DeviceSize;
println!("vertex_buffer_size: {:?}", vertex_buffer_size);
let physical_device_memory_properties = unsafe { instance.get_physical_device_memory_properties(physical_device) };
println!("\n physical_device_memory_properties: {:?}", physical_device_memory_properties);
pretty_print(physical_device_memory_properties);
let vertex_buffer_create_info = vk::BufferCreateInfoBuilder::new()
.size(vertex_buffer_size * 8)
.usage(vk::BufferUsageFlags::VERTEX_BUFFER)
.sharing_mode(vk::SharingMode::EXCLUSIVE);
println!("\n vertex_buffer_create_info: {:?}", vertex_buffer_create_info);
let vertex_buffer = unsafe {
device
.create_buffer(&vertex_buffer_create_info, None)
.expect("Failed to create vertex buffer.")
};
let vertex_buffer_memory_reqs = unsafe {
device
.get_buffer_memory_requirements(vertex_buffer)
};
println!("\n vertex_buffer_memory_reqs: {:?}", vertex_buffer_memory_reqs);
let vertex_buffer_memory_allocate_info = unsafe {
vk::MemoryAllocateInfoBuilder::new()
.allocation_size(vertex_buffer_memory_reqs.size)
.memory_type_index(2)
.build()
};
println!("\n vertex_buffer_memory_allocate_info, {:?} \n", vertex_buffer_memory_allocate_info);
let vertex_buffer_memory = unsafe {
device
.allocate_memory(&vertex_buffer_memory_allocate_info, None)
.expect("Failed to allocate vertex buffer memory.")
};
println!("\n vertex_buffer_memory: {:?} \n", &vertex_buffer_memory);
unsafe { device.bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0) }
.expect("Error on bind buffer memory");
unsafe {
let mut pointer: *mut *mut std::ffi::c_void = std::ptr::null_mut();
device
.map_memory(
vertex_buffer_memory,
0,
vertex_buffer_memory_reqs.size,
None,
pointer,
)
.expect("failed to map 333memory.");
}
}
fn pretty_print(stuff: vk::PhysicalDeviceMemoryProperties) {
println!("\n pretty_print physical_device_memory_properties: \n");
for memory_type in stuff.memory_types {
println!("memory type: {:?}", memory_type);
}
for heap in stuff.memory_heaps {
println!("memory heap: {:?}", heap);
}
}
With help from friz64 on the Erupt GameDev board:
I was derefencing a null pointer.
The pointer needed to be *mut rather than *mut *mut, and then take a mutable reference from it.
The block around map_memory should look like this:
unsafe {
let mut pointer: *mut std::ffi::c_void = std::ptr::null_mut();
let mut ref1 = &mut pointer;
device
.map_memory(
vertex_buffer_memory,
256,
vk::WHOLE_SIZE,
None,
ref1,
)
.expect("failed to map 333memory.");
}
I'm writing a process memory scanner with a console prompt interface in Rust.
I need scanner types such as a winapi scanner or a ring0 driver scanner so I'm trying to implement polymorphism.
I have the following construction at this moment:
pub trait Scanner {
fn attach(&mut self, pid: u32) -> bool;
fn detach(&mut self);
}
pub struct WinapiScanner {
pid: u32,
hprocess: HANDLE,
addresses: Vec<usize>
}
impl WinapiScanner {
pub fn new() -> WinapiScanner {
WinapiScanner {
pid: 0,
hprocess: 0 as HANDLE,
addresses: Vec::<usize>::new()
}
}
}
impl Scanner for WinapiScanner {
fn attach(&mut self, pid: u32) -> bool {
let handle = unsafe { OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) };
if handle == 0 as HANDLE {
self.pid = pid;
self.hprocess = handle;
true
} else {
false
}
}
fn detach(&mut self) {
unsafe { CloseHandle(self.hprocess) };
self.pid = 0;
self.hprocess = 0 as HANDLE;
self.addresses.clear();
}
}
In future, I'll have some more scanner types besides WinapiScanner, so, if I understand correctly, I should use a trait reference (&Scanner) to implement polymorphism. I'm trying to create Scanner object like this (note the comments):
enum ScannerType {
Winapi
}
pub fn start() {
let mut scanner: Option<&mut Scanner> = None;
let mut scanner_type = ScannerType::Winapi;
loop {
let line = prompt();
let tokens: Vec<&str> = line.split_whitespace().collect();
match tokens[0] {
// commands
"scanner" => {
if tokens.len() != 2 {
println!("\"scanner\" command takes 1 argument")
} else {
match tokens[1] {
"list" => {
println!("Available scanners: winapi");
},
"winapi" => {
scanner_type = ScannerType::Winapi;
println!("Scanner type set to: winapi");
},
x => {
println!("Unknown scanner type: {}", x);
}
}
}
},
"attach" => {
if tokens.len() > 1 {
match tokens[1].parse::<u32>() {
Ok(pid) => {
scanner = match scanner_type {
// ----------------------
// Problem goes here.
// Object, created by WinapiScanner::new() constructor
// doesn't live long enough to borrow it here
ScannerType::Winapi => Some(&mut WinapiScanner::new())
// ----------------------
}
}
Err(_) => {
println!("Wrong pid");
}
}
}
},
x => println!("Unknown command: {}", x)
}
}
}
fn prompt() -> String {
use std::io::Write;
use std::io::BufRead;
let stdout = io::stdout();
let mut lock = stdout.lock();
let _ = lock.write(">> ".as_bytes());
let _ = lock.flush();
let stdin = io::stdin();
let mut lock = stdin.lock();
let mut buf = String::new();
let _ = lock.read_line(&mut buf);
String::from(buf.trim())
}
It's not a full program; I've pasted important parts only.
What am I doing wrong and how do I implement what I want in Rust?
Trait objects must be used behind a pointer. But references are not the only kind of pointers; Box is also a pointer!
let mut scanner: Option<Box<Scanner>> = None;
scanner = match scanner_type {
ScannerType::Winapi => Some(Box::new(WinapiScanner::new()))
}
Is there a Rust equivalent to the system function in the C/C++ standard library? Specifically I am trying to use cls to clear the command line.
You could use C's system function through the libc crate. But fortunately there's a much better way: std::process::Command.
A quick and dirty way to call cls would be
if std::process::Command::new("cls").status().unwrap().success() {
println!("screen successfully cleared");
}
The mentioned methods did not work for me
The following method works in windows cmd
Cargo.toml
[dependencies]
winapi = "0.2.8"
kernel32-sys = "0.2.1"
Code
extern crate kernel32;
extern crate winapi;
use winapi::HANDLE;
use winapi::wincon::CONSOLE_SCREEN_BUFFER_INFO;
use winapi::wincon::COORD;
use winapi::wincon::SMALL_RECT;
use winapi::WORD;
use winapi::DWORD;
static mut CONSOLE_HANDLE: Option<HANDLE> = None;
fn get_output_handle() -> HANDLE {
unsafe {
if let Some(handle) = CONSOLE_HANDLE {
return handle;
} else {
let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
CONSOLE_HANDLE = Some(handle);
return handle;
}
}
}
fn get_buffer_info() -> winapi::CONSOLE_SCREEN_BUFFER_INFO {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
let mut buffer = CONSOLE_SCREEN_BUFFER_INFO {
dwSize: COORD { X: 0, Y: 0 },
dwCursorPosition: COORD { X: 0, Y: 0 },
wAttributes: 0 as WORD,
srWindow: SMALL_RECT {
Left: 0,
Top: 0,
Right: 0,
Bottom: 0,
},
dwMaximumWindowSize: COORD { X: 0, Y: 0 },
};
unsafe {
kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer);
}
buffer
}
fn clear() {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
let screen_buffer = get_buffer_info();
let console_size: DWORD = screen_buffer.dwSize.X as u32 * screen_buffer.dwSize.Y as u32;
let coord_screen = COORD { X: 0, Y: 0 };
let mut amount_chart_written: DWORD = 0;
unsafe {
kernel32::FillConsoleOutputCharacterW(
handle,
32 as winapi::WCHAR,
console_size,
coord_screen,
&mut amount_chart_written,
);
}
set_cursor_possition(0, 0);
}
fn set_cursor_possition(y: i16, x: i16) {
let handle = get_output_handle();
if handle == winapi::INVALID_HANDLE_VALUE {
panic!("NoConsole")
}
unsafe {
kernel32::SetConsoleCursorPosition(handle, COORD { X: x, Y: y });
}
}
Example
fn main() {
loop {
let mut input = String::new();
std::io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
println!("You typed: {}", input);
if input.trim() == "clear" {
clear();
}
}
}
oli_obk, actually I think this is correct - it worked for me with Rust on Linux:
assert!( std::process::Command::new("cls").status().or_else(|_| std::process::Command::new("clear").status()).unwrap().success() );
status() has to be used twice.
(Put the code line above inside a function like main.)