2022-11-20 10:48:54 +11:00
|
|
|
use gl::types::GLint;
|
2023-01-29 17:57:09 +11:00
|
|
|
use librashader_reflect::reflect::semantics::{BindingStage, UniformMemberBlock};
|
2022-11-30 17:38:05 +11:00
|
|
|
use librashader_runtime::uniforms::{BindUniform, UniformScalar, UniformStorage};
|
2022-11-20 10:48:54 +11:00
|
|
|
|
2023-01-29 17:57:09 +11:00
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub struct VariableLocation {
|
|
|
|
pub(crate) ubo: Option<UniformLocation<GLint>>,
|
|
|
|
pub(crate) push: Option<UniformLocation<GLint>>,
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl VariableLocation {
|
2023-01-29 17:57:09 +11:00
|
|
|
pub fn location(&self, offset_type: UniformMemberBlock) -> Option<UniformLocation<GLint>> {
|
2023-01-29 18:30:58 +11:00
|
|
|
match offset_type {
|
|
|
|
UniformMemberBlock::Ubo => self.ubo,
|
|
|
|
UniformMemberBlock::PushConstant => self.push,
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub struct UniformLocation<T> {
|
|
|
|
pub vertex: T,
|
|
|
|
pub fragment: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UniformLocation<GLint> {
|
2022-11-28 15:27:21 +11:00
|
|
|
pub fn is_valid(&self, stage: BindingStage) -> bool {
|
|
|
|
let mut validity = false;
|
|
|
|
if stage.contains(BindingStage::FRAGMENT) {
|
|
|
|
validity = validity || self.fragment >= 0;
|
|
|
|
}
|
|
|
|
if stage.contains(BindingStage::VERTEX) {
|
|
|
|
validity = validity || self.vertex >= 0;
|
|
|
|
}
|
|
|
|
validity
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
2023-01-29 17:57:09 +11:00
|
|
|
|
|
|
|
pub fn bindable(&self) -> bool {
|
|
|
|
self.is_valid(BindingStage::VERTEX | BindingStage::FRAGMENT)
|
|
|
|
}
|
2022-11-20 10:48:54 +11:00
|
|
|
}
|
2022-11-29 14:56:20 +11:00
|
|
|
|
2023-01-29 17:57:09 +11:00
|
|
|
pub(crate) type GlUniformStorage = UniformStorage<GlUniformBinder, VariableLocation>;
|
2022-11-29 14:56:20 +11:00
|
|
|
|
|
|
|
pub trait GlUniformScalar: UniformScalar {
|
|
|
|
const FACTORY: unsafe fn(GLint, Self) -> ();
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GlUniformScalar for f32 {
|
|
|
|
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GlUniformScalar for i32 {
|
|
|
|
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1i;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GlUniformScalar for u32 {
|
|
|
|
const FACTORY: unsafe fn(GLint, Self) -> () = gl::Uniform1ui;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct GlUniformBinder;
|
2024-03-04 18:10:08 +11:00
|
|
|
impl<T> BindUniform<VariableLocation, T, ()> for GlUniformBinder
|
2022-11-30 17:38:05 +11:00
|
|
|
where
|
|
|
|
T: GlUniformScalar,
|
2022-11-29 14:56:20 +11:00
|
|
|
{
|
2024-03-03 17:07:07 +11:00
|
|
|
fn bind_uniform(
|
|
|
|
block: UniformMemberBlock,
|
|
|
|
value: T,
|
|
|
|
location: VariableLocation,
|
|
|
|
_: &(),
|
|
|
|
) -> Option<()> {
|
2023-01-29 17:57:09 +11:00
|
|
|
if let Some(location) = location.location(block)
|
|
|
|
&& location.bindable()
|
|
|
|
{
|
|
|
|
if location.is_valid(BindingStage::VERTEX) {
|
2024-02-03 18:04:39 +11:00
|
|
|
unsafe {
|
|
|
|
T::FACTORY(location.vertex, value);
|
|
|
|
}
|
2023-01-29 17:57:09 +11:00
|
|
|
}
|
|
|
|
if location.is_valid(BindingStage::FRAGMENT) {
|
2024-02-03 18:04:39 +11:00
|
|
|
unsafe {
|
|
|
|
T::FACTORY(location.fragment, value);
|
|
|
|
}
|
2022-11-29 14:56:20 +11:00
|
|
|
}
|
|
|
|
Some(())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 18:10:08 +11:00
|
|
|
impl BindUniform<VariableLocation, &[f32; 4], ()> for GlUniformBinder {
|
2023-01-29 18:30:58 +11:00
|
|
|
fn bind_uniform(
|
|
|
|
block: UniformMemberBlock,
|
|
|
|
vec4: &[f32; 4],
|
|
|
|
location: VariableLocation,
|
2024-03-03 17:07:07 +11:00
|
|
|
_: &(),
|
2023-01-29 18:30:58 +11:00
|
|
|
) -> Option<()> {
|
2023-01-29 17:57:09 +11:00
|
|
|
if let Some(location) = location.location(block)
|
|
|
|
&& location.bindable()
|
|
|
|
{
|
2022-11-29 14:56:20 +11:00
|
|
|
unsafe {
|
|
|
|
if location.is_valid(BindingStage::VERTEX) {
|
|
|
|
gl::Uniform4fv(location.vertex, 1, vec4.as_ptr());
|
|
|
|
}
|
|
|
|
if location.is_valid(BindingStage::FRAGMENT) {
|
|
|
|
gl::Uniform4fv(location.fragment, 1, vec4.as_ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 18:10:08 +11:00
|
|
|
impl BindUniform<VariableLocation, &[f32; 16], ()> for GlUniformBinder {
|
2023-01-29 18:30:58 +11:00
|
|
|
fn bind_uniform(
|
|
|
|
block: UniformMemberBlock,
|
|
|
|
mat4: &[f32; 16],
|
|
|
|
location: VariableLocation,
|
2024-03-03 17:07:07 +11:00
|
|
|
_: &(),
|
2023-01-29 18:30:58 +11:00
|
|
|
) -> Option<()> {
|
2023-01-29 17:57:09 +11:00
|
|
|
if let Some(location) = location.location(block)
|
|
|
|
&& location.bindable()
|
|
|
|
{
|
2022-11-29 14:56:20 +11:00
|
|
|
unsafe {
|
|
|
|
if location.is_valid(BindingStage::VERTEX) {
|
|
|
|
gl::UniformMatrix4fv(location.vertex, 1, gl::FALSE, mat4.as_ptr());
|
|
|
|
}
|
|
|
|
if location.is_valid(BindingStage::FRAGMENT) {
|
|
|
|
gl::UniformMatrix4fv(location.fragment, 1, gl::FALSE, mat4.as_ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(())
|
2022-11-30 17:38:05 +11:00
|
|
|
} else {
|
2022-11-29 14:56:20 +11:00
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2022-11-30 17:38:05 +11:00
|
|
|
}
|