Rename BindGroup to BindGroupDescriptor. Add BindGroupDescriptorId

This commit is contained in:
Carter Anderson 2020-03-25 18:17:48 -07:00
parent 47ef339e7b
commit aec817c533
8 changed files with 58 additions and 55 deletions

View file

@ -1,55 +1,58 @@
use super::Binding;
use super::BindingDescriptor;
use std::{
collections::{hash_map::DefaultHasher, BTreeSet},
hash::{Hash, Hasher},
};
#[derive(Clone, Debug)]
pub struct BindGroup {
pub struct BindGroupDescriptor {
pub index: u32,
pub bindings: BTreeSet<Binding>,
hash: Option<u64>,
pub bindings: BTreeSet<BindingDescriptor>,
hash: Option<BindGroupDescriptorId>,
}
impl BindGroup {
pub fn new(index: u32, bindings: Vec<Binding>) -> Self {
BindGroup {
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
pub struct BindGroupDescriptorId(u64);
impl BindGroupDescriptor {
pub fn new(index: u32, bindings: Vec<BindingDescriptor>) -> Self {
BindGroupDescriptor {
index,
bindings: bindings.iter().cloned().collect(),
hash: None,
}
}
pub fn get_hash(&self) -> Option<u64> {
pub fn get_id(&self) -> Option<BindGroupDescriptorId> {
self.hash
}
pub fn get_or_update_hash(&mut self) -> u64 {
pub fn get_or_update_id(&mut self) -> BindGroupDescriptorId {
if self.hash.is_none() {
self.update_hash();
self.update_id();
}
self.hash.unwrap()
}
pub fn update_hash(&mut self) {
pub fn update_id(&mut self) {
let mut hasher = DefaultHasher::new();
self.hash(&mut hasher);
self.hash = Some(hasher.finish());
self.hash = Some(BindGroupDescriptorId(hasher.finish()));
}
}
impl Hash for BindGroup {
impl Hash for BindGroupDescriptor {
fn hash<H: Hasher>(&self, state: &mut H) {
self.index.hash(state);
self.bindings.hash(state);
}
}
impl PartialEq for BindGroup {
fn eq(&self, other: &BindGroup) -> bool {
impl PartialEq for BindGroupDescriptor {
fn eq(&self, other: &BindGroupDescriptor) -> bool {
self.index == other.index && self.bindings == other.bindings
}
}
impl Eq for BindGroup {}
impl Eq for BindGroupDescriptor {}

View file

@ -2,7 +2,7 @@ use super::UniformProperty;
use crate::render::texture::TextureViewDimension;
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Binding {
pub struct BindingDescriptor {
pub name: String,
pub index: u32,
pub bind_type: BindType,

View file

@ -4,7 +4,7 @@ use super::{
DepthStencilStateDescriptor, FrontFace, IndexFormat, PrimitiveTopology,
RasterizationStateDescriptor, StencilStateFaceDescriptor,
},
BindGroup, PipelineLayout, VertexBufferDescriptor,
BindGroupDescriptor, PipelineLayout, VertexBufferDescriptor,
};
use crate::{
asset::{AssetStorage, Handle},
@ -169,7 +169,7 @@ impl<'a> PipelineBuilder<'a> {
self
}
pub fn add_bind_group(&mut self, bind_group: BindGroup) -> &mut Self {
pub fn add_bind_group(&mut self, bind_group: BindGroupDescriptor) -> &mut Self {
if let PipelineLayoutType::Reflected(_) = self.pipeline.as_ref().unwrap().layout {
self.pipeline.as_mut().unwrap().layout =
PipelineLayoutType::Manual(PipelineLayout::new());

View file

@ -1,10 +1,10 @@
use super::BindGroup;
use super::BindGroupDescriptor;
use crate::render::shader::ShaderLayout;
use std::{collections::HashMap, hash::Hash};
#[derive(Clone, Debug)]
pub struct PipelineLayout {
pub bind_groups: Vec<BindGroup>,
pub bind_groups: Vec<BindGroupDescriptor>,
}
impl PipelineLayout {
@ -15,7 +15,7 @@ impl PipelineLayout {
}
pub fn from_shader_layouts(shader_layouts: &mut [ShaderLayout]) -> Self {
let mut bind_groups = HashMap::<u32, BindGroup>::new();
let mut bind_groups = HashMap::<u32, BindGroupDescriptor>::new();
for shader_layout in shader_layouts {
for shader_bind_group in shader_layout.bind_groups.iter_mut() {
match bind_groups.get_mut(&shader_bind_group.index) {
@ -43,7 +43,7 @@ impl PipelineLayout {
let mut bind_groups_result = bind_groups
.drain()
.map(|(_, value)| value)
.collect::<Vec<BindGroup>>();
.collect::<Vec<BindGroupDescriptor>>();
// NOTE: for some reason bind groups need to be sorted by index. this is likely an issue with bevy and not with wgpu
bind_groups_result.sort_by(|a, b| a.index.partial_cmp(&b.index).unwrap());

View file

@ -44,7 +44,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
) -> Option<Range<u32>> {
let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
let bind_group_id = bind_group.get_hash().unwrap();
let bind_group_id = bind_group.get_id().unwrap();
let wgpu_bind_group = match self.wgpu_resources.bind_groups.get(&bind_group_id) {
// if there is a "global" bind group, use that
Some(wgpu_bind_group) => wgpu_bind_group,

View file

@ -177,7 +177,7 @@ impl WgpuRenderer {
// setup new bind group layouts
for bind_group in layout.bind_groups.iter_mut() {
let bind_group_id = bind_group.get_or_update_hash();
let bind_group_id = bind_group.get_or_update_id();
if let None = wgpu_resources.bind_group_layouts.get(&bind_group_id) {
let bind_group_layout_binding = bind_group
.bindings
@ -204,7 +204,7 @@ impl WgpuRenderer {
.bind_groups
.iter()
.map(|bind_group| {
let bind_group_id = bind_group.get_hash().unwrap();
let bind_group_id = bind_group.get_id().unwrap();
wgpu_resources
.bind_group_layouts
.get(&bind_group_id)
@ -652,7 +652,7 @@ impl Renderer for WgpuRenderer {
) {
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
let bind_group_id = bind_group.get_hash().unwrap();
let bind_group_id = bind_group.get_id().unwrap();
// only setup entity bind groups if there isn't already a "global" bind group created
if let None = self.wgpu_resources.bind_groups.get(&bind_group_id) {
if let None = self

View file

@ -1,6 +1,6 @@
use super::WgpuRenderer;
use crate::render::{
pipeline::{BindGroup, BindType},
pipeline::{BindGroupDescriptor, BindType, BindGroupDescriptorId},
render_resource::{
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceAssignmentsId,
RenderResources, ResourceInfo,
@ -16,9 +16,9 @@ pub struct WgpuResources {
pub textures: HashMap<RenderResource, wgpu::TextureView>,
pub samplers: HashMap<RenderResource, wgpu::Sampler>,
pub resource_info: HashMap<RenderResource, ResourceInfo>,
pub bind_groups: HashMap<u64, wgpu::BindGroup>,
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
pub assignment_bind_groups: HashMap<(RenderResourceAssignmentsId, u64), wgpu::BindGroup>,
pub bind_groups: HashMap<BindGroupDescriptorId, wgpu::BindGroup>,
pub bind_group_layouts: HashMap<BindGroupDescriptorId, wgpu::BindGroupLayout>,
pub assignment_bind_groups: HashMap<(RenderResourceAssignmentsId, BindGroupDescriptorId), wgpu::BindGroup>,
}
impl WgpuResources {
@ -40,13 +40,13 @@ impl WgpuResources {
}
// TODO: consider moving this to a resource provider
pub fn setup_bind_group(&mut self, device: &wgpu::Device, bind_group: &BindGroup) {
let bind_group_id = bind_group.get_hash().unwrap();
pub fn setup_bind_group(&mut self, device: &wgpu::Device, bind_group_descriptor: &BindGroupDescriptor) {
let bind_group_descriptor_id = bind_group_descriptor.get_id().unwrap();
if let None = self.bind_groups.get(&bind_group_id) {
if let None = self.bind_groups.get(&bind_group_descriptor_id) {
let mut binding_resources = Vec::new();
// if a uniform resource buffer doesn't exist, create a new empty one
for binding in bind_group.bindings.iter() {
for binding in bind_group_descriptor.bindings.iter() {
let resource = match self.render_resources.get_named_resource(&binding.name) {
resource @ Some(_) => resource,
None => return,
@ -58,7 +58,7 @@ impl WgpuResources {
}
// create wgpu Bindings
let bindings = bind_group
let bindings = bind_group_descriptor
.bindings
.iter()
.zip(binding_resources)
@ -87,7 +87,7 @@ impl WgpuResources {
})
.collect::<Vec<wgpu::Binding>>();
let bind_group_layout = self.bind_group_layouts.get(&bind_group_id).unwrap();
let bind_group_layout = self.bind_group_layouts.get(&bind_group_descriptor_id).unwrap();
let bind_group_descriptor = wgpu::BindGroupDescriptor {
layout: bind_group_layout,
bindings: bindings.as_slice(),
@ -95,27 +95,27 @@ impl WgpuResources {
let bind_group = device.create_bind_group(&bind_group_descriptor);
self.bind_groups
.insert(bind_group_id, bind_group);
.insert(bind_group_descriptor_id, bind_group);
}
}
pub fn get_assignments_bind_group(
&self,
render_resource_assignment_id: RenderResourceAssignmentsId,
bind_group_id: u64,
bind_group_descriptor_id: BindGroupDescriptorId,
) -> Option<&wgpu::BindGroup> {
self.assignment_bind_groups
.get(&(render_resource_assignment_id, bind_group_id))
.get(&(render_resource_assignment_id, bind_group_descriptor_id))
}
pub fn create_assignments_bind_group(
&mut self,
device: &wgpu::Device,
bind_group: &BindGroup,
bind_group_descriptor: &BindGroupDescriptor,
render_resource_assignments: &RenderResourceAssignments,
) {
// TODO: don't make this per-entity. bind groups should be re-used across the same resource when possible
let bind_group_id = bind_group.get_hash().unwrap();
let bindings = bind_group
let bind_group_descriptor_id = bind_group_descriptor.get_id().unwrap();
let bindings = bind_group_descriptor
.bindings
.iter()
.map(|binding| {
@ -163,7 +163,7 @@ impl WgpuResources {
}
})
.collect::<Vec<wgpu::Binding>>();
let bind_group_layout = self.bind_group_layouts.get(&bind_group_id).unwrap();
let bind_group_layout = self.bind_group_layouts.get(&bind_group_descriptor_id).unwrap();
let bind_group_descriptor = wgpu::BindGroupDescriptor {
layout: bind_group_layout,
bindings: bindings.as_slice(),
@ -172,7 +172,7 @@ impl WgpuResources {
let bind_group = device.create_bind_group(&bind_group_descriptor);
// TODO: storing a large number entity bind groups might actually be really bad. make sure this is ok
self.assignment_bind_groups.insert(
(render_resource_assignments.get_id(), bind_group_id),
(render_resource_assignments.get_id(), bind_group_descriptor_id),
bind_group,
);
}

View file

@ -1,6 +1,6 @@
use crate::render::{
pipeline::{
BindGroup, BindType, Binding, InputStepMode, UniformProperty, UniformPropertyType,
BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty, UniformPropertyType,
VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
},
texture::TextureViewDimension,
@ -30,7 +30,7 @@ use zerocopy::AsBytes;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ShaderLayout {
pub bind_groups: Vec<BindGroup>,
pub bind_groups: Vec<BindGroupDescriptor>,
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
pub entry_point: String,
}
@ -149,14 +149,14 @@ fn reflect_vertex_attribute_descriptor(
}
}
fn reflect_bind_group(descriptor_set: &ReflectDescriptorSet) -> BindGroup {
fn reflect_bind_group(descriptor_set: &ReflectDescriptorSet) -> BindGroupDescriptor {
let mut bindings = Vec::new();
for descriptor_binding in descriptor_set.bindings.iter() {
let binding = reflect_binding(descriptor_binding);
bindings.push(binding);
}
BindGroup::new(descriptor_set.set, bindings)
BindGroupDescriptor::new(descriptor_set.set, bindings)
}
fn reflect_dimension(type_description: &ReflectTypeDescription) -> TextureViewDimension {
@ -169,7 +169,7 @@ fn reflect_dimension(type_description: &ReflectTypeDescription) -> TextureViewDi
}
}
fn reflect_binding(binding: &ReflectDescriptorBinding) -> Binding {
fn reflect_binding(binding: &ReflectDescriptorBinding) -> BindingDescriptor {
let type_description = binding.type_description.as_ref().unwrap();
let (name, bind_type) = match binding.descriptor_type {
ReflectDescriptorType::UniformBuffer => (
@ -190,7 +190,7 @@ fn reflect_binding(binding: &ReflectDescriptorBinding) -> Binding {
_ => panic!("unsupported bind type {:?}", binding.descriptor_type),
};
Binding {
BindingDescriptor {
index: binding.binding,
bind_type,
name: name.to_string(),
@ -394,9 +394,9 @@ mod tests {
}
],
bind_groups: vec![
BindGroup::new(
BindGroupDescriptor::new(
0,
vec![Binding {
vec![BindingDescriptor {
index: 0,
name: "Camera".to_string(),
bind_type: BindType::Uniform {
@ -413,9 +413,9 @@ mod tests {
},
}]
),
BindGroup::new(
BindGroupDescriptor::new(
1,
vec![Binding {
vec![BindingDescriptor {
index: 0,
name: "Texture".to_string(),
bind_type: BindType::SampledTexture {