Implement most of the reflection API
This commit is contained in:
parent
0efe5f8115
commit
7deb377f78
@ -1,8 +1,8 @@
|
||||
# Slang Rust Bindings
|
||||
|
||||
Rust bindings for the [Slang](https://github.com/shader-slang/slang/) shader language compiler. In contrast to existing bindings, these internally use Slang's COM/C++ API because the old C API is soon to be deprecated.
|
||||
Rust bindings for the [Slang](https://github.com/shader-slang/slang/) shader language. Supporting both the modern compilation and reflection API.
|
||||
|
||||
Currently mostly reflects the needs of our own [engine](https://github.com/FloatyMonkey/engine) but issues and pull requests are more than welcome.
|
||||
Currently mostly reflects the needs of our own [engine](https://github.com/FloatyMonkey/engine) but contributions are more than welcome.
|
||||
|
||||
## Example
|
||||
|
||||
@ -37,6 +37,9 @@ let program = session.create_composite_component_type(&[
|
||||
|
||||
let linked_program = program.link().unwrap();
|
||||
|
||||
// Entry point to the reflection API.
|
||||
let reflection = linked_program.layout(0).unwrap();
|
||||
|
||||
let shader_bytecode = linked_program.get_entry_point_code(0, 0).unwrap();
|
||||
```
|
||||
|
||||
|
@ -18,7 +18,8 @@ fn main() {
|
||||
.header(slang_dir.join("include/slang.h").to_str().unwrap())
|
||||
.clang_arg("-v")
|
||||
.clang_arg("-xc++")
|
||||
.clang_arg("-std=c++14")
|
||||
.clang_arg("-std=c++17")
|
||||
.allowlist_function("spReflection.*")
|
||||
.allowlist_function("slang_.*")
|
||||
.allowlist_type("slang.*")
|
||||
.allowlist_var("SLANG_.*")
|
||||
|
@ -4,7 +4,7 @@ include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
|
||||
use std::ffi::{c_char, c_int, c_void};
|
||||
|
||||
// Based on Slang version 2024.1.29
|
||||
// Based on Slang version 2024.14.3
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IBlobVtable {
|
||||
@ -88,6 +88,8 @@ pub struct IComponentTypeVtable {
|
||||
pub renameEntryPoint: unsafe extern "C" fn(*mut c_void, newName: *const c_char, outEntryPoint: *mut *mut slang_IComponentType) -> SlangResult,
|
||||
pub linkWithOptions: unsafe extern "C" fn(*mut c_void, outLinkedComponentType: *mut *mut slang_IComponentType, compilerOptionEntryCount: u32, compilerOptionEntries: *mut slang_CompilerOptionEntry, outDiagnostics: *mut *mut ISlangBlob) -> SlangResult,
|
||||
pub getTargetCode: unsafe extern "C" fn(*mut c_void, targetIndex: SlangInt, outCode: *mut *mut ISlangBlob, outDiagnostics: *mut *mut ISlangBlob) -> SlangResult,
|
||||
pub getTargetMetadata: unsafe extern "C" fn(*mut c_void, targetIndex: SlangInt, outMetadata: *mut *mut slang_IMetadata, outDiagnostics: *mut *mut ISlangBlob) -> SlangResult,
|
||||
pub getEntryPointMetadata: unsafe extern "C" fn(*mut c_void, entryPointIndex: SlangInt, targetIndex: SlangInt, outMetadata: *mut *mut slang_IMetadata, outDiagnostics: *mut *mut ISlangBlob) -> SlangResult,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -115,4 +117,5 @@ pub struct IModuleVtable {
|
||||
pub findAndCheckEntryPoint: unsafe extern "C" fn(*mut c_void, name: *const c_char, stage: SlangStage, outEntryPoint: *mut *mut slang_IEntryPoint, outDiagnostics: *mut *mut ISlangBlob) -> SlangResult,
|
||||
pub getDependencyFileCount: unsafe extern "C" fn(*mut c_void) -> SlangInt32,
|
||||
pub getDependencyFilePath: unsafe extern "C" fn(*mut c_void, index: SlangInt32) -> *const c_char,
|
||||
pub getModuleReflection: unsafe extern "C" fn(*mut c_void) -> *mut slang_DeclReflection,
|
||||
}
|
||||
|
27
src/lib.rs
27
src/lib.rs
@ -1,3 +1,5 @@
|
||||
pub mod reflection;
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
@ -270,6 +272,19 @@ unsafe impl Interface for ComponentType {
|
||||
}
|
||||
|
||||
impl ComponentType {
|
||||
pub fn layout(&self, target: i64) -> Result<&reflection::Shader> {
|
||||
let mut diagnostics = null_mut();
|
||||
let ptr = vcall!(self, getLayout(target, &mut diagnostics));
|
||||
|
||||
if ptr.is_null() {
|
||||
Err(Error::Blob(Blob(IUnknown(
|
||||
std::ptr::NonNull::new(diagnostics as *mut _).unwrap(),
|
||||
))))
|
||||
} else {
|
||||
Ok(unsafe { &*(ptr as *const _) })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link(&self) -> Result<ComponentType> {
|
||||
let mut linked_component_type = null_mut();
|
||||
let mut diagnostics = null_mut();
|
||||
@ -284,7 +299,7 @@ impl ComponentType {
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn get_entry_point_code(&self, index: i64, target: i64) -> Result<Blob> {
|
||||
pub fn entry_point_code(&self, index: i64, target: i64) -> Result<Blob> {
|
||||
let mut code = null_mut();
|
||||
let mut diagnostics = null_mut();
|
||||
|
||||
@ -300,6 +315,11 @@ impl ComponentType {
|
||||
std::ptr::NonNull::new(code as *mut _).unwrap(),
|
||||
)))
|
||||
}
|
||||
|
||||
#[deprecated = "Use `entry_point_code` instead"]
|
||||
pub fn get_entry_point_code(&self, index: i64, target: i64) -> Result<Blob> {
|
||||
self.entry_point_code(index, target)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
@ -386,6 +406,11 @@ impl Module {
|
||||
let identity = vcall!(self, getUniqueIdentity());
|
||||
unsafe { CStr::from_ptr(identity).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn module_reflection(&self) -> &reflection::Decl {
|
||||
let ptr = vcall!(self, getModuleReflection());
|
||||
unsafe { &*(ptr as *const _) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TargetDescBuilder {
|
||||
|
48
src/reflection/decl.rs
Normal file
48
src/reflection/decl.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use super::{rcall, Function, Generic, Type, Variable};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Decl(sys::SlangReflectionDecl);
|
||||
|
||||
impl Decl {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionDecl_getName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> sys::SlangDeclKind {
|
||||
rcall!(spReflectionDecl_getKind(self))
|
||||
}
|
||||
|
||||
pub fn child_count(&self) -> u32 {
|
||||
rcall!(spReflectionDecl_getChildrenCount(self))
|
||||
}
|
||||
|
||||
pub fn child_by_index(&self, index: u32) -> Option<&Decl> {
|
||||
rcall!(spReflectionDecl_getChild(self, index) as Option<&Decl>)
|
||||
}
|
||||
|
||||
pub fn children(&self) -> impl ExactSizeIterator<Item = &Decl> {
|
||||
(0..self.child_count()).map(move |i| rcall!(spReflectionDecl_getChild(self, i) as &Decl))
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> &Type {
|
||||
rcall!(spReflection_getTypeFromDecl(self) as &Type)
|
||||
}
|
||||
|
||||
pub fn as_variable(&self) -> &Variable {
|
||||
rcall!(spReflectionDecl_castToVariable(self) as &Variable)
|
||||
}
|
||||
|
||||
pub fn as_function(&self) -> &Function {
|
||||
rcall!(spReflectionDecl_castToFunction(self) as &Function)
|
||||
}
|
||||
|
||||
pub fn as_generic(&self) -> &Generic {
|
||||
rcall!(spReflectionDecl_castToGeneric(self) as &Generic)
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> &Decl {
|
||||
rcall!(spReflectionDecl_getParent(self) as &Decl)
|
||||
}
|
||||
}
|
62
src/reflection/entry_point.rs
Normal file
62
src/reflection/entry_point.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use super::{rcall, Function, TypeLayout, VariableLayout};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct EntryPoint(sys::SlangReflectionEntryPoint);
|
||||
|
||||
impl EntryPoint {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionEntryPoint_getName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn name_override(&self) -> Option<&str> {
|
||||
let name = rcall!(spReflectionEntryPoint_getNameOverride(self));
|
||||
(!name.is_null()).then(|| unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() })
|
||||
}
|
||||
|
||||
pub fn parameter_count(&self) -> u32 {
|
||||
rcall!(spReflectionEntryPoint_getParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn parameter_by_index(&self, index: u32) -> Option<&VariableLayout> {
|
||||
rcall!(spReflectionEntryPoint_getParameterByIndex(self, index) as Option<&VariableLayout>)
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> impl ExactSizeIterator<Item = &VariableLayout> {
|
||||
(0..self.parameter_count()).map(move |i| {
|
||||
rcall!(spReflectionEntryPoint_getParameterByIndex(self, i) as &VariableLayout)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn function(&self) -> &Function {
|
||||
rcall!(spReflectionEntryPoint_getFunction(self) as &Function)
|
||||
}
|
||||
|
||||
pub fn stage(&self) -> sys::SlangStage {
|
||||
rcall!(spReflectionEntryPoint_getStage(self))
|
||||
}
|
||||
|
||||
// TODO: compute_thread_group_size
|
||||
// TODO: compute_wave_size
|
||||
|
||||
pub fn uses_any_sample_rate_input(&self) -> bool {
|
||||
rcall!(spReflectionEntryPoint_usesAnySampleRateInput(self)) != 0
|
||||
}
|
||||
|
||||
pub fn var_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflectionEntryPoint_getVarLayout(self) as &VariableLayout)
|
||||
}
|
||||
|
||||
pub fn type_layout(&self) -> &TypeLayout {
|
||||
self.var_layout().type_layout()
|
||||
}
|
||||
|
||||
pub fn result_var_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflectionEntryPoint_getResultVarLayout(self) as &VariableLayout)
|
||||
}
|
||||
|
||||
pub fn has_default_constant_buffer(&self) -> bool {
|
||||
rcall!(spReflectionEntryPoint_hasDefaultConstantBuffer(self)) != 0
|
||||
}
|
||||
}
|
65
src/reflection/function.rs
Normal file
65
src/reflection/function.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use super::{rcall, Type, UserAttribute, Variable};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Function(sys::SlangReflectionFunction);
|
||||
|
||||
impl Function {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionFunction_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn return_type(&self) -> &Type {
|
||||
rcall!(spReflectionFunction_GetResultType(self) as &Type)
|
||||
}
|
||||
|
||||
pub fn parameter_count(&self) -> u32 {
|
||||
rcall!(spReflectionFunction_GetParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn parameter_by_index(&self, index: u32) -> Option<&Variable> {
|
||||
rcall!(spReflectionFunction_GetParameter(self, index) as Option<&Variable>)
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> impl ExactSizeIterator<Item = &Variable> {
|
||||
(0..self.parameter_count())
|
||||
.map(move |i| rcall!(spReflectionFunction_GetParameter(self, i) as &Variable))
|
||||
}
|
||||
|
||||
pub fn user_attribute_count(&self) -> u32 {
|
||||
rcall!(spReflectionFunction_GetUserAttributeCount(self))
|
||||
}
|
||||
|
||||
pub fn user_attribute_by_index(&self, index: u32) -> Option<&UserAttribute> {
|
||||
rcall!(spReflectionFunction_GetUserAttribute(self, index) as Option<&UserAttribute>)
|
||||
}
|
||||
|
||||
pub fn user_attributes(&self) -> impl ExactSizeIterator<Item = &UserAttribute> {
|
||||
(0..self.user_attribute_count())
|
||||
.map(move |i| rcall!(spReflectionFunction_GetUserAttribute(self, i) as &UserAttribute))
|
||||
}
|
||||
|
||||
// TODO: find_user_attribute_by_name
|
||||
// TODO: find_modifier
|
||||
// TODO: generic_container
|
||||
// TODO: apply_specializations
|
||||
// TODO: specialize_with_arg_types
|
||||
|
||||
pub fn is_overloaded(&self) -> bool {
|
||||
rcall!(spReflectionFunction_isOverloaded(self))
|
||||
}
|
||||
|
||||
pub fn overload_count(&self) -> u32 {
|
||||
rcall!(spReflectionFunction_getOverloadCount(self))
|
||||
}
|
||||
|
||||
pub fn overload_by_index(&self, index: u32) -> Option<&Function> {
|
||||
rcall!(spReflectionFunction_getOverload(self, index) as Option<&Function>)
|
||||
}
|
||||
|
||||
pub fn overloads(&self) -> impl ExactSizeIterator<Item = &Function> {
|
||||
(0..self.overload_count())
|
||||
.map(move |i| rcall!(spReflectionFunction_getOverload(self, i) as &Function))
|
||||
}
|
||||
}
|
91
src/reflection/generic.rs
Normal file
91
src/reflection/generic.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use super::{rcall, Decl, Type, TypeParameter, Variable};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Generic(sys::SlangReflectionGeneric);
|
||||
|
||||
impl Generic {
|
||||
pub fn as_decl(&self) -> &Decl {
|
||||
rcall!(spReflectionGeneric_asDecl(self) as &Decl)
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionGeneric_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn type_parameter_count(&self) -> u32 {
|
||||
rcall!(spReflectionGeneric_GetTypeParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn type_parameter_by_index(&self, index: u32) -> Option<&TypeParameter> {
|
||||
rcall!(spReflectionGeneric_GetTypeParameter(self, index) as Option<&TypeParameter>)
|
||||
}
|
||||
|
||||
pub fn type_parameters(&self) -> impl ExactSizeIterator<Item = &TypeParameter> {
|
||||
(0..self.type_parameter_count())
|
||||
.map(move |i| rcall!(spReflectionGeneric_GetTypeParameter(self, i) as &TypeParameter))
|
||||
}
|
||||
|
||||
pub fn value_parameter_count(&self) -> u32 {
|
||||
rcall!(spReflectionGeneric_GetValueParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn value_parameter_by_index(&self, index: u32) -> Option<&Variable> {
|
||||
rcall!(spReflectionGeneric_GetValueParameter(self, index) as Option<&Variable>)
|
||||
}
|
||||
|
||||
pub fn value_parameters(&self) -> impl ExactSizeIterator<Item = &Variable> {
|
||||
(0..self.value_parameter_count())
|
||||
.map(move |i| rcall!(spReflectionGeneric_GetValueParameter(self, i) as &Variable))
|
||||
}
|
||||
|
||||
pub fn type_parameter_constraint_count(&self, type_param: &Variable) -> u32 {
|
||||
rcall!(spReflectionGeneric_GetTypeParameterConstraintCount(
|
||||
self,
|
||||
type_param as *const _ as *mut _
|
||||
))
|
||||
}
|
||||
|
||||
pub fn type_parameter_constraint_by_index(
|
||||
&self,
|
||||
type_param: &Variable,
|
||||
index: u32,
|
||||
) -> Option<&Type> {
|
||||
rcall!(spReflectionGeneric_GetTypeParameterConstraintType(
|
||||
self,
|
||||
type_param as *const _ as *mut _,
|
||||
index
|
||||
) as Option<&Type>)
|
||||
}
|
||||
|
||||
pub fn inner_decl(&self) -> &Decl {
|
||||
rcall!(spReflectionGeneric_GetInnerDecl(self) as &Decl)
|
||||
}
|
||||
|
||||
pub fn inner_kind(&self) -> sys::SlangDeclKind {
|
||||
rcall!(spReflectionGeneric_GetInnerKind(self))
|
||||
}
|
||||
|
||||
pub fn outer_generic_container(&self) -> &Generic {
|
||||
rcall!(spReflectionGeneric_GetOuterGenericContainer(self) as &Generic)
|
||||
}
|
||||
|
||||
pub fn concrete_type(&self, type_param: &Variable) -> &Type {
|
||||
rcall!(spReflectionGeneric_GetConcreteType(self, type_param as *const _ as *mut _) as &Type)
|
||||
}
|
||||
|
||||
pub fn concrete_int_val(&self, value_param: &Variable) -> i64 {
|
||||
rcall!(spReflectionGeneric_GetConcreteIntVal(
|
||||
self,
|
||||
value_param as *const _ as *mut _
|
||||
))
|
||||
}
|
||||
|
||||
pub fn apply_specializations(&self, generic: &Generic) -> &Generic {
|
||||
rcall!(
|
||||
spReflectionGeneric_applySpecializations(self, generic as *const _ as *mut _)
|
||||
as &Generic
|
||||
)
|
||||
}
|
||||
}
|
38
src/reflection/mod.rs
Normal file
38
src/reflection/mod.rs
Normal file
@ -0,0 +1,38 @@
|
||||
mod decl;
|
||||
mod entry_point;
|
||||
mod function;
|
||||
mod generic;
|
||||
mod shader;
|
||||
mod ty;
|
||||
mod type_parameter;
|
||||
mod user_attribute;
|
||||
mod variable;
|
||||
|
||||
pub use decl::Decl;
|
||||
pub use entry_point::EntryPoint;
|
||||
pub use function::Function;
|
||||
pub use generic::Generic;
|
||||
pub use shader::Shader;
|
||||
pub use ty::{Type, TypeLayout};
|
||||
pub use type_parameter::TypeParameter;
|
||||
pub use user_attribute::UserAttribute;
|
||||
pub use variable::{Variable, VariableLayout};
|
||||
|
||||
macro_rules! rcall {
|
||||
($f:ident($s:ident $(,$arg:expr)*)) => {
|
||||
unsafe { sys::$f($s as *const _ as *mut _ $(,$arg)*) }
|
||||
};
|
||||
|
||||
($f:ident($s:ident $(,$arg:expr)*) as Option<&$cast:ty>) => {
|
||||
unsafe {
|
||||
let ptr = sys::$f($s as *const _ as *mut _ $(,$arg)*);
|
||||
(!ptr.is_null()).then(|| &*(ptr as *const $cast))
|
||||
}
|
||||
};
|
||||
|
||||
($f:ident($s:ident $(,$arg:expr)*) as &$cast:ty) => {
|
||||
unsafe { &*(sys::$f($s as *const _ as *mut _ $(,$arg)*) as *const $cast) }
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) use rcall;
|
125
src/reflection/shader.rs
Normal file
125
src/reflection/shader.rs
Normal file
@ -0,0 +1,125 @@
|
||||
use super::{
|
||||
rcall, EntryPoint, Function, Type, TypeLayout, TypeParameter, Variable, VariableLayout,
|
||||
};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Shader(sys::SlangReflection);
|
||||
|
||||
impl Shader {
|
||||
pub fn parameter_count(&self) -> u32 {
|
||||
rcall!(spReflection_GetParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn parameter_by_index(&self, index: u32) -> Option<&VariableLayout> {
|
||||
rcall!(spReflection_GetParameterByIndex(self, index) as Option<&VariableLayout>)
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> impl ExactSizeIterator<Item = &VariableLayout> {
|
||||
(0..self.parameter_count())
|
||||
.map(move |i| rcall!(spReflection_GetParameterByIndex(self, i) as &VariableLayout))
|
||||
}
|
||||
|
||||
pub fn type_parameter_count(&self) -> u32 {
|
||||
rcall!(spReflection_GetTypeParameterCount(self))
|
||||
}
|
||||
|
||||
pub fn type_parameter_by_index(&self, index: u32) -> Option<&TypeParameter> {
|
||||
rcall!(spReflection_GetTypeParameterByIndex(self, index) as Option<&TypeParameter>)
|
||||
}
|
||||
|
||||
pub fn type_parameters(&self) -> impl ExactSizeIterator<Item = &TypeParameter> {
|
||||
(0..self.type_parameter_count())
|
||||
.map(move |i| rcall!(spReflection_GetTypeParameterByIndex(self, i) as &TypeParameter))
|
||||
}
|
||||
|
||||
pub fn find_type_parameter_by_name(&self, name: &str) -> Option<&TypeParameter> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(spReflection_FindTypeParameter(self, name.as_ptr()) as Option<&TypeParameter>)
|
||||
}
|
||||
|
||||
pub fn entry_point_count(&self) -> u32 {
|
||||
rcall!(spReflection_getEntryPointCount(self)) as _
|
||||
}
|
||||
|
||||
pub fn entry_point_by_index(&self, index: u32) -> Option<&EntryPoint> {
|
||||
rcall!(spReflection_getEntryPointByIndex(self, index as _) as Option<&EntryPoint>)
|
||||
}
|
||||
|
||||
pub fn entry_points(&self) -> impl ExactSizeIterator<Item = &EntryPoint> {
|
||||
(0..self.entry_point_count())
|
||||
.map(move |i| rcall!(spReflection_getEntryPointByIndex(self, i as _) as &EntryPoint))
|
||||
}
|
||||
|
||||
pub fn find_entry_point_by_name(&self, name: &str) -> Option<&EntryPoint> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(spReflection_findEntryPointByName(self, name.as_ptr()) as Option<&EntryPoint>)
|
||||
}
|
||||
|
||||
pub fn global_constant_buffer_binding(&self) -> u64 {
|
||||
rcall!(spReflection_getGlobalConstantBufferBinding(self))
|
||||
}
|
||||
|
||||
pub fn global_constant_buffer_size(&self) -> usize {
|
||||
rcall!(spReflection_getGlobalConstantBufferSize(self))
|
||||
}
|
||||
|
||||
pub fn find_type_by_name(&self, name: &str) -> Option<&Type> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(spReflection_FindTypeByName(self, name.as_ptr()) as Option<&Type>)
|
||||
}
|
||||
|
||||
pub fn find_function_by_name(&self, name: &str) -> Option<&Function> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(spReflection_FindFunctionByName(self, name.as_ptr()) as Option<&Function>)
|
||||
}
|
||||
|
||||
pub fn find_function_by_name_in_type(&self, ty: &Type, name: &str) -> Option<&Function> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(
|
||||
spReflection_FindFunctionByNameInType(self, ty as *const _ as *mut _, name.as_ptr())
|
||||
as Option<&Function>
|
||||
)
|
||||
}
|
||||
|
||||
pub fn find_var_by_name_in_type(&self, ty: &Type, name: &str) -> Option<&Variable> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(
|
||||
spReflection_FindVarByNameInType(self, ty as *const _ as *mut _, name.as_ptr())
|
||||
as Option<&Variable>
|
||||
)
|
||||
}
|
||||
|
||||
fn type_layout(&self, ty: &Type, rules: sys::SlangLayoutRules) -> Option<&TypeLayout> {
|
||||
rcall!(
|
||||
spReflection_GetTypeLayout(self, ty as *const _ as *mut _, rules)
|
||||
as Option<&TypeLayout>
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: specialize_type
|
||||
// TODO: specialize_generic
|
||||
// TODO: is_sub_type
|
||||
|
||||
pub fn hashed_string_count(&self) -> u64 {
|
||||
rcall!(spReflection_getHashedStringCount(self))
|
||||
}
|
||||
|
||||
pub fn hashed_string(&self, index: u64) -> Option<&str> {
|
||||
let mut len = 0;
|
||||
let result = rcall!(spReflection_getHashedString(self, index, &mut len));
|
||||
|
||||
(!result.is_null()).then(|| {
|
||||
let slice = unsafe { std::slice::from_raw_parts(result as *const u8, len as usize) };
|
||||
std::str::from_utf8(slice).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_params_type_layout(&self) -> &TypeLayout {
|
||||
rcall!(spReflection_getGlobalParamsTypeLayout(self) as &TypeLayout)
|
||||
}
|
||||
|
||||
pub fn global_params_var_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflection_getGlobalParamsVarLayout(self) as &VariableLayout)
|
||||
}
|
||||
}
|
376
src/reflection/ty.rs
Normal file
376
src/reflection/ty.rs
Normal file
@ -0,0 +1,376 @@
|
||||
use super::{rcall, UserAttribute, Variable, VariableLayout};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Type(sys::SlangReflectionType);
|
||||
|
||||
impl Type {
|
||||
pub fn kind(&self) -> sys::SlangTypeKind {
|
||||
rcall!(spReflectionType_GetKind(self))
|
||||
}
|
||||
|
||||
pub fn field_count(&self) -> u32 {
|
||||
rcall!(spReflectionType_GetFieldCount(self))
|
||||
}
|
||||
|
||||
pub fn field_by_index(&self, index: u32) -> Option<&Variable> {
|
||||
rcall!(spReflectionType_GetFieldByIndex(self, index) as Option<&Variable>)
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> impl ExactSizeIterator<Item = &Variable> {
|
||||
(0..self.field_count())
|
||||
.map(move |i| rcall!(spReflectionType_GetFieldByIndex(self, i) as &Variable))
|
||||
}
|
||||
|
||||
// TODO: is_array
|
||||
|
||||
// TODO: unwrap_array
|
||||
|
||||
pub fn element_count(&self) -> usize {
|
||||
rcall!(spReflectionType_GetElementCount(self))
|
||||
}
|
||||
|
||||
// TODO: total_array_element_count
|
||||
|
||||
pub fn element_type(&self) -> &Type {
|
||||
rcall!(spReflectionType_GetElementType(self) as &Type)
|
||||
}
|
||||
|
||||
pub fn row_count(&self) -> u32 {
|
||||
rcall!(spReflectionType_GetRowCount(self))
|
||||
}
|
||||
|
||||
pub fn column_count(&self) -> u32 {
|
||||
rcall!(spReflectionType_GetColumnCount(self))
|
||||
}
|
||||
|
||||
pub fn scalar_type(&self) -> sys::SlangScalarType {
|
||||
rcall!(spReflectionType_GetScalarType(self))
|
||||
}
|
||||
|
||||
pub fn resource_result_type(&self) -> &Type {
|
||||
rcall!(spReflectionType_GetResourceResultType(self) as &Type)
|
||||
}
|
||||
|
||||
pub fn resource_shape(&self) -> sys::SlangResourceShape {
|
||||
rcall!(spReflectionType_GetResourceShape(self))
|
||||
}
|
||||
|
||||
pub fn resource_access(&self) -> sys::SlangResourceAccess {
|
||||
rcall!(spReflectionType_GetResourceAccess(self))
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionType_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
// TODO: full_name
|
||||
|
||||
pub fn user_attribute_count(&self) -> u32 {
|
||||
rcall!(spReflectionType_GetUserAttributeCount(self))
|
||||
}
|
||||
|
||||
pub fn user_attribute_by_index(&self, index: u32) -> Option<&UserAttribute> {
|
||||
rcall!(spReflectionType_GetUserAttribute(self, index) as Option<&UserAttribute>)
|
||||
}
|
||||
|
||||
pub fn user_attributes(&self) -> impl ExactSizeIterator<Item = &UserAttribute> {
|
||||
(0..self.user_attribute_count())
|
||||
.map(move |i| rcall!(spReflectionType_GetUserAttribute(self, i) as &UserAttribute))
|
||||
}
|
||||
|
||||
pub fn find_user_attribute_by_name(&self, name: &str) -> Option<&UserAttribute> {
|
||||
let name = std::ffi::CString::new(name).unwrap();
|
||||
rcall!(
|
||||
spReflectionType_FindUserAttributeByName(self, name.as_ptr()) as Option<&UserAttribute>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct TypeLayout(sys::SlangReflectionTypeLayout);
|
||||
|
||||
impl TypeLayout {
|
||||
pub fn ty(&self) -> &Type {
|
||||
rcall!(spReflectionTypeLayout_GetType(self) as &Type)
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> sys::SlangTypeKind {
|
||||
rcall!(spReflectionTypeLayout_getKind(self))
|
||||
}
|
||||
|
||||
pub fn size(&self, category: sys::SlangParameterCategory) -> usize {
|
||||
rcall!(spReflectionTypeLayout_GetSize(self, category))
|
||||
}
|
||||
|
||||
pub fn stride(&self, category: sys::SlangParameterCategory) -> usize {
|
||||
rcall!(spReflectionTypeLayout_GetStride(self, category))
|
||||
}
|
||||
|
||||
pub fn alignment(&self, category: sys::SlangParameterCategory) -> i32 {
|
||||
rcall!(spReflectionTypeLayout_getAlignment(self, category))
|
||||
}
|
||||
|
||||
pub fn field_count(&self) -> u32 {
|
||||
rcall!(spReflectionTypeLayout_GetFieldCount(self))
|
||||
}
|
||||
|
||||
pub fn field_by_index(&self, index: u32) -> Option<&VariableLayout> {
|
||||
rcall!(spReflectionTypeLayout_GetFieldByIndex(self, index) as Option<&VariableLayout>)
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> impl ExactSizeIterator<Item = &VariableLayout> {
|
||||
(0..self.field_count()).map(move |i| {
|
||||
rcall!(spReflectionTypeLayout_GetFieldByIndex(self, i) as &VariableLayout)
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: find_field_index_by_name
|
||||
// TODO: explicit_counter
|
||||
// TODO: is_array
|
||||
// TODO: unwrap_array
|
||||
|
||||
pub fn element_count(&self) -> usize {
|
||||
self.ty().element_count()
|
||||
}
|
||||
|
||||
// TODO: total_array_element_count
|
||||
|
||||
pub fn element_stride(&self, category: sys::SlangParameterCategory) -> usize {
|
||||
rcall!(spReflectionTypeLayout_GetElementStride(self, category))
|
||||
}
|
||||
|
||||
pub fn element_type_layout(&self) -> &TypeLayout {
|
||||
rcall!(spReflectionTypeLayout_GetElementTypeLayout(self) as &TypeLayout)
|
||||
}
|
||||
|
||||
pub fn element_var_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflectionTypeLayout_GetElementVarLayout(self) as &VariableLayout)
|
||||
}
|
||||
|
||||
pub fn container_var_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflectionTypeLayout_getContainerVarLayout(self) as &VariableLayout)
|
||||
}
|
||||
|
||||
pub fn parameter_category(&self) -> sys::SlangParameterCategory {
|
||||
rcall!(spReflectionTypeLayout_GetParameterCategory(self))
|
||||
}
|
||||
|
||||
pub fn category_count(&self) -> u32 {
|
||||
rcall!(spReflectionTypeLayout_GetCategoryCount(self))
|
||||
}
|
||||
|
||||
pub fn category_by_index(&self, index: u32) -> sys::SlangParameterCategory {
|
||||
rcall!(spReflectionTypeLayout_GetCategoryByIndex(self, index))
|
||||
}
|
||||
|
||||
pub fn categories(&self) -> impl ExactSizeIterator<Item = sys::SlangParameterCategory> + '_ {
|
||||
(0..self.category_count())
|
||||
.map(move |i| rcall!(spReflectionTypeLayout_GetCategoryByIndex(self, i)))
|
||||
}
|
||||
|
||||
pub fn row_count(&self) -> u32 {
|
||||
self.ty().row_count()
|
||||
}
|
||||
|
||||
pub fn column_count(&self) -> u32 {
|
||||
self.ty().column_count()
|
||||
}
|
||||
|
||||
pub fn scalar_type(&self) -> sys::SlangScalarType {
|
||||
self.ty().scalar_type()
|
||||
}
|
||||
|
||||
pub fn resource_result_type(&self) -> &Type {
|
||||
self.ty().resource_result_type()
|
||||
}
|
||||
|
||||
pub fn resource_shape(&self) -> sys::SlangResourceShape {
|
||||
self.ty().resource_shape()
|
||||
}
|
||||
|
||||
pub fn resource_access(&self) -> sys::SlangResourceAccess {
|
||||
self.ty().resource_access()
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
self.ty().name()
|
||||
}
|
||||
|
||||
pub fn matrix_layout_mode(&self) -> sys::SlangMatrixLayoutMode {
|
||||
rcall!(spReflectionTypeLayout_GetMatrixLayoutMode(self))
|
||||
}
|
||||
|
||||
pub fn generic_param_index(&self) -> i32 {
|
||||
rcall!(spReflectionTypeLayout_getGenericParamIndex(self))
|
||||
}
|
||||
|
||||
pub fn pending_data_type_layout(&self) -> &TypeLayout {
|
||||
rcall!(spReflectionTypeLayout_getPendingDataTypeLayout(self) as &TypeLayout)
|
||||
}
|
||||
|
||||
pub fn specialized_type_pending_data_var_layout(&self) -> &VariableLayout {
|
||||
rcall!(
|
||||
spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(self) as &VariableLayout
|
||||
)
|
||||
}
|
||||
|
||||
pub fn binding_range_count(&self) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeCount(self))
|
||||
}
|
||||
|
||||
pub fn binding_range_type(&self, index: i64) -> sys::SlangBindingType {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeType(self, index))
|
||||
}
|
||||
|
||||
pub fn is_binding_range_specializable(&self, index: i64) -> bool {
|
||||
rcall!(spReflectionTypeLayout_isBindingRangeSpecializable(
|
||||
self, index
|
||||
)) != 0
|
||||
}
|
||||
|
||||
pub fn binding_range_binding_count(&self, index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeBindingCount(
|
||||
self, index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn field_binding_range_offset(&self, field_index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getFieldBindingRangeOffset(
|
||||
self,
|
||||
field_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn explicit_counter_binding_range_offset(&self) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getExplicitCounterBindingRangeOffset(
|
||||
self
|
||||
))
|
||||
}
|
||||
|
||||
pub fn binding_range_leaf_type_layout(&self, index: i64) -> &TypeLayout {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeLeafTypeLayout(self, index) as &TypeLayout)
|
||||
}
|
||||
|
||||
pub fn binding_range_leaf_variable(&self, index: i64) -> &Variable {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeLeafVariable(self, index) as &Variable)
|
||||
}
|
||||
|
||||
pub fn binding_range_image_format(&self, index: i64) -> sys::SlangImageFormat {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeImageFormat(
|
||||
self, index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn binding_range_descriptor_set_index(&self, index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeDescriptorSetIndex(
|
||||
self, index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn binding_range_first_descriptor_range_index(&self, index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex(self, index))
|
||||
}
|
||||
|
||||
pub fn binding_range_descriptor_range_count(&self, index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getBindingRangeDescriptorRangeCount(
|
||||
self, index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn descriptor_set_count(&self) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getDescriptorSetCount(self))
|
||||
}
|
||||
|
||||
pub fn descriptor_set_space_offset(&self, set_index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getDescriptorSetSpaceOffset(
|
||||
self, set_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn descriptor_set_descriptor_range_count(&self, set_index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount(
|
||||
self, set_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn descriptor_set_descriptor_range_index_offset(
|
||||
&self,
|
||||
set_index: i64,
|
||||
range_index: i64,
|
||||
) -> i64 {
|
||||
rcall!(
|
||||
spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset(
|
||||
self,
|
||||
set_index,
|
||||
range_index
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn descriptor_set_descriptor_range_descriptor_count(
|
||||
&self,
|
||||
set_index: i64,
|
||||
range_index: i64,
|
||||
) -> i64 {
|
||||
rcall!(
|
||||
spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount(
|
||||
self,
|
||||
set_index,
|
||||
range_index
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn descriptor_set_descriptor_range_type(
|
||||
&self,
|
||||
set_index: i64,
|
||||
range_index: i64,
|
||||
) -> sys::SlangBindingType {
|
||||
rcall!(spReflectionTypeLayout_getDescriptorSetDescriptorRangeType(
|
||||
self,
|
||||
set_index,
|
||||
range_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn descriptor_set_descriptor_range_category(
|
||||
&self,
|
||||
set_index: i64,
|
||||
range_index: i64,
|
||||
) -> sys::SlangParameterCategory {
|
||||
rcall!(
|
||||
spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory(
|
||||
self,
|
||||
set_index,
|
||||
range_index
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn sub_object_range_count(&self) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getSubObjectRangeCount(self))
|
||||
}
|
||||
|
||||
pub fn sub_object_range_binding_range_index(&self, sub_object_range_index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(
|
||||
self,
|
||||
sub_object_range_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn sub_object_range_space_offset(&self, sub_object_range_index: i64) -> i64 {
|
||||
rcall!(spReflectionTypeLayout_getSubObjectRangeSpaceOffset(
|
||||
self,
|
||||
sub_object_range_index
|
||||
))
|
||||
}
|
||||
|
||||
pub fn sub_object_range_offset(&self, sub_object_range_index: i64) -> &VariableLayout {
|
||||
rcall!(
|
||||
spReflectionTypeLayout_getSubObjectRangeOffset(self, sub_object_range_index)
|
||||
as &VariableLayout
|
||||
)
|
||||
}
|
||||
}
|
29
src/reflection/type_parameter.rs
Normal file
29
src/reflection/type_parameter.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use super::{rcall, Type};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct TypeParameter(sys::SlangReflectionTypeParameter);
|
||||
|
||||
impl TypeParameter {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionTypeParameter_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn index(&self) -> u32 {
|
||||
rcall!(spReflectionTypeParameter_GetIndex(self))
|
||||
}
|
||||
|
||||
pub fn constraint_count(&self) -> u32 {
|
||||
rcall!(spReflectionTypeParameter_GetConstraintCount(self))
|
||||
}
|
||||
|
||||
pub fn constraint_by_index(&self, index: u32) -> &Type {
|
||||
rcall!(spReflectionTypeParameter_GetConstraintByIndex(self, index) as &Type)
|
||||
}
|
||||
|
||||
pub fn constraints(&self) -> impl ExactSizeIterator<Item = &Type> {
|
||||
(0..self.constraint_count())
|
||||
.map(move |i| rcall!(spReflectionTypeParameter_GetConstraintByIndex(self, i) as &Type))
|
||||
}
|
||||
}
|
54
src/reflection/user_attribute.rs
Normal file
54
src/reflection/user_attribute.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use super::{rcall, Type};
|
||||
use slang_sys as sys;
|
||||
|
||||
fn succeeded(result: sys::SlangResult) -> bool {
|
||||
result >= 0
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct UserAttribute(sys::SlangReflectionUserAttribute);
|
||||
|
||||
impl UserAttribute {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionUserAttribute_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn argument_count(&self) -> u32 {
|
||||
rcall!(spReflectionUserAttribute_GetArgumentCount(self))
|
||||
}
|
||||
|
||||
pub fn argument_type(&self, index: u32) -> &Type {
|
||||
rcall!(spReflectionUserAttribute_GetArgumentType(self, index) as &Type)
|
||||
}
|
||||
|
||||
pub fn argument_value_int(&self, index: u32) -> Option<i32> {
|
||||
let mut out = 0;
|
||||
let result = rcall!(spReflectionUserAttribute_GetArgumentValueInt(
|
||||
self, index, &mut out
|
||||
));
|
||||
|
||||
succeeded(result).then(|| out)
|
||||
}
|
||||
|
||||
pub fn argument_value_float(&self, index: u32) -> Option<f32> {
|
||||
let mut out = 0.0;
|
||||
let result = rcall!(spReflectionUserAttribute_GetArgumentValueFloat(
|
||||
self, index, &mut out
|
||||
));
|
||||
|
||||
succeeded(result).then(|| out)
|
||||
}
|
||||
|
||||
pub fn argument_value_string(&self, index: u32) -> Option<&str> {
|
||||
let mut len = 0;
|
||||
let result = rcall!(spReflectionUserAttribute_GetArgumentValueString(
|
||||
self, index, &mut len
|
||||
));
|
||||
|
||||
(!result.is_null()).then(|| {
|
||||
let slice = unsafe { std::slice::from_raw_parts(result as *const u8, len as usize) };
|
||||
std::str::from_utf8(slice).unwrap()
|
||||
})
|
||||
}
|
||||
}
|
105
src/reflection/variable.rs
Normal file
105
src/reflection/variable.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use super::{rcall, Type, TypeLayout, UserAttribute};
|
||||
use slang_sys as sys;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Variable(sys::SlangReflectionVariable);
|
||||
|
||||
impl Variable {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = rcall!(spReflectionVariable_GetName(self));
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> &Type {
|
||||
rcall!(spReflectionVariable_GetType(self) as &Type)
|
||||
}
|
||||
|
||||
// TODO: find_modifier
|
||||
|
||||
pub fn user_attribute_count(&self) -> u32 {
|
||||
rcall!(spReflectionVariable_GetUserAttributeCount(self))
|
||||
}
|
||||
|
||||
pub fn user_attribute_by_index(&self, index: u32) -> Option<&UserAttribute> {
|
||||
rcall!(spReflectionVariable_GetUserAttribute(self, index) as Option<&UserAttribute>)
|
||||
}
|
||||
|
||||
pub fn user_attributes(&self) -> impl ExactSizeIterator<Item = &UserAttribute> {
|
||||
(0..self.user_attribute_count())
|
||||
.map(move |i| rcall!(spReflectionVariable_GetUserAttribute(self, i) as &UserAttribute))
|
||||
}
|
||||
|
||||
// TODO: find_user_attribute_by_name
|
||||
|
||||
pub fn has_default_value(&self) -> bool {
|
||||
rcall!(spReflectionVariable_HasDefaultValue(self))
|
||||
}
|
||||
|
||||
// TODO: generic_container
|
||||
// TODO: apply_specializations
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct VariableLayout(sys::SlangReflectionVariableLayout);
|
||||
|
||||
impl VariableLayout {
|
||||
pub fn variable(&self) -> &Variable {
|
||||
rcall!(spReflectionVariableLayout_GetVariable(self) as &Variable)
|
||||
}
|
||||
|
||||
// TODO: get_name
|
||||
// TODO: find_modifier
|
||||
|
||||
pub fn type_layout(&self) -> &TypeLayout {
|
||||
rcall!(spReflectionVariableLayout_GetTypeLayout(self) as &TypeLayout)
|
||||
}
|
||||
|
||||
pub fn category(&self) -> sys::SlangParameterCategory {
|
||||
self.type_layout().parameter_category()
|
||||
}
|
||||
|
||||
pub fn category_count(&self) -> u32 {
|
||||
self.type_layout().category_count()
|
||||
}
|
||||
|
||||
pub fn category_by_index(&self, index: u32) -> sys::SlangParameterCategory {
|
||||
self.type_layout().category_by_index(index)
|
||||
}
|
||||
|
||||
pub fn offset(&self, category: sys::SlangParameterCategory) -> usize {
|
||||
rcall!(spReflectionVariableLayout_GetOffset(self, category))
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> &Type {
|
||||
self.variable().ty()
|
||||
}
|
||||
|
||||
pub fn binding_index(&self) -> u32 {
|
||||
rcall!(spReflectionParameter_GetBindingIndex(self))
|
||||
}
|
||||
|
||||
pub fn binding_space(&self) -> u32 {
|
||||
rcall!(spReflectionParameter_GetBindingSpace(self))
|
||||
}
|
||||
|
||||
pub fn binding_space_with_category(&self, category: sys::SlangParameterCategory) -> usize {
|
||||
rcall!(spReflectionVariableLayout_GetSpace(self, category))
|
||||
}
|
||||
|
||||
pub fn semantic_name(&self) -> Option<&str> {
|
||||
let name = rcall!(spReflectionVariableLayout_GetSemanticName(self));
|
||||
unsafe { (!name.is_null()).then(|| std::ffi::CStr::from_ptr(name).to_str().unwrap()) }
|
||||
}
|
||||
|
||||
pub fn semantic_index(&self) -> usize {
|
||||
rcall!(spReflectionVariableLayout_GetSemanticIndex(self))
|
||||
}
|
||||
|
||||
pub fn stage(&self) -> sys::SlangStage {
|
||||
rcall!(spReflectionVariableLayout_getStage(self))
|
||||
}
|
||||
|
||||
pub fn pending_data_layout(&self) -> &VariableLayout {
|
||||
rcall!(spReflectionVariableLayout_getPendingDataLayout(self) as &VariableLayout)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user