mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-22 06:45:13 +00:00
Disable variable pointers by default (#591)
This commit is contained in:
parent
b6311789bb
commit
9679e615bd
@ -372,6 +372,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn zombie_ptr_equal(&self, def: Word, inst: &str) {
|
||||||
|
if !self.builder.has_capability(Capability::VariablePointers) {
|
||||||
|
self.zombie(
|
||||||
|
def,
|
||||||
|
&format!("{} without OpCapability VariablePointers", inst),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// If possible, return the appropriate `OpAccessChain` indices for going from
|
/// If possible, return the appropriate `OpAccessChain` indices for going from
|
||||||
/// a pointer to `ty`, to a pointer to `leaf_ty`, with an added `offset`.
|
/// a pointer to `ty`, to a pointer to `leaf_ty`, with an added `offset`.
|
||||||
///
|
///
|
||||||
@ -1433,7 +1442,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
|||||||
SpirvType::Pointer { .. } => match op {
|
SpirvType::Pointer { .. } => match op {
|
||||||
IntEQ => {
|
IntEQ => {
|
||||||
if self.emit().version().unwrap() > (1, 3) {
|
if self.emit().version().unwrap() > (1, 3) {
|
||||||
self.emit().ptr_equal(b, None, lhs.def(self), rhs.def(self))
|
self.emit()
|
||||||
|
.ptr_equal(b, None, lhs.def(self), rhs.def(self))
|
||||||
|
.map(|result| {
|
||||||
|
self.zombie_ptr_equal(result, "OpPtrEqual");
|
||||||
|
result
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
let int_ty = self.type_usize();
|
let int_ty = self.type_usize();
|
||||||
let lhs = self
|
let lhs = self
|
||||||
@ -1453,6 +1467,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
|
|||||||
if self.emit().version().unwrap() > (1, 3) {
|
if self.emit().version().unwrap() > (1, 3) {
|
||||||
self.emit()
|
self.emit()
|
||||||
.ptr_not_equal(b, None, lhs.def(self), rhs.def(self))
|
.ptr_not_equal(b, None, lhs.def(self), rhs.def(self))
|
||||||
|
.map(|result| {
|
||||||
|
self.zombie_ptr_equal(result, "OpPtrNotEqual");
|
||||||
|
result
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
let int_ty = self.type_usize();
|
let int_ty = self.type_usize();
|
||||||
let lhs = self
|
let lhs = self
|
||||||
|
@ -46,7 +46,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.emit_with_cursor(self.cursor)
|
self.emit_with_cursor(self.cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zombie(&self, word: Word, reason: &'static str) {
|
pub fn zombie(&self, word: Word, reason: &str) {
|
||||||
if let Some(current_span) = self.current_span {
|
if let Some(current_span) = self.current_span {
|
||||||
self.zombie_with_span(word, current_span, reason);
|
self.zombie_with_span(word, current_span, reason);
|
||||||
} else {
|
} else {
|
||||||
|
@ -320,10 +320,6 @@ impl BuilderSpirv {
|
|||||||
}
|
}
|
||||||
builder.capability(Capability::VulkanMemoryModel);
|
builder.capability(Capability::VulkanMemoryModel);
|
||||||
}
|
}
|
||||||
builder.capability(Capability::VariablePointers);
|
|
||||||
if version < (1, 3) {
|
|
||||||
builder.extension("SPV_KHR_variable_pointers");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The linker will always be ran on this module
|
// The linker will always be ran on this module
|
||||||
|
@ -19,7 +19,8 @@ pub fn inline(module: &mut Module) {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|f| (f.def_id().unwrap(), f.clone()))
|
.map(|f| (f.def_id().unwrap(), f.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
let disallowed_argument_types = compute_disallowed_argument_types(module);
|
let (disallowed_argument_types, disallowed_return_types) =
|
||||||
|
compute_disallowed_argument_and_return_types(module);
|
||||||
let void = module
|
let void = module
|
||||||
.types_global_values
|
.types_global_values
|
||||||
.iter()
|
.iter()
|
||||||
@ -30,7 +31,7 @@ pub fn inline(module: &mut Module) {
|
|||||||
// inlines in functions that will get inlined)
|
// inlines in functions that will get inlined)
|
||||||
let mut dropped_ids = FxHashSet::default();
|
let mut dropped_ids = FxHashSet::default();
|
||||||
module.functions.retain(|f| {
|
module.functions.retain(|f| {
|
||||||
if should_inline(&disallowed_argument_types, f) {
|
if should_inline(&disallowed_argument_types, &disallowed_return_types, f) {
|
||||||
// TODO: We should insert all defined IDs in this function.
|
// TODO: We should insert all defined IDs in this function.
|
||||||
dropped_ids.insert(f.def_id().unwrap());
|
dropped_ids.insert(f.def_id().unwrap());
|
||||||
false
|
false
|
||||||
@ -51,6 +52,7 @@ pub fn inline(module: &mut Module) {
|
|||||||
void,
|
void,
|
||||||
functions: &functions,
|
functions: &functions,
|
||||||
disallowed_argument_types: &disallowed_argument_types,
|
disallowed_argument_types: &disallowed_argument_types,
|
||||||
|
disallowed_return_types: &disallowed_return_types,
|
||||||
};
|
};
|
||||||
for function in &mut module.functions {
|
for function in &mut module.functions {
|
||||||
inliner.inline_fn(function);
|
inliner.inline_fn(function);
|
||||||
@ -58,17 +60,19 @@ pub fn inline(module: &mut Module) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_disallowed_argument_types(module: &Module) -> FxHashSet<Word> {
|
fn compute_disallowed_argument_and_return_types(
|
||||||
|
module: &Module,
|
||||||
|
) -> (FxHashSet<Word>, FxHashSet<Word>) {
|
||||||
let allowed_argument_storage_classes = &[
|
let allowed_argument_storage_classes = &[
|
||||||
StorageClass::UniformConstant,
|
StorageClass::UniformConstant,
|
||||||
StorageClass::Function,
|
StorageClass::Function,
|
||||||
StorageClass::Private,
|
StorageClass::Private,
|
||||||
StorageClass::Workgroup,
|
StorageClass::Workgroup,
|
||||||
StorageClass::AtomicCounter,
|
StorageClass::AtomicCounter,
|
||||||
// TODO: StorageBuffer is allowed if VariablePointers is enabled
|
|
||||||
];
|
];
|
||||||
let mut disallowed_argument_types = FxHashSet::default();
|
let mut disallowed_argument_types = FxHashSet::default();
|
||||||
let mut disallowed_pointees = FxHashSet::default();
|
let mut disallowed_pointees = FxHashSet::default();
|
||||||
|
let mut disallowed_return_types = FxHashSet::default();
|
||||||
for inst in &module.types_global_values {
|
for inst in &module.types_global_values {
|
||||||
match inst.class.opcode {
|
match inst.class.opcode {
|
||||||
Op::TypePointer => {
|
Op::TypePointer => {
|
||||||
@ -81,24 +85,19 @@ fn compute_disallowed_argument_types(module: &Module) -> FxHashSet<Word> {
|
|||||||
disallowed_argument_types.insert(inst.result_id.unwrap());
|
disallowed_argument_types.insert(inst.result_id.unwrap());
|
||||||
}
|
}
|
||||||
disallowed_pointees.insert(inst.result_id.unwrap());
|
disallowed_pointees.insert(inst.result_id.unwrap());
|
||||||
|
disallowed_return_types.insert(inst.result_id.unwrap());
|
||||||
}
|
}
|
||||||
Op::TypeStruct => {
|
Op::TypeStruct => {
|
||||||
if inst
|
let fields = || inst.operands.iter().map(|op| op.id_ref_any().unwrap());
|
||||||
.operands
|
if fields().any(|id| disallowed_argument_types.contains(&id)) {
|
||||||
.iter()
|
|
||||||
.map(|op| op.id_ref_any().unwrap())
|
|
||||||
.any(|id| disallowed_argument_types.contains(&id))
|
|
||||||
{
|
|
||||||
disallowed_argument_types.insert(inst.result_id.unwrap());
|
disallowed_argument_types.insert(inst.result_id.unwrap());
|
||||||
}
|
}
|
||||||
if inst
|
if fields().any(|id| disallowed_pointees.contains(&id)) {
|
||||||
.operands
|
|
||||||
.iter()
|
|
||||||
.map(|op| op.id_ref_any().unwrap())
|
|
||||||
.any(|id| disallowed_pointees.contains(&id))
|
|
||||||
{
|
|
||||||
disallowed_pointees.insert(inst.result_id.unwrap());
|
disallowed_pointees.insert(inst.result_id.unwrap());
|
||||||
}
|
}
|
||||||
|
if fields().any(|id| disallowed_return_types.contains(&id)) {
|
||||||
|
disallowed_return_types.insert(inst.result_id.unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Op::TypeArray | Op::TypeRuntimeArray | Op::TypeVector => {
|
Op::TypeArray | Op::TypeRuntimeArray | Op::TypeVector => {
|
||||||
let id = inst.operands[0].id_ref_any().unwrap();
|
let id = inst.operands[0].id_ref_any().unwrap();
|
||||||
@ -112,10 +111,14 @@ fn compute_disallowed_argument_types(module: &Module) -> FxHashSet<Word> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
disallowed_argument_types
|
(disallowed_argument_types, disallowed_return_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_inline(disallowed_argument_types: &FxHashSet<Word>, function: &Function) -> bool {
|
fn should_inline(
|
||||||
|
disallowed_argument_types: &FxHashSet<Word>,
|
||||||
|
disallowed_return_types: &FxHashSet<Word>,
|
||||||
|
function: &Function,
|
||||||
|
) -> bool {
|
||||||
let def = function.def.as_ref().unwrap();
|
let def = function.def.as_ref().unwrap();
|
||||||
let control = def.operands[0].unwrap_function_control();
|
let control = def.operands[0].unwrap_function_control();
|
||||||
control.contains(FunctionControl::INLINE)
|
control.contains(FunctionControl::INLINE)
|
||||||
@ -123,6 +126,7 @@ fn should_inline(disallowed_argument_types: &FxHashSet<Word>, function: &Functio
|
|||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.any(|inst| disallowed_argument_types.contains(inst.result_type.as_ref().unwrap()))
|
.any(|inst| disallowed_argument_types.contains(inst.result_type.as_ref().unwrap()))
|
||||||
|
|| disallowed_return_types.contains(&function.def.as_ref().unwrap().result_type.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steps:
|
// Steps:
|
||||||
@ -137,6 +141,7 @@ struct Inliner<'m, 'map> {
|
|||||||
void: Word,
|
void: Word,
|
||||||
functions: &'map FunctionMap,
|
functions: &'map FunctionMap,
|
||||||
disallowed_argument_types: &'map FxHashSet<Word>,
|
disallowed_argument_types: &'map FxHashSet<Word>,
|
||||||
|
disallowed_return_types: &'map FxHashSet<Word>,
|
||||||
// rewrite_rules: FxHashMap<Word, Word>,
|
// rewrite_rules: FxHashMap<Word, Word>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +203,13 @@ impl Inliner<'_, '_> {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.find(|(_, _, f)| should_inline(self.disallowed_argument_types, f));
|
.find(|(_, _, f)| {
|
||||||
|
should_inline(
|
||||||
|
self.disallowed_argument_types,
|
||||||
|
self.disallowed_return_types,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
});
|
||||||
let (call_index, call_inst, callee) = match call {
|
let (call_index, call_inst, callee) = match call {
|
||||||
None => return false,
|
None => return false,
|
||||||
Some(call) => call,
|
Some(call) => call,
|
||||||
|
@ -27,7 +27,6 @@ fn custom_entry_point() {
|
|||||||
pub fn main() { }
|
pub fn main() { }
|
||||||
"#,
|
"#,
|
||||||
r#"OpCapability Shader
|
r#"OpCapability Shader
|
||||||
OpCapability VariablePointers
|
|
||||||
OpMemoryModel Logical Simple
|
OpMemoryModel Logical Simple
|
||||||
OpEntryPoint Fragment %1 "hello_world"
|
OpEntryPoint Fragment %1 "hello_world"
|
||||||
OpExecutionMode %1 OriginUpperLeft
|
OpExecutionMode %1 OriginUpperLeft
|
||||||
@ -171,7 +170,6 @@ fn asm_op_decorate() {
|
|||||||
add_decorate();
|
add_decorate();
|
||||||
}"#,
|
}"#,
|
||||||
r#"OpCapability Shader
|
r#"OpCapability Shader
|
||||||
OpCapability VariablePointers
|
|
||||||
OpCapability RuntimeDescriptorArray
|
OpCapability RuntimeDescriptorArray
|
||||||
OpExtension "SPV_EXT_descriptor_indexing"
|
OpExtension "SPV_EXT_descriptor_indexing"
|
||||||
OpMemoryModel Logical Simple
|
OpMemoryModel Logical Simple
|
||||||
|
@ -26,6 +26,7 @@ pub fn main(
|
|||||||
bool_out: &mut bool,
|
bool_out: &mut bool,
|
||||||
vec_out: &mut Vec2,
|
vec_out: &mut Vec2,
|
||||||
) {
|
) {
|
||||||
|
unsafe { asm!("OpCapability VariablePointers") };
|
||||||
*scalar_out = deep_load(&&123);
|
*scalar_out = deep_load(&&123);
|
||||||
*bool_out = vec_in == &Vec2::ZERO;
|
*bool_out = vec_in == &Vec2::ZERO;
|
||||||
*vec_out = deep_transpose(&ROT90) * *vec_in;
|
*vec_out = deep_transpose(&ROT90) * *vec_in;
|
||||||
|
Loading…
Reference in New Issue
Block a user