From b2dc1911467f2c7f5c4419dcaa92dc5e19663f4d Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 27 Jun 2018 18:24:49 -0400 Subject: [PATCH 1/4] Avoid allocation on vertex buffer binding --- Makefile | 5 ++++- examples/quad/main.rs | 6 +++--- src/backend/dx11/src/lib.rs | 11 ++++++++--- src/backend/dx12/src/command.rs | 14 ++++++++++---- src/backend/empty/src/lib.rs | 6 +++++- src/backend/gl/src/command.rs | 25 ++++++++++++++----------- src/backend/metal/src/command.rs | 27 ++++++++++++++++++++------- src/backend/vulkan/src/command.rs | 14 +++++++++----- src/hal/src/command/graphics.rs | 13 ++++++++----- src/hal/src/command/raw.rs | 5 ++++- src/hal/src/command/render_pass.rs | 8 ++++++-- src/hal/src/pso/input_assembler.rs | 17 +---------------- src/warden/src/gpu.rs | 6 ++---- 13 files changed, 94 insertions(+), 63 deletions(-) diff --git a/Makefile b/Makefile index fb5b5e1a14a..e4b3998b61d 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ else endif -.PHONY: all check test reftests travis-sdl2 +.PHONY: all check quad test reftests travis-sdl2 all: check test @@ -62,6 +62,9 @@ reftests-ci: cd src/warden && cargo test --features "gl" cd src/warden && cargo run --features "gl" -- ci #TODO: "gl-headless" +quad: + cd examples && cargo run --bin quad --features ${FEATURES_HAL} + travis-sdl2: #TODO #if [ -e $(SDL2_CONFIG) ]; then exit 1; fi diff --git a/examples/quad/main.rs b/examples/quad/main.rs index 306e34a9c10..02ae289bc59 100644 --- a/examples/quad/main.rs +++ b/examples/quad/main.rs @@ -30,8 +30,8 @@ use hal::pso::{PipelineStage, ShaderStageFlags, Specialization}; use hal::queue::Submission; use std::fs; -use std::io::Cursor; -use std::io::Read; +use std::io::{Cursor, Read}; + const ENTRY_NAME: &str = "main"; @@ -480,7 +480,7 @@ fn main() { cmd_buffer.set_viewports(0, &[viewport.clone()]); cmd_buffer.set_scissors(0, &[viewport.rect]); cmd_buffer.bind_graphics_pipeline(&pipeline); - cmd_buffer.bind_vertex_buffers(0, pso::VertexBufferSet(vec![(&vertex_buffer, 0)])); + cmd_buffer.bind_vertex_buffers(0, Some((&vertex_buffer, 0))); cmd_buffer.bind_graphics_descriptor_sets(&pipeline_layout, 0, Some(&desc_set), &[]); //TODO { diff --git a/src/backend/dx11/src/lib.rs b/src/backend/dx11/src/lib.rs index 755eae70115..47d8c84a819 100644 --- a/src/backend/dx11/src/lib.rs +++ b/src/backend/dx11/src/lib.rs @@ -866,9 +866,14 @@ impl hal::command::RawCommandBuffer for CommandBuffer { } } - fn bind_vertex_buffers(&mut self, first_binding: u32, vbs: pso::VertexBufferSet) { - let (buffers, offsets): (Vec<*mut d3d11::ID3D11Buffer>, Vec) = vbs.0.iter() - .map(|(buf, offset)| (buf.internal.raw, *offset as u32)) + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + let (buffers, offsets): (Vec<*mut d3d11::ID3D11Buffer>, Vec) = buffers + .into_iter() + .map(|(buf, offset)| (buf.borrow().internal.raw, offset as u32)) .unzip(); // TODO: strides diff --git a/src/backend/dx12/src/command.rs b/src/backend/dx12/src/command.rs index 78ed4db6275..6e49e8c7f17 100644 --- a/src/backend/dx12/src/command.rs +++ b/src/backend/dx12/src/command.rs @@ -1634,15 +1634,21 @@ impl com::RawCommandBuffer for CommandBuffer { } } - fn bind_vertex_buffers(&mut self, first_binding: u32, vbs: pso::VertexBufferSet) { + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { // Only cache the vertex buffer views as we don't know the stride (PSO). assert!(first_binding as usize <= MAX_VERTEX_BUFFERS); - for (&(buffer, offset), view) in vbs.0.iter() + for (&(buffer, offset), view) in buffers + .into_iter() .zip(self.vertex_buffer_views[first_binding as _..].iter_mut()) { - let base = unsafe { (*buffer.resource).GetGPUVirtualAddress() }; + let b = buffer.borrow(); + let base = unsafe { (*b.resource).GetGPUVirtualAddress() }; view.BufferLocation = base + offset as u64; - view.SizeInBytes = buffer.size_in_bytes - offset as u32; + view.SizeInBytes = b.size_in_bytes - offset as u32; } } diff --git a/src/backend/empty/src/lib.rs b/src/backend/empty/src/lib.rs index 1ce539cce82..71771433ebf 100644 --- a/src/backend/empty/src/lib.rs +++ b/src/backend/empty/src/lib.rs @@ -499,7 +499,11 @@ impl command::RawCommandBuffer for RawCommandBuffer { unimplemented!() } - fn bind_vertex_buffers(&mut self, _: u32, _: pso::VertexBufferSet) { + fn bind_vertex_buffers(&mut self, _: u32, _: I) + where + I: IntoIterator, + T: Borrow<()>, + { unimplemented!() } diff --git a/src/backend/gl/src/command.rs b/src/backend/gl/src/command.rs index 7a3b30fd40f..98ce54ad8e7 100644 --- a/src/backend/gl/src/command.rs +++ b/src/backend/gl/src/command.rs @@ -698,17 +698,20 @@ impl command::RawCommandBuffer for RawCommandBuffer { self.push_cmd(Command::BindIndexBuffer(ibv.buffer.raw)); } - fn bind_vertex_buffers(&mut self, _first_binding: u32, vbs: hal::pso::VertexBufferSet) { - if vbs.0.len() == 0 { - return - } - - let needed_length = vbs.0.iter().map(|vb| vb.1).max().unwrap() + 1; - - self.cache.vertex_buffers.resize(needed_length as usize, 0); - - for vb in vbs.0 { - self.cache.vertex_buffers[vb.1 as usize] = vb.0.raw; + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + for (i, (buffer, offset)) in buffers.into_iter().enumerate() { + let index = first_binding as usize + i; + if self.cache.vertex_buffers.len() <= index { + self.cache.vertex_buffers.resize(index+1, 0); + } + self.cache.vertex_buffers[index] = buffer.borrow().raw; + if offset != 0 { + error!("Vertex buffer offset {} is not supported", offset); + } } } diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index 0809f822f08..b88d79c7db2 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -2233,13 +2233,26 @@ impl com::RawCommandBuffer for CommandBuffer { }); } - fn bind_vertex_buffers(&mut self, first_binding: u32, buffer_set: pso::VertexBufferSet) { - while self.state.vertex_buffers.len() < first_binding as usize + buffer_set.0.len() { - self.state.vertex_buffers.push(None); - } - for (i, &(buffer, offset)) in buffer_set.0.iter().enumerate() { - let buffer_ptr = BufferPtr(buffer.raw.as_ptr()); - self.state.vertex_buffers[first_binding as usize + i] = Some((buffer_ptr, buffer.range.start + offset)); + + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + if self.state.vertex_buffers.len() <= first_binding as usize { + self.state.vertex_buffers.resize(first_binding as usize + 1, None); + } + for (i, (buffer, offset)) in buffers.into_iter().enumerate() { + let b = buffer.borrow(); + let buffer_ptr = BufferPtr(b.raw.as_ptr()); + let index = first_binding as usize + i; + let value = Some((buffer_ptr, b.range.start + offset)); + if index >= self.state.vertex_buffers.len() { + debug_assert_eq!(index, self.state.vertex_buffers.len()); + self.state.vertex_buffers.push(value); + } else { + self.state.vertex_buffers[index] = value; + } } let mask = self.state.set_vertex_buffers(); diff --git a/src/backend/vulkan/src/command.rs b/src/backend/vulkan/src/command.rs index a11cd294443..601f40b61f7 100644 --- a/src/backend/vulkan/src/command.rs +++ b/src/backend/vulkan/src/command.rs @@ -483,11 +483,15 @@ impl com::RawCommandBuffer for CommandBuffer { } } - fn bind_vertex_buffers(&mut self, first_binding: u32, vbs: pso::VertexBufferSet) { - let buffers: SmallVec<[vk::Buffer; 16]> = - vbs.0.iter().map(|&(ref buffer, _)| buffer.raw).collect(); - let offsets: SmallVec<[vk::DeviceSize; 16]> = - vbs.0.iter().map(|&(_, offset)| offset as u64).collect(); + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + let (buffers, offsets): (SmallVec<[vk::Buffer; 16]>, SmallVec<[vk::DeviceSize; 16]>) = buffers + .into_iter() + .map(|(buffer, offset)| (buffer.borrow().raw, offset)) + .unzip(); unsafe { self.device.0.cmd_bind_vertex_buffers( diff --git a/src/hal/src/command/graphics.rs b/src/hal/src/command/graphics.rs index 753a4cf1639..58b46d9b4e3 100644 --- a/src/hal/src/command/graphics.rs +++ b/src/hal/src/command/graphics.rs @@ -3,8 +3,7 @@ use std::borrow::Borrow; use std::ops::Range; use Backend; -use {image, pso}; -use buffer::IndexBufferView; +use {buffer, image, pso}; use query::{Query, QueryControl, QueryId}; use queue::capability::{Graphics, GraphicsOrCompute, Supports}; use super::{ @@ -181,13 +180,17 @@ impl<'a, B: Backend, C: Supports, S: Shot, L: Level> CommandBuffer<'a, } /// Identical to the `RawCommandBuffer` method of the same name. - pub fn bind_index_buffer(&mut self, ibv: IndexBufferView) { + pub fn bind_index_buffer(&mut self, ibv: buffer::IndexBufferView) { self.raw.bind_index_buffer(ibv) } /// Identical to the `RawCommandBuffer` method of the same name. - pub fn bind_vertex_buffers(&mut self, first_binding: u32, vbs: pso::VertexBufferSet) { - self.raw.bind_vertex_buffers(first_binding, vbs) + pub fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + self.raw.bind_vertex_buffers(first_binding, buffers) } /// Identical to the `RawCommandBuffer` method of the same name. diff --git a/src/hal/src/command/raw.rs b/src/hal/src/command/raw.rs index 8e62c7fce7e..63dea9d975f 100644 --- a/src/hal/src/command/raw.rs +++ b/src/hal/src/command/raw.rs @@ -206,7 +206,10 @@ pub trait RawCommandBuffer: Clone + Any + Send + Sync { /// /// Each buffer passed corresponds to the vertex input binding with the same index, /// starting from an offset index `first_binding`. - fn bind_vertex_buffers(&mut self, first_binding: u32, pso::VertexBufferSet); + fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow; /// Set the viewport parameters for the rasterizer. /// diff --git a/src/hal/src/command/render_pass.rs b/src/hal/src/command/render_pass.rs index 5522bb35d6b..45bd50f1b39 100644 --- a/src/hal/src/command/render_pass.rs +++ b/src/hal/src/command/render_pass.rs @@ -65,8 +65,12 @@ impl<'a, B: Backend> RenderSubpassCommon<'a, B> { } /// - pub fn bind_vertex_buffers(&mut self, first_binding: u32, vbs: pso::VertexBufferSet) { - self.0.bind_vertex_buffers(first_binding, vbs); + pub fn bind_vertex_buffers(&mut self, first_binding: u32, buffers: I) + where + I: IntoIterator, + T: Borrow, + { + self.0.bind_vertex_buffers(first_binding, buffers); } /// diff --git a/src/hal/src/pso/input_assembler.rs b/src/hal/src/pso/input_assembler.rs index a70252f2e7b..5876dde3fad 100644 --- a/src/hal/src/pso/input_assembler.rs +++ b/src/hal/src/pso/input_assembler.rs @@ -2,8 +2,7 @@ //! The input assembler collects raw vertex and index data. use format; -use buffer::Offset; -use {Backend, Primitive}; +use {Primitive}; /// Shader binding location. pub type Location = u32; @@ -88,17 +87,3 @@ impl InputAssemblerDesc { } } } - -/// A complete set of vertex buffers to be used for vertex import in PSO. -#[derive(Clone, Debug)] -pub struct VertexBufferSet<'a, B: Backend>( - /// Array of buffer handles with offsets in them - pub Vec<(&'a B::Buffer, Offset)>, -); - -impl<'a, B: Backend> VertexBufferSet<'a, B> { - /// Create an empty set - pub fn new() -> Self { - VertexBufferSet(Vec::new()) - } -} diff --git a/src/warden/src/gpu.rs b/src/warden/src/gpu.rs index fb9a47d87f0..8dff81aca55 100644 --- a/src/warden/src/gpu.rs +++ b/src/warden/src/gpu.rs @@ -945,10 +945,8 @@ impl Scene { .expect(&format!("Missing vertex buffer: {}", name)) .handle; (buf, offset) - }) - .collect::>(); - let set = pso::VertexBufferSet(buffers_raw); - encoder.bind_vertex_buffers(0, set); + }); + encoder.bind_vertex_buffers(0, buffers_raw); } Dc::BindPipeline(ref name) => { let pso = resources.graphics_pipelines From a2754916ec3eeb8af4e73cb511fc5c21ccd72435 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 27 Jun 2018 18:38:39 -0400 Subject: [PATCH 2/4] [mtl] cache attachments in clear_image --- src/backend/metal/src/command.rs | 52 +++++++++++++++++--------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index b88d79c7db2..8188a05d7c0 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -1690,51 +1690,63 @@ impl com::RawCommandBuffer for CommandBuffer { &*image.raw }; - let clear_color_attachment = sub.aspects.contains(Aspects::COLOR); - if image.format_desc.aspects.contains(Aspects::COLOR) { + let color_attachment = if image.format_desc.aspects.contains(Aspects::COLOR) { let attachment = descriptor .color_attachments() .object_at(0) .unwrap(); attachment.set_texture(Some(texture)); attachment.set_store_action(metal::MTLStoreAction::Store); - if clear_color_attachment { + if sub.aspects.contains(Aspects::COLOR) { attachment.set_load_action(metal::MTLLoadAction::Clear); attachment.set_clear_color(clear_color.clone()); + Some(attachment) } else { attachment.set_load_action(metal::MTLLoadAction::Load); + None } - } + } else { + assert!(!sub.aspects.contains(Aspects::COLOR)); + None + }; - let clear_depth_attachment = sub.aspects.contains(Aspects::DEPTH); - if image.format_desc.aspects.contains(Aspects::DEPTH) { + let depth_attachment = if image.format_desc.aspects.contains(Aspects::DEPTH) { let attachment = descriptor .depth_attachment() .unwrap(); attachment.set_texture(Some(texture)); attachment.set_store_action(metal::MTLStoreAction::Store); - if clear_depth_attachment { + if sub.aspects.contains(Aspects::DEPTH) { attachment.set_load_action(metal::MTLLoadAction::Clear); attachment.set_clear_depth(depth_stencil.depth as _); + Some(attachment) } else { attachment.set_load_action(metal::MTLLoadAction::Load); + None } - } + } else { + assert!(!sub.aspects.contains(Aspects::DEPTH)); + None + }; - let clear_stencil_attachment = sub.aspects.contains(Aspects::STENCIL); - if image.format_desc.aspects.contains(Aspects::STENCIL) { + let stencil_attachment = if image.format_desc.aspects.contains(Aspects::STENCIL) { let attachment = descriptor .stencil_attachment() .unwrap(); attachment.set_texture(Some(texture)); attachment.set_store_action(metal::MTLStoreAction::Store); - if clear_stencil_attachment { + if sub.aspects.contains(Aspects::STENCIL) { attachment.set_load_action(metal::MTLLoadAction::Clear); attachment.set_clear_stencil(depth_stencil.stencil); + Some(attachment) } else { attachment.set_load_action(metal::MTLLoadAction::Load); + None } - } + } else { + assert!(!sub.aspects.contains(Aspects::STENCIL)); + None + }; for layer in layers { for level in sub.levels.clone() { @@ -1746,29 +1758,19 @@ impl com::RawCommandBuffer for CommandBuffer { descriptor.set_render_target_array_length(num_layers); }; - if clear_color_attachment { - let attachment = descriptor - .color_attachments() - .object_at(0) - .unwrap(); + if let Some(attachment) = color_attachment { attachment.set_level(level as _); if !CLEAR_IMAGE_ARRAY { attachment.set_slice(layer as _); } } - if clear_depth_attachment { - let attachment = descriptor - .depth_attachment() - .unwrap(); + if let Some(attachment) = depth_attachment { attachment.set_level(level as _); if !CLEAR_IMAGE_ARRAY { attachment.set_slice(layer as _); } } - if clear_stencil_attachment { - let attachment = descriptor - .stencil_attachment() - .unwrap(); + if let Some(attachment) = stencil_attachment { attachment.set_level(level as _); if !CLEAR_IMAGE_ARRAY { attachment.set_slice(layer as _); From d6b8b934b59e1d37b23cd6a5a1f406a6ce5947cb Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 27 Jun 2018 18:54:59 -0400 Subject: [PATCH 3/4] [mtl] avoid heap allocation and an extra autorelease pool at begin_render_pass --- src/backend/metal/src/command.rs | 12 +++++++++--- src/backend/metal/src/device.rs | 3 ++- src/backend/metal/src/native.rs | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index 8188a05d7c0..358c7a238a7 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -821,11 +821,11 @@ impl CommandSink { ) where I: Iterator>, { + //assert!(AutoReleasePool::is_active()); self.stop_encoding(); match *self { CommandSink::Immediate { ref cmd_buffer, ref mut encoder_state, .. } => { - let _ap = AutoreleasePool::new(); let encoder = cmd_buffer.new_render_command_encoder(descriptor); for command in init_commands { exec_render(encoder, command); @@ -1446,7 +1446,7 @@ impl pool::RawCommandPool for CommandPool { framebuffer_inner: native::FramebufferInner { extent: Extent::default(), aspects: Aspects::empty(), - colors: Vec::new(), + colors: SmallVec::new(), depth_stencil: None, } }, @@ -1653,6 +1653,8 @@ impl com::RawCommandBuffer for CommandBuffer { T: IntoIterator, T::Item: Borrow, { + let _ap = AutoreleasePool::new(); + let CommandBufferInner { ref mut retained_textures, ref mut sink, @@ -2017,6 +2019,8 @@ impl com::RawCommandBuffer for CommandBuffer { T: IntoIterator, T::Item: Borrow { + let _ap = AutoreleasePool::new(); + let vertices = &mut self.temp.blit_vertices; vertices.clear(); @@ -2220,7 +2224,9 @@ impl com::RawCommandBuffer for CommandBuffer { .chain(&extra) .cloned(); - inner.sink().begin_render_pass(false, &descriptor, commands); + inner + .sink() + .begin_render_pass(false, &descriptor, commands); } } diff --git a/src/backend/metal/src/device.rs b/src/backend/metal/src/device.rs index a8db0c2e9fb..48f69ebe41b 100644 --- a/src/backend/metal/src/device.rs +++ b/src/backend/metal/src/device.rs @@ -27,6 +27,7 @@ use metal::{self, MTLVertexStepFunction, MTLSamplerBorderColor, MTLSamplerMipFilter, MTLTextureType, CaptureManager }; +use smallvec::SmallVec; use spirv_cross::{msl, spirv, ErrorCode as SpirvErrorCode}; use foreign_types::ForeignType; @@ -1124,7 +1125,7 @@ impl hal::Device for Device { let mut inner = n::FramebufferInner { extent, aspects: format::Aspects::empty(), - colors: Vec::new(), + colors: SmallVec::new(), depth_stencil: None, }; diff --git a/src/backend/metal/src/native.rs b/src/backend/metal/src/native.rs index e7313cc02ae..948edd42633 100644 --- a/src/backend/metal/src/native.rs +++ b/src/backend/metal/src/native.rs @@ -13,6 +13,7 @@ use hal::format::{Aspects, Format, FormatDesc}; use cocoa::foundation::{NSUInteger}; use metal; +use smallvec::SmallVec; use spirv_cross::{msl, spirv}; use foreign_types::ForeignType; @@ -51,7 +52,7 @@ pub struct ColorAttachment { pub struct FramebufferInner { pub extent: image::Extent, pub aspects: Aspects, - pub colors: Vec, + pub colors: SmallVec<[ColorAttachment; 4]>, pub depth_stencil: Option, } From 96871af86dc6ddf65be1a414970a81e5fc157e67 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 27 Jun 2018 19:20:52 -0400 Subject: [PATCH 4/4] [mtl] ban non-fast hash maps entirely --- src/backend/dx12/src/command.rs | 4 ++-- src/backend/metal/src/device.rs | 20 +++++++++++--------- src/backend/metal/src/native.rs | 9 ++++++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/backend/dx12/src/command.rs b/src/backend/dx12/src/command.rs index 6e49e8c7f17..32937b724f7 100644 --- a/src/backend/dx12/src/command.rs +++ b/src/backend/dx12/src/command.rs @@ -1641,13 +1641,13 @@ impl com::RawCommandBuffer for CommandBuffer { { // Only cache the vertex buffer views as we don't know the stride (PSO). assert!(first_binding as usize <= MAX_VERTEX_BUFFERS); - for (&(buffer, offset), view) in buffers + for ((buffer, offset), view) in buffers .into_iter() .zip(self.vertex_buffer_views[first_binding as _..].iter_mut()) { let b = buffer.borrow(); let base = unsafe { (*b.resource).GetGPUVirtualAddress() }; - view.BufferLocation = base + offset as u64; + view.BufferLocation = base + offset; view.SizeInBytes = b.size_in_bytes - offset as u32; } } diff --git a/src/backend/metal/src/device.rs b/src/backend/metal/src/device.rs index 48f69ebe41b..96426050860 100644 --- a/src/backend/metal/src/device.rs +++ b/src/backend/metal/src/device.rs @@ -6,14 +6,13 @@ use {conversions as conv, command, native as n}; use native; use std::borrow::Borrow; -use std::collections::hash_map::{Entry, HashMap}; +use std::collections::hash_map::Entry; use std::ops::Range; use std::path::Path; use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::{cmp, mem, slice, time}; use hal::{self, error, image, pass, format, mapping, memory, buffer, pso, query, window}; -use hal::backend::FastHashMap; use hal::device::{BindError, OutOfMemory, FramebufferError, ShaderError}; use hal::memory::Properties; use hal::pool::CommandPoolCreateFlags; @@ -496,7 +495,7 @@ impl Device { { Ok(library) => Ok(n::ShaderModule::Compiled { library, - entry_point_map: FastHashMap::default(), + entry_point_map: n::EntryPointMap::default(), }), Err(err) => Err(ShaderError::CompilationFailed(err.into())), } @@ -506,8 +505,8 @@ impl Device { &self, raw_data: &[u8], primitive_class: MTLPrimitiveTopologyClass, - overrides: &HashMap, - ) -> Result<(metal::Library, FastHashMap), ShaderError> { + overrides: &n::ResourceOverrideMap, + ) -> Result<(metal::Library, n::EntryPointMap), ShaderError> { // spec requires "codeSize must be a multiple of 4" assert_eq!(raw_data.len() & 3, 0); @@ -528,7 +527,10 @@ impl Device { compiler_options.resolve_specialized_array_lengths = true; compiler_options.vertex.invert_y = true; // fill the overrides - compiler_options.resource_binding_overrides = overrides.clone(); + compiler_options.resource_binding_overrides = overrides + .iter() + .map(|(key, value)| (key.clone(), value.clone())) + .collect(); ast.set_compiler_options(&compiler_options) .map_err(|err| { @@ -557,7 +559,7 @@ impl Device { ShaderError::CompilationFailed(msg) })?; - let mut entry_point_map = FastHashMap::default(); + let mut entry_point_map = n::EntryPointMap::default(); for entry_point in entry_points { info!("Entry point {:?}", entry_point); let cleansed = ast.get_cleansed_entry_point_name(&entry_point.name, entry_point.execution_model) @@ -727,7 +729,7 @@ impl hal::Device for Device { (ShaderStageFlags::FRAGMENT, spirv::ExecutionModel::Fragment, Counters { buffers:0, textures:0, samplers:0 }), (ShaderStageFlags::COMPUTE, spirv::ExecutionModel::GlCompute, Counters { buffers:0, textures:0, samplers:0 }), ]; - let mut res_overrides = HashMap::new(); + let mut res_overrides = n::ResourceOverrideMap::default(); for (set_index, set_layout) in set_layouts.into_iter().enumerate() { match set_layout.borrow() { @@ -1185,7 +1187,7 @@ impl hal::Device for Device { let (library, entry_point_map) = self.compile_shader_library( raw_data, MTLPrimitiveTopologyClass::Unspecified, - &HashMap::new(), + &n::ResourceOverrideMap::default(), )?; n::ShaderModule::Compiled { library, diff --git a/src/backend/metal/src/native.rs b/src/backend/metal/src/native.rs index 948edd42633..89ed8bb840a 100644 --- a/src/backend/metal/src/native.rs +++ b/src/backend/metal/src/native.rs @@ -2,7 +2,6 @@ use {Backend, BufferPtr, SamplerPtr, TexturePtr}; use internal::Channel; use window::SwapchainImage; -use std::collections::HashMap; use std::ops::Range; use std::os::raw::{c_void, c_long}; use std::sync::{Arc, Condvar, Mutex, RwLock}; @@ -20,13 +19,15 @@ use foreign_types::ForeignType; use range_alloc::RangeAllocator; +pub type EntryPointMap = FastHashMap; + /// Shader module can be compiled in advance if it's resource bindings do not /// depend on pipeline layout, in which case the value would become `Compiled`. #[derive(Debug)] pub enum ShaderModule { Compiled { library: metal::Library, - entry_point_map: FastHashMap, + entry_point_map: EntryPointMap, }, Raw(Vec), } @@ -65,11 +66,13 @@ pub struct Framebuffer { unsafe impl Send for Framebuffer {} unsafe impl Sync for Framebuffer {} +pub type ResourceOverrideMap = FastHashMap; + #[derive(Debug)] pub struct PipelineLayout { // First vertex buffer index to be used by attributes pub(crate) attribute_buffer_index: u32, - pub(crate) res_overrides: HashMap, + pub(crate) res_overrides: ResourceOverrideMap, } #[derive(Clone, Debug)]