use std::marker::PhantomData;
use core::{ResourceViewSlot, UnorderedViewSlot, SamplerSlot, Resources};
use core::{handle, pso, shade};
use core::memory::Typed;
use core::format::Format;
use super::{DataLink, DataBind, RawDataSet, AccessInfo};
pub struct ShaderResource<T>(RawShaderResource, PhantomData<T>);
impl<T> PartialEq for ShaderResource<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for ShaderResource<T> {}
impl<T> std::hash::Hash for ShaderResource<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T> Clone for ShaderResource<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), PhantomData)
}
}
impl<T> std::fmt::Debug for ShaderResource<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("ShaderResource").field(&self.0).finish()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct RawShaderResource(Option<(ResourceViewSlot, shade::Usage)>);
pub struct UnorderedAccess<T>(Option<(UnorderedViewSlot, shade::Usage)>, PhantomData<T>);
impl<T> PartialEq for UnorderedAccess<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for UnorderedAccess<T> {}
impl<T> std::hash::Hash for UnorderedAccess<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T> Clone for UnorderedAccess<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), PhantomData)
}
}
impl<T> std::fmt::Debug for UnorderedAccess<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("UnorderedAccess").field(&self.0).finish()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Sampler(Option<(SamplerSlot, shade::Usage)>);
pub struct TextureSampler<T>(ShaderResource<T>, Sampler);
impl<T> PartialEq for TextureSampler<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}
impl<T> Eq for TextureSampler<T> {}
impl<T> std::hash::Hash for TextureSampler<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
self.1.hash(state);
}
}
impl<T> Clone for TextureSampler<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1.clone())
}
}
impl<T> std::fmt::Debug for TextureSampler<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("TextureSampler").field(&self.0).field(&self.1).finish()
}
}
impl<'a, T> DataLink<'a> for ShaderResource<T> {
type Init = &'a str;
fn new() -> Self {
ShaderResource(RawShaderResource(None), PhantomData)
}
fn is_active(&self) -> bool {
self.0.is_active()
}
fn link_resource_view(&mut self, var: &shade::TextureVar, init: &Self::Init)
-> Option<Result<pso::ResourceViewDesc, Format>> {
self.0.link_resource_view(var, init)
}
}
impl<R: Resources, T> DataBind<R> for ShaderResource<T> {
type Data = handle::ShaderResourceView<R, T>;
fn bind_to(&self,
out: &mut RawDataSet<R>,
data: &Self::Data,
man: &mut handle::Manager<R>,
access: &mut AccessInfo<R>) {
self.0.bind_to(out, data.raw(), man, access)
}
}
impl<'a> DataLink<'a> for RawShaderResource {
type Init = &'a str;
fn new() -> Self {
RawShaderResource(None)
}
fn is_active(&self) -> bool {
self.0.is_some()
}
fn link_resource_view(&mut self, var: &shade::TextureVar, init: &Self::Init)
-> Option<Result<pso::ResourceViewDesc, Format>> {
if *init == var.name {
self.0 = Some((var.slot, var.usage));
Some(Ok(var.usage))
}else {
None
}
}
}
impl<R: Resources> DataBind<R> for RawShaderResource {
type Data = handle::RawShaderResourceView<R>;
fn bind_to(&self,
out: &mut RawDataSet<R>,
data: &Self::Data,
man: &mut handle::Manager<R>,
_: &mut AccessInfo<R>) {
if let Some((slot, usage)) = self.0 {
let view = man.ref_srv(data).clone();
out.resource_views.push(pso::ResourceViewParam(view, usage, slot));
}
}
}
impl<'a, T> DataLink<'a> for UnorderedAccess<T> {
type Init = &'a str;
fn new() -> Self {
UnorderedAccess(None, PhantomData)
}
fn is_active(&self) -> bool {
self.0.is_some()
}
fn link_unordered_view(&mut self, var: &shade::UnorderedVar, init: &Self::Init)
-> Option<Result<pso::UnorderedViewDesc, Format>> {
if *init == var.name {
self.0 = Some((var.slot, var.usage));
Some(Ok(var.usage))
}else {
None
}
}
}
impl<R: Resources, T> DataBind<R> for UnorderedAccess<T> {
type Data = handle::UnorderedAccessView<R, T>;
fn bind_to(&self,
out: &mut RawDataSet<R>,
data: &Self::Data,
man: &mut handle::Manager<R>,
_: &mut AccessInfo<R>) {
if let Some((slot, usage)) = self.0 {
let view = man.ref_uav(data.raw()).clone();
out.unordered_views.push(pso::UnorderedViewParam(view, usage, slot));
}
}
}
impl<'a> DataLink<'a> for Sampler {
type Init = &'a str;
fn new() -> Self {
Sampler(None)
}
fn is_active(&self) -> bool {
self.0.is_some()
}
fn link_sampler(&mut self, var: &shade::SamplerVar, init: &Self::Init)
-> Option<pso::SamplerDesc> {
if *init == var.name {
self.0 = Some((var.slot, var.usage));
Some(var.usage)
}else {
None
}
}
}
impl<R: Resources> DataBind<R> for Sampler {
type Data = handle::Sampler<R>;
fn bind_to(&self,
out: &mut RawDataSet<R>,
data: &Self::Data,
man: &mut handle::Manager<R>,
_: &mut AccessInfo<R>) {
if let Some((slot, usage)) = self.0 {
let sm = man.ref_sampler(data).clone();
out.samplers.push(pso::SamplerParam(sm, usage, slot));
}
}
}
impl<'a, T> DataLink<'a> for TextureSampler<T> {
type Init = &'a str;
fn new() -> Self {
TextureSampler(ShaderResource::new(), Sampler::new())
}
fn is_active(&self) -> bool {
self.0.is_active()
}
fn link_resource_view(&mut self, var: &shade::TextureVar, init: &Self::Init)
-> Option<Result<pso::ResourceViewDesc, Format>> {
self.0.link_resource_view(var, init)
}
fn link_sampler(&mut self, var: &shade::SamplerVar, init: &Self::Init) -> Option<pso::SamplerDesc> {
self.1.link_sampler(var, init)
}
}
impl<R: Resources, T> DataBind<R> for TextureSampler<T> {
type Data = (handle::ShaderResourceView<R, T>, handle::Sampler<R>);
fn bind_to(&self,
out: &mut RawDataSet<R>,
data: &Self::Data,
man: &mut handle::Manager<R>,
access: &mut AccessInfo<R>) {
self.0.bind_to(out, &data.0, man, access);
self.1.bind_to(out, &data.1, man, access);
}
}