vk: write uniforms directly to host-visible mapped memory
This commit is contained in:
parent
fceda0e99d
commit
e947271f9a
|
@ -1,6 +1,7 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::vulkan_primitives::VulkanBuffer;
|
use crate::vulkan_primitives::VulkanBuffer;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub(crate) static VBO_DEFAULT_FINAL: &[f32; 16] = &[
|
pub(crate) static VBO_DEFAULT_FINAL: &[f32; 16] = &[
|
||||||
|
@ -13,12 +14,12 @@ pub(crate) static VBO_DEFAULT_FINAL: &[f32; 16] = &[
|
||||||
|
|
||||||
pub struct DrawQuad {
|
pub struct DrawQuad {
|
||||||
buffer: VulkanBuffer,
|
buffer: VulkanBuffer,
|
||||||
device: ash::Device,
|
device: Arc<ash::Device>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrawQuad {
|
impl DrawQuad {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ash::Device,
|
device: &Arc<ash::Device>,
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
) -> error::Result<DrawQuad> {
|
) -> error::Result<DrawQuad> {
|
||||||
let mut buffer = VulkanBuffer::new(
|
let mut buffer = VulkanBuffer::new(
|
||||||
|
|
|
@ -8,7 +8,8 @@ use crate::queue_selection::get_graphics_queue;
|
||||||
use crate::render_target::{RenderTarget, DEFAULT_MVP};
|
use crate::render_target::{RenderTarget, DEFAULT_MVP};
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
|
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
|
||||||
use crate::ubo_ring::VkUboRing;
|
// use crate::ubo_ring::VkUboRing;
|
||||||
|
use crate::vulkan_primitives::RawVulkanBuffer;
|
||||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
@ -352,8 +353,13 @@ impl FilterChainVulkan {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ubo| ubo.size as usize)
|
.map(|ubo| ubo.size as usize)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let uniform_storage = UniformStorage::new(
|
let uniform_storage = UniformStorage::new_with_storage(
|
||||||
ubo_size,
|
RawVulkanBuffer::new(
|
||||||
|
&vulkan.device,
|
||||||
|
&vulkan.memory_properties,
|
||||||
|
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
||||||
|
ubo_size,
|
||||||
|
)?,
|
||||||
reflection
|
reflection
|
||||||
.push_constant
|
.push_constant
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -383,13 +389,12 @@ impl FilterChainVulkan {
|
||||||
frames_in_flight,
|
frames_in_flight,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let ubo_ring = VkUboRing::new(
|
// let ubo_ring = VkUboRing::new(
|
||||||
&vulkan.device,
|
// &vulkan.device,
|
||||||
&vulkan.memory_properties,
|
// &vulkan.memory_properties,
|
||||||
frames_in_flight as usize,
|
// frames_in_flight as usize,
|
||||||
ubo_size,
|
// ubo_size,
|
||||||
)?;
|
// )?;
|
||||||
// shader_vulkan: 2026
|
|
||||||
filters.push(FilterPass {
|
filters.push(FilterPass {
|
||||||
device: vulkan.device.clone(),
|
device: vulkan.device.clone(),
|
||||||
reflection,
|
reflection,
|
||||||
|
@ -399,7 +404,7 @@ impl FilterChainVulkan {
|
||||||
source,
|
source,
|
||||||
config,
|
config,
|
||||||
graphics_pipeline,
|
graphics_pipeline,
|
||||||
ubo_ring,
|
// ubo_ring,
|
||||||
frames_in_flight,
|
frames_in_flight,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::filter_chain::FilterCommon;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::InputImage;
|
use crate::texture::InputImage;
|
||||||
use crate::ubo_ring::VkUboRing;
|
use crate::vulkan_primitives::RawVulkanBuffer;
|
||||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||||
use crate::{error, VulkanImage};
|
use crate::{error, VulkanImage};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
@ -14,7 +14,7 @@ use librashader_reflect::reflect::semantics::{
|
||||||
};
|
};
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||||
use librashader_runtime::uniforms::{UniformStorage, UniformStorageAccess};
|
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -22,12 +22,12 @@ pub struct FilterPass {
|
||||||
pub device: Arc<ash::Device>,
|
pub device: Arc<ash::Device>,
|
||||||
pub reflection: ShaderReflection,
|
pub reflection: ShaderReflection,
|
||||||
// pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
// pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
||||||
pub(crate) uniform_storage: UniformStorage,
|
pub(crate) uniform_storage: UniformStorage<NoUniformBinder, Option<()>, RawVulkanBuffer>,
|
||||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub config: ShaderPassConfig,
|
pub config: ShaderPassConfig,
|
||||||
pub graphics_pipeline: VulkanGraphicsPipeline,
|
pub graphics_pipeline: VulkanGraphicsPipeline,
|
||||||
pub ubo_ring: VkUboRing,
|
// pub ubo_ring: VkUboRing,
|
||||||
pub frames_in_flight: u32,
|
pub frames_in_flight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ impl TextureInput for InputImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BindSemantics for FilterPass {
|
impl BindSemantics<NoUniformBinder, Option<()>, RawVulkanBuffer> for FilterPass {
|
||||||
type InputTexture = InputImage;
|
type InputTexture = InputImage;
|
||||||
type SamplerSet = SamplerSet;
|
type SamplerSet = SamplerSet;
|
||||||
type DescriptorSet<'a> = vk::DescriptorSet;
|
type DescriptorSet<'a> = vk::DescriptorSet;
|
||||||
|
@ -113,10 +113,21 @@ impl FilterPass {
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ubo) = &self.reflection.ubo {
|
if let Some(ubo) = &self.reflection.ubo {
|
||||||
// shader_vulkan: 2554 (ra uses uses one big buffer)
|
// RetroArch uses uses one big buffer for this and handles alignment themselves.
|
||||||
// itll be simpler for us if we just use a RingBuffer<vk::Buffer> tbh.
|
// It's simpler here if we just use a buffer for each pass but not ideal.
|
||||||
self.ubo_ring
|
//
|
||||||
.bind_to_descriptor_set(descriptor, ubo.binding, &self.uniform_storage)?;
|
// May want to switch to something like VMA in the future.
|
||||||
|
|
||||||
|
// VkUboRing is no longer used, we just write directly to the storage now.
|
||||||
|
|
||||||
|
// self.ubo_ring
|
||||||
|
// .bind_to_descriptor_set(descriptor, ubo.binding, &self.uniform_storage)?;
|
||||||
|
|
||||||
|
self.uniform_storage.inner_ubo().bind_to_descriptor_set(
|
||||||
|
descriptor,
|
||||||
|
ubo.binding,
|
||||||
|
&self.uniform_storage,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
output.output.begin_pass(cmd);
|
output.output.begin_pass(cmd);
|
||||||
|
|
|
@ -12,6 +12,8 @@ use std::mem::align_of;
|
||||||
const ENTRY_POINT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") };
|
const ENTRY_POINT: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") };
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, Copy)]
|
#[derive(Default, Clone, Debug, Copy)]
|
||||||
|
#[repr(C)]
|
||||||
|
#[allow(dead_code)]
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
pos: [f32; 4],
|
pos: [f32; 4],
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
|
|
|
@ -14,7 +14,6 @@ mod queue_selection;
|
||||||
mod render_target;
|
mod render_target;
|
||||||
mod samplers;
|
mod samplers;
|
||||||
mod texture;
|
mod texture;
|
||||||
mod ubo_ring;
|
|
||||||
mod util;
|
mod util;
|
||||||
mod vulkan_primitives;
|
mod vulkan_primitives;
|
||||||
mod vulkan_state;
|
mod vulkan_state;
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use librashader_runtime::uniforms::UniformStorageAccess;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use std::ptr::NonNull;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct VulkanImageMemory {
|
pub struct VulkanImageMemory {
|
||||||
|
@ -36,9 +40,9 @@ impl Drop for VulkanImageMemory {
|
||||||
|
|
||||||
pub struct VulkanBuffer {
|
pub struct VulkanBuffer {
|
||||||
pub handle: vk::Buffer,
|
pub handle: vk::Buffer,
|
||||||
device: ash::Device,
|
device: Arc<ash::Device>,
|
||||||
pub memory: vk::DeviceMemory,
|
memory: vk::DeviceMemory,
|
||||||
pub size: vk::DeviceSize,
|
size: vk::DeviceSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VulkanBufferMapHandle<'a> {
|
pub struct VulkanBufferMapHandle<'a> {
|
||||||
|
@ -48,7 +52,7 @@ pub struct VulkanBufferMapHandle<'a> {
|
||||||
|
|
||||||
impl VulkanBuffer {
|
impl VulkanBuffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ash::Device,
|
device: &Arc<ash::Device>,
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
usage: vk::BufferUsageFlags,
|
usage: vk::BufferUsageFlags,
|
||||||
size: usize,
|
size: usize,
|
||||||
|
@ -112,13 +116,15 @@ impl Drop for VulkanBuffer {
|
||||||
|
|
||||||
impl<'a> VulkanBufferMapHandle<'a> {
|
impl<'a> VulkanBufferMapHandle<'a> {
|
||||||
pub unsafe fn copy_from(&mut self, offset: usize, src: &[u8]) {
|
pub unsafe fn copy_from(&mut self, offset: usize, src: &[u8]) {
|
||||||
std::ptr::copy_nonoverlapping(
|
let mut align = ash::util::Align::new(
|
||||||
src.as_ptr(),
|
|
||||||
self.ptr
|
self.ptr
|
||||||
.map_addr(|original| original.wrapping_add(offset))
|
.map_addr(|original| original.wrapping_add(offset))
|
||||||
.cast(),
|
.cast(),
|
||||||
src.len(),
|
std::mem::align_of::<u8>() as u64,
|
||||||
|
self.buffer.size,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
align.copy_from_slice(src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,3 +133,87 @@ impl<'a> Drop for VulkanBufferMapHandle<'a> {
|
||||||
unsafe { self.buffer.device.unmap_memory(self.buffer.memory) }
|
unsafe { self.buffer.device.unmap_memory(self.buffer.memory) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RawVulkanBuffer {
|
||||||
|
buffer: ManuallyDrop<VulkanBuffer>,
|
||||||
|
ptr: NonNull<c_void>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawVulkanBuffer {
|
||||||
|
pub fn new(
|
||||||
|
device: &Arc<ash::Device>,
|
||||||
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
|
usage: vk::BufferUsageFlags,
|
||||||
|
size: usize,
|
||||||
|
) -> error::Result<Self> {
|
||||||
|
let buffer = ManuallyDrop::new(VulkanBuffer::new(device, mem_props, usage, size)?);
|
||||||
|
let ptr = unsafe {
|
||||||
|
NonNull::new_unchecked(device.map_memory(
|
||||||
|
buffer.memory,
|
||||||
|
0,
|
||||||
|
buffer.size,
|
||||||
|
vk::MemoryMapFlags::empty(),
|
||||||
|
)?)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(RawVulkanBuffer { buffer, ptr })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind_to_descriptor_set(
|
||||||
|
&self,
|
||||||
|
descriptor_set: vk::DescriptorSet,
|
||||||
|
binding: u32,
|
||||||
|
storage: &impl UniformStorageAccess,
|
||||||
|
) -> error::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
let buffer_info = [vk::DescriptorBufferInfo::builder()
|
||||||
|
.buffer(self.buffer.handle)
|
||||||
|
.offset(0)
|
||||||
|
.range(storage.ubo_slice().len() as vk::DeviceSize)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
let write_info = [vk::WriteDescriptorSet::builder()
|
||||||
|
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
|
||||||
|
.dst_set(descriptor_set)
|
||||||
|
.dst_binding(binding)
|
||||||
|
.dst_array_element(0)
|
||||||
|
.buffer_info(&buffer_info)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
self.buffer.device.update_descriptor_sets(&write_info, &[])
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for RawVulkanBuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.buffer.device.unmap_memory(self.buffer.memory);
|
||||||
|
self.ptr = NonNull::dangling();
|
||||||
|
if self.buffer.memory != vk::DeviceMemory::null() {
|
||||||
|
self.buffer.device.free_memory(self.buffer.memory, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.handle != vk::Buffer::null() {
|
||||||
|
self.buffer.device.destroy_buffer(self.buffer.handle, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for RawVulkanBuffer {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().cast(), self.buffer.size as usize) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for RawVulkanBuffer {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
unsafe {
|
||||||
|
std::slice::from_raw_parts_mut(self.ptr.as_ptr().cast(), self.buffer.size as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -183,7 +183,6 @@ impl VulkanGraphicsPipeline {
|
||||||
reflection: &ShaderReflection,
|
reflection: &ShaderReflection,
|
||||||
replicas: u32,
|
replicas: u32,
|
||||||
) -> error::Result<VulkanGraphicsPipeline> {
|
) -> error::Result<VulkanGraphicsPipeline> {
|
||||||
// shader_vulkan 1927 (init_pipeline_layout)
|
|
||||||
let pipeline_layout = PipelineLayoutObjects::new(reflection, replicas, device)?;
|
let pipeline_layout = PipelineLayoutObjects::new(reflection, replicas, device)?;
|
||||||
|
|
||||||
let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::builder()
|
let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::builder()
|
||||||
|
|
|
@ -6,6 +6,7 @@ use librashader_reflect::reflect::semantics::{
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::BuildHasher;
|
use std::hash::BuildHasher;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
/// Trait for input textures used during uniform binding,
|
/// Trait for input textures used during uniform binding,
|
||||||
pub trait TextureInput {
|
pub trait TextureInput {
|
||||||
|
@ -47,8 +48,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that abstracts binding of semantics to shader uniforms.
|
/// Trait that abstracts binding of semantics to shader uniforms.
|
||||||
pub trait BindSemantics<H = NoUniformBinder, C = Option<()>>
|
pub trait BindSemantics<H = NoUniformBinder, C = Option<()>, S = Box<[u8]>>
|
||||||
where
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
H: BindUniform<C, f32>,
|
H: BindUniform<C, f32>,
|
||||||
H: BindUniform<C, u32>,
|
H: BindUniform<C, u32>,
|
||||||
H: BindUniform<C, i32>,
|
H: BindUniform<C, i32>,
|
||||||
|
@ -84,7 +86,7 @@ where
|
||||||
fn bind_semantics<'a>(
|
fn bind_semantics<'a>(
|
||||||
device: &Self::DeviceContext,
|
device: &Self::DeviceContext,
|
||||||
sampler_set: &Self::SamplerSet,
|
sampler_set: &Self::SamplerSet,
|
||||||
uniform_storage: &mut UniformStorage<H, C>,
|
uniform_storage: &mut UniformStorage<H, C, S>,
|
||||||
descriptor_set: &mut Self::DescriptorSet<'a>,
|
descriptor_set: &mut Self::DescriptorSet<'a>,
|
||||||
mvp: &[f32; 16],
|
mvp: &[f32; 16],
|
||||||
frame_count: u32,
|
frame_count: u32,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use librashader_reflect::reflect::semantics::MemberOffset;
|
use librashader_reflect::reflect::semantics::MemberOffset;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
/// A scalar value that is valid as a uniform member
|
/// A scalar value that is valid as a uniform member
|
||||||
pub trait UniformScalar: Copy + bytemuck::Pod {}
|
pub trait UniformScalar: Copy + bytemuck::Pod {}
|
||||||
|
@ -36,7 +37,10 @@ pub trait UniformStorageAccess {
|
||||||
fn push_slice(&self) -> &[u8];
|
fn push_slice(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, H> UniformStorageAccess for UniformStorage<T, H> {
|
impl<T, H, S> UniformStorageAccess for UniformStorage<T, H, S>
|
||||||
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
|
{
|
||||||
fn ubo_pointer(&self) -> *const u8 {
|
fn ubo_pointer(&self) -> *const u8 {
|
||||||
self.ubo.as_ptr()
|
self.ubo.as_ptr()
|
||||||
}
|
}
|
||||||
|
@ -64,24 +68,29 @@ impl<T> BindUniform<Option<()>, T> for NoUniformBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper to bind uniform variables to UBO or Push Constant Buffers.
|
/// A helper to bind uniform variables to UBO or Push Constant Buffers.
|
||||||
pub struct UniformStorage<H = NoUniformBinder, C = Option<()>> {
|
pub struct UniformStorage<H = NoUniformBinder, C = Option<()>, S = Box<[u8]>>
|
||||||
ubo: Box<[u8]>,
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
|
{
|
||||||
|
ubo: S,
|
||||||
push: Box<[u8]>,
|
push: Box<[u8]>,
|
||||||
_h: PhantomData<H>,
|
_h: PhantomData<H>,
|
||||||
_c: PhantomData<C>,
|
_c: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, C> UniformStorage<H, C> {
|
impl<H, C, S> UniformStorage<H, C, S>
|
||||||
/// Create a new `UniformStorage` with the given size for UBO and Push Constant Buffer sizes.
|
where
|
||||||
pub fn new(ubo_size: usize, push_size: usize) -> Self {
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
UniformStorage {
|
{
|
||||||
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
pub fn inner_ubo(&self) -> &S {
|
||||||
push: vec![0u8; push_size].into_boxed_slice(),
|
&self.ubo
|
||||||
_h: Default::default(),
|
|
||||||
_c: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, C, S> UniformStorage<H, C, S>
|
||||||
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn write_scalar_inner<T: UniformScalar>(buffer: &mut [u8], value: T, ctx: C)
|
fn write_scalar_inner<T: UniformScalar>(buffer: &mut [u8], value: T, ctx: C)
|
||||||
where
|
where
|
||||||
|
@ -100,8 +109,8 @@ impl<H, C> UniformStorage<H, C> {
|
||||||
H: BindUniform<C, T>,
|
H: BindUniform<C, T>,
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
MemberOffset::Ubo(offset) => (self.ubo.deref_mut(), offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
MemberOffset::PushConstant(offset) => (self.push.deref_mut(), offset),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::write_scalar_inner(
|
Self::write_scalar_inner(
|
||||||
|
@ -110,10 +119,33 @@ impl<H, C> UniformStorage<H, C> {
|
||||||
ctx,
|
ctx,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new `UniformStorage` with the given backing storage
|
||||||
|
pub fn new_with_storage(storage: S, push_size: usize) -> UniformStorage<H, C, S> {
|
||||||
|
UniformStorage {
|
||||||
|
ubo: storage,
|
||||||
|
push: vec![0u8; push_size].into_boxed_slice(),
|
||||||
|
_h: Default::default(),
|
||||||
|
_c: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, C> UniformStorage<H, C>
|
impl<H, C> UniformStorage<H, C, Box<[u8]>> {
|
||||||
|
/// Create a new `UniformStorage` with the given size for UBO and Push Constant Buffer sizes.
|
||||||
|
pub fn new(ubo_size: usize, push_size: usize) -> UniformStorage<H, C, Box<[u8]>> {
|
||||||
|
UniformStorage {
|
||||||
|
ubo: vec![0u8; ubo_size].into_boxed_slice(),
|
||||||
|
push: vec![0u8; push_size].into_boxed_slice(),
|
||||||
|
_h: Default::default(),
|
||||||
|
_c: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, C, S> UniformStorage<H, C, S>
|
||||||
where
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
H: for<'a> BindUniform<C, &'a [f32; 4]>,
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -128,8 +160,8 @@ where
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) {
|
pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) {
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
MemberOffset::Ubo(offset) => (self.ubo.deref_mut(), offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
MemberOffset::PushConstant(offset) => (self.push.deref_mut(), offset),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::write_vec4_inner(
|
Self::write_vec4_inner(
|
||||||
|
@ -140,8 +172,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, C> UniformStorage<H, C>
|
impl<H, C, S> UniformStorage<H, C, S>
|
||||||
where
|
where
|
||||||
|
S: Deref<Target = [u8]> + DerefMut,
|
||||||
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
H: for<'a> BindUniform<C, &'a [f32; 16]>,
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -156,8 +189,8 @@ where
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) {
|
pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) {
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.ubo, offset),
|
MemberOffset::Ubo(offset) => (self.ubo.deref_mut(), offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push, offset),
|
MemberOffset::PushConstant(offset) => (self.push.deref_mut(), offset),
|
||||||
};
|
};
|
||||||
Self::write_mat4_inner(
|
Self::write_mat4_inner(
|
||||||
&mut buffer[offset..][..16 * std::mem::size_of::<f32>()],
|
&mut buffer[offset..][..16 * std::mem::size_of::<f32>()],
|
||||||
|
|
Loading…
Reference in a new issue