mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Align the block decoration with SPIR-V, require storage buffers
This commit is contained in:
committed by
Dzmitry Malyshau
parent
e87f57d82c
commit
7d042337e2
@@ -1,13 +1,13 @@
|
||||
use spirv::Word;
|
||||
|
||||
pub(crate) fn bytes_to_words(bytes: &[u8]) -> Vec<Word> {
|
||||
pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec<Word> {
|
||||
bytes
|
||||
.chunks(4)
|
||||
.map(|chars| chars.iter().rev().fold(0u32, |u, c| (u << 8) | *c as u32))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn string_to_words(input: &str) -> Vec<Word> {
|
||||
pub(super) fn string_to_words(input: &str) -> Vec<Word> {
|
||||
let bytes = input.as_bytes();
|
||||
let mut words = bytes_to_words(bytes);
|
||||
|
||||
@@ -18,3 +18,15 @@ pub(crate) fn string_to_words(input: &str) -> Vec<Word> {
|
||||
|
||||
words
|
||||
}
|
||||
|
||||
pub(super) fn map_storage_class(class: crate::StorageClass) -> spirv::StorageClass {
|
||||
match class {
|
||||
crate::StorageClass::Handle => spirv::StorageClass::UniformConstant,
|
||||
crate::StorageClass::Function => spirv::StorageClass::Function,
|
||||
crate::StorageClass::Private => spirv::StorageClass::Private,
|
||||
crate::StorageClass::Storage => spirv::StorageClass::StorageBuffer,
|
||||
crate::StorageClass::Uniform => spirv::StorageClass::Uniform,
|
||||
crate::StorageClass::WorkGroup => spirv::StorageClass::Workgroup,
|
||||
crate::StorageClass::PushConstant => spirv::StorageClass::PushConstant,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,12 @@ impl super::Instruction {
|
||||
// Extension Instructions
|
||||
//
|
||||
|
||||
pub(super) fn extension(name: &str) -> Self {
|
||||
let mut instruction = Self::new(Op::Extension);
|
||||
instruction.add_operands(helpers::string_to_words(name));
|
||||
instruction
|
||||
}
|
||||
|
||||
pub(super) fn ext_inst_import(id: Word, name: &str) -> Self {
|
||||
let mut instruction = Self::new(Op::ExtInstImport);
|
||||
instruction.set_result(id);
|
||||
|
||||
@@ -23,26 +23,6 @@ impl PhysicalLayout {
|
||||
sink.extend(iter::once(self.bound));
|
||||
sink.extend(iter::once(self.instruction_schema));
|
||||
}
|
||||
|
||||
pub(super) fn supports_storage_buffers(&self) -> bool {
|
||||
self.version >= 0x10300
|
||||
}
|
||||
|
||||
pub(super) fn map_storage_class(&self, class: crate::StorageClass) -> spirv::StorageClass {
|
||||
match class {
|
||||
crate::StorageClass::Handle => spirv::StorageClass::UniformConstant,
|
||||
crate::StorageClass::Function => spirv::StorageClass::Function,
|
||||
crate::StorageClass::Private => spirv::StorageClass::Private,
|
||||
crate::StorageClass::Storage if self.supports_storage_buffers() => {
|
||||
spirv::StorageClass::StorageBuffer
|
||||
}
|
||||
crate::StorageClass::Storage | crate::StorageClass::Uniform => {
|
||||
spirv::StorageClass::Uniform
|
||||
}
|
||||
crate::StorageClass::WorkGroup => spirv::StorageClass::Workgroup,
|
||||
crate::StorageClass::PushConstant => spirv::StorageClass::PushConstant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogicalLayout {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*! Standard Portable Intermediate Representation (SPIR-V) backend
|
||||
!*/
|
||||
|
||||
mod helpers;
|
||||
mod instructions;
|
||||
mod layout;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*! Standard Portable Intermediate Representation (SPIR-V) backend !*/
|
||||
use super::{Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags};
|
||||
use super::{
|
||||
helpers::map_storage_class, Instruction, LogicalLayout, Options, PhysicalLayout, WriterFlags,
|
||||
};
|
||||
use crate::{
|
||||
arena::{Arena, Handle},
|
||||
proc::{Layouter, TypeResolution},
|
||||
@@ -141,7 +142,7 @@ impl PhysicalLayout {
|
||||
},
|
||||
crate::TypeInner::Pointer { base, class } => LocalType::Pointer {
|
||||
base,
|
||||
class: self.map_storage_class(class),
|
||||
class: map_storage_class(class),
|
||||
},
|
||||
crate::TypeInner::ValuePointer {
|
||||
size,
|
||||
@@ -152,7 +153,7 @@ impl PhysicalLayout {
|
||||
vector_size: size,
|
||||
kind,
|
||||
width,
|
||||
pointer_class: Some(self.map_storage_class(class)),
|
||||
pointer_class: Some(map_storage_class(class)),
|
||||
},
|
||||
_ => return None,
|
||||
})
|
||||
@@ -266,9 +267,6 @@ pub struct Writer {
|
||||
lookup_constant: crate::FastHashMap<Handle<crate::Constant>, Word>,
|
||||
global_variables: Vec<GlobalVariable>,
|
||||
cached: CachedExpressions,
|
||||
// TODO: this is a type property that depends on the global variable that uses it
|
||||
// so it may require us to duplicate the type!
|
||||
struct_type_handles: crate::FastHashMap<Handle<crate::Type>, crate::StorageAccess>,
|
||||
gl450_ext_inst_id: Word,
|
||||
temp_chain: Vec<Word>,
|
||||
}
|
||||
@@ -283,6 +281,7 @@ impl Writer {
|
||||
let mut id_gen = IdGenerator::default();
|
||||
let gl450_ext_inst_id = id_gen.next();
|
||||
let void_type = id_gen.next();
|
||||
|
||||
Ok(Writer {
|
||||
physical_layout: PhysicalLayout::new(raw_version),
|
||||
logical_layout: LogicalLayout::default(),
|
||||
@@ -299,7 +298,6 @@ impl Writer {
|
||||
lookup_constant: crate::FastHashMap::default(),
|
||||
global_variables: Vec::new(),
|
||||
cached: CachedExpressions::default(),
|
||||
struct_type_handles: crate::FastHashMap::default(),
|
||||
gl450_ext_inst_id,
|
||||
temp_chain: Vec::new(),
|
||||
})
|
||||
@@ -815,18 +813,10 @@ impl Writer {
|
||||
crate::ArraySize::Dynamic => Instruction::type_runtime_array(id, type_id),
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Struct {
|
||||
block: true,
|
||||
ref members,
|
||||
} => {
|
||||
if let Some(&access) = self.struct_type_handles.get(&handle) {
|
||||
let decoration = if access.is_empty() {
|
||||
spirv::Decoration::Block
|
||||
} else {
|
||||
spirv::Decoration::BufferBlock
|
||||
};
|
||||
crate::TypeInner::Struct { block, ref members } => {
|
||||
if block {
|
||||
self.annotations
|
||||
.push(Instruction::decorate(id, decoration, &[]));
|
||||
.push(Instruction::decorate(id, spirv::Decoration::Block, &[]));
|
||||
}
|
||||
|
||||
let mut current_offset = 0;
|
||||
@@ -877,20 +867,9 @@ impl Writer {
|
||||
}
|
||||
Instruction::type_struct(id, member_ids.as_slice())
|
||||
}
|
||||
crate::TypeInner::Struct {
|
||||
block: false,
|
||||
ref members,
|
||||
} => {
|
||||
let mut member_ids = Vec::with_capacity(members.len());
|
||||
for member in members {
|
||||
let member_id = self.get_type_id(arena, LookupType::Handle(member.ty))?;
|
||||
member_ids.push(member_id);
|
||||
}
|
||||
Instruction::type_struct(id, member_ids.as_slice())
|
||||
}
|
||||
crate::TypeInner::Pointer { base, class } => {
|
||||
let type_id = self.get_type_id(arena, LookupType::Handle(base))?;
|
||||
let raw_class = self.physical_layout.map_storage_class(class);
|
||||
let raw_class = map_storage_class(class);
|
||||
Instruction::type_pointer(id, raw_class, type_id)
|
||||
}
|
||||
crate::TypeInner::ValuePointer {
|
||||
@@ -899,7 +878,7 @@ impl Writer {
|
||||
width,
|
||||
class,
|
||||
} => {
|
||||
let raw_class = self.physical_layout.map_storage_class(class);
|
||||
let raw_class = map_storage_class(class);
|
||||
let type_id = self.get_type_id(
|
||||
arena,
|
||||
LookupType::Local(LocalType::Value {
|
||||
@@ -1091,9 +1070,7 @@ impl Writer {
|
||||
) -> Result<(Instruction, Word, spirv::StorageClass), Error> {
|
||||
let id = self.id_gen.next();
|
||||
|
||||
let class = self
|
||||
.physical_layout
|
||||
.map_storage_class(global_variable.class);
|
||||
let class = map_storage_class(global_variable.class);
|
||||
self.check(class.required_capabilities())?;
|
||||
|
||||
let init_word = global_variable
|
||||
@@ -2345,6 +2322,15 @@ impl Writer {
|
||||
ir_module: &crate::Module,
|
||||
mod_info: &ModuleInfo,
|
||||
) -> Result<(), Error> {
|
||||
let has_storage_buffers = ir_module
|
||||
.global_variables
|
||||
.iter()
|
||||
.any(|(_, var)| var.class == crate::StorageClass::Storage);
|
||||
if self.physical_layout.version < 0x10300 && has_storage_buffers {
|
||||
// enable the storage buffer class on < SPV-1.3
|
||||
Instruction::extension("SPV_KHR_storage_buffer_storage_class")
|
||||
.to_words(&mut self.logical_layout.extensions);
|
||||
}
|
||||
Instruction::type_void(self.void_type).to_words(&mut self.logical_layout.declarations);
|
||||
Instruction::ext_inst_import(self.gl450_ext_inst_id, "GLSL.std.450")
|
||||
.to_words(&mut self.logical_layout.ext_inst_imports);
|
||||
@@ -2371,14 +2357,6 @@ impl Writer {
|
||||
}
|
||||
}
|
||||
|
||||
// then gather the struct type handles, then affect types
|
||||
self.struct_type_handles.clear();
|
||||
for (_, var) in ir_module.global_variables.iter() {
|
||||
if let crate::TypeInner::Struct { .. } = ir_module.types[var.ty].inner {
|
||||
self.struct_type_handles.insert(var.ty, var.storage_access);
|
||||
}
|
||||
}
|
||||
|
||||
// then all types, some of them may rely on constants and struct type set
|
||||
for (handle, _) in ir_module.types.iter() {
|
||||
self.write_type_declaration_arena(&ir_module.types, &mod_info.layouter, handle)?;
|
||||
|
||||
@@ -2406,7 +2406,6 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
|
||||
let mut members = Vec::with_capacity(inst.wc as usize - 2);
|
||||
let mut member_type_ids = Vec::with_capacity(members.capacity());
|
||||
let mut host_shared = false;
|
||||
for i in 0..u32::from(inst.wc) - 2 {
|
||||
let type_id = self.next()?;
|
||||
member_type_ids.push(type_id);
|
||||
@@ -2415,8 +2414,6 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
.future_member_decor
|
||||
.remove(&(id, i))
|
||||
.unwrap_or_default();
|
||||
// this is a bit of a hack
|
||||
host_shared |= decor.offset.is_some();
|
||||
members.push(crate::StructMember {
|
||||
name: decor.name,
|
||||
ty,
|
||||
@@ -2427,7 +2424,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
}
|
||||
|
||||
let inner = crate::TypeInner::Struct {
|
||||
block: block_decor.is_some() || host_shared,
|
||||
block: block_decor.is_some(),
|
||||
members,
|
||||
};
|
||||
let ty_handle = module.types.append(crate::Type {
|
||||
|
||||
@@ -393,6 +393,7 @@ pub enum TypeInner {
|
||||
},
|
||||
/// User-defined structure.
|
||||
Struct {
|
||||
/// This is a top-level host-shareable structure.
|
||||
block: bool,
|
||||
members: Vec<StructMember>,
|
||||
},
|
||||
|
||||
@@ -272,42 +272,32 @@ impl super::Validator {
|
||||
let (allowed_storage_access, required_type_flags, is_resource) = match var.class {
|
||||
crate::StorageClass::Function => return Err(GlobalVariableError::InvalidUsage),
|
||||
crate::StorageClass::Storage => {
|
||||
match types[var.ty].inner {
|
||||
crate::TypeInner::Struct { block: true, .. } => {
|
||||
if let Err((ty_handle, ref disalignment)) = type_info.storage_layout {
|
||||
if self.flags.contains(ValidationFlags::STRUCT_LAYOUTS) {
|
||||
return Err(GlobalVariableError::Alignment(
|
||||
ty_handle,
|
||||
disalignment.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Err((ty_handle, ref disalignment)) = type_info.storage_layout {
|
||||
if self.flags.contains(ValidationFlags::STRUCT_LAYOUTS) {
|
||||
return Err(GlobalVariableError::Alignment(
|
||||
ty_handle,
|
||||
disalignment.clone(),
|
||||
));
|
||||
}
|
||||
_ => return Err(GlobalVariableError::InvalidType),
|
||||
}
|
||||
(
|
||||
crate::StorageAccess::all(),
|
||||
TypeFlags::DATA | TypeFlags::HOST_SHARED,
|
||||
TypeFlags::DATA | TypeFlags::HOST_SHARED | TypeFlags::BLOCK,
|
||||
true,
|
||||
)
|
||||
}
|
||||
crate::StorageClass::Uniform => {
|
||||
match types[var.ty].inner {
|
||||
crate::TypeInner::Struct { block: true, .. } => {
|
||||
if let Err((ty_handle, ref disalignment)) = type_info.uniform_layout {
|
||||
if self.flags.contains(ValidationFlags::STRUCT_LAYOUTS) {
|
||||
return Err(GlobalVariableError::Alignment(
|
||||
ty_handle,
|
||||
disalignment.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Err((ty_handle, ref disalignment)) = type_info.uniform_layout {
|
||||
if self.flags.contains(ValidationFlags::STRUCT_LAYOUTS) {
|
||||
return Err(GlobalVariableError::Alignment(
|
||||
ty_handle,
|
||||
disalignment.clone(),
|
||||
));
|
||||
}
|
||||
_ => return Err(GlobalVariableError::InvalidType),
|
||||
}
|
||||
(
|
||||
crate::StorageAccess::empty(),
|
||||
TypeFlags::DATA | TypeFlags::SIZED | TypeFlags::HOST_SHARED,
|
||||
TypeFlags::DATA | TypeFlags::SIZED | TypeFlags::HOST_SHARED | TypeFlags::BLOCK,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ bitflags::bitflags! {
|
||||
const INTERFACE = 0x4;
|
||||
/// Can be used for host-shareable structures.
|
||||
const HOST_SHARED = 0x8;
|
||||
/// This is a top-level host-shareable type.
|
||||
const BLOCK = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +63,8 @@ pub enum TypeError {
|
||||
size: u32,
|
||||
base_size: u32,
|
||||
},
|
||||
#[error("The composite type contains a block structure")]
|
||||
NestedBlock,
|
||||
}
|
||||
|
||||
// Only makes sense if `flags.contains(HOST_SHARED)`
|
||||
@@ -163,6 +167,9 @@ impl super::Validator {
|
||||
if !base_info.flags.contains(TypeFlags::DATA | TypeFlags::SIZED) {
|
||||
return Err(TypeError::InvalidArrayBaseType(base));
|
||||
}
|
||||
if base_info.flags.contains(TypeFlags::BLOCK) {
|
||||
return Err(TypeError::NestedBlock);
|
||||
}
|
||||
|
||||
let base_layout = &layouter[base];
|
||||
if let Some(stride) = stride {
|
||||
@@ -239,7 +246,10 @@ impl super::Validator {
|
||||
}
|
||||
}
|
||||
Ti::Struct { block, ref members } => {
|
||||
let mut flags = TypeFlags::all();
|
||||
let mut flags = TypeFlags::DATA
|
||||
| TypeFlags::SIZED
|
||||
| TypeFlags::HOST_SHARED
|
||||
| TypeFlags::INTERFACE;
|
||||
let mut uniform_layout = Ok(());
|
||||
let mut storage_layout = Ok(());
|
||||
let mut offset = 0;
|
||||
@@ -248,13 +258,16 @@ impl super::Validator {
|
||||
return Err(TypeError::UnresolvedBase(member.ty));
|
||||
}
|
||||
let base_info = &self.types[member.ty.index()];
|
||||
flags &= base_info.flags;
|
||||
if !base_info.flags.contains(TypeFlags::DATA) {
|
||||
return Err(TypeError::InvalidData(member.ty));
|
||||
}
|
||||
if block && !base_info.flags.contains(TypeFlags::INTERFACE) {
|
||||
return Err(TypeError::InvalidBlockType(member.ty));
|
||||
}
|
||||
if base_info.flags.contains(TypeFlags::BLOCK) {
|
||||
return Err(TypeError::NestedBlock);
|
||||
}
|
||||
flags &= base_info.flags;
|
||||
|
||||
let base_layout = &layouter[member.ty];
|
||||
let (range, _alignment) = layouter.member_placement(offset, member);
|
||||
@@ -294,6 +307,9 @@ impl super::Validator {
|
||||
uniform_layout = uniform_layout.or_else(|_| base_info.uniform_layout.clone());
|
||||
storage_layout = storage_layout.or_else(|_| base_info.storage_layout.clone());
|
||||
}
|
||||
if block {
|
||||
flags |= TypeFlags::BLOCK;
|
||||
}
|
||||
|
||||
// disabled temporarily, see https://github.com/gpuweb/gpuweb/issues/1558
|
||||
const CHECK_STRUCT_SIZE: bool = false;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const NUM_PARTICLES: u32 = 1500u;
|
||||
|
||||
[[block]]
|
||||
struct Particle {
|
||||
pos : vec2<f32>;
|
||||
vel : vec2<f32>;
|
||||
|
||||
@@ -6,7 +6,6 @@ struct Globals {
|
||||
[[group(0), binding(0)]]
|
||||
var<uniform> u_globals: Globals;
|
||||
|
||||
[[block]]
|
||||
struct Light {
|
||||
proj: mat4x4<f32>;
|
||||
pos: vec4<f32>;
|
||||
|
||||
@@ -7,6 +7,7 @@ expression: dis
|
||||
; Generator: rspirv
|
||||
; Bound: 221
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %43 "main" %40
|
||||
@@ -53,7 +54,7 @@ OpMemberDecorate %17 4 Offset 16
|
||||
OpMemberDecorate %17 5 Offset 20
|
||||
OpMemberDecorate %17 6 Offset 24
|
||||
OpDecorate %18 ArrayStride 16
|
||||
OpDecorate %19 BufferBlock
|
||||
OpDecorate %19 Block
|
||||
OpMemberDecorate %19 0 Offset 0
|
||||
OpDecorate %21 DescriptorSet 0
|
||||
OpDecorate %21 Binding 0
|
||||
@@ -84,9 +85,9 @@ OpDecorate %40 BuiltIn GlobalInvocationId
|
||||
%20 = OpTypeVector %4 3
|
||||
%22 = OpTypePointer Uniform %17
|
||||
%21 = OpVariable %22 Uniform
|
||||
%24 = OpTypePointer Uniform %19
|
||||
%23 = OpVariable %24 Uniform
|
||||
%25 = OpVariable %24 Uniform
|
||||
%24 = OpTypePointer StorageBuffer %19
|
||||
%23 = OpVariable %24 StorageBuffer
|
||||
%25 = OpVariable %24 StorageBuffer
|
||||
%27 = OpTypePointer Function %15
|
||||
%33 = OpTypePointer Function %8
|
||||
%38 = OpTypePointer Function %4
|
||||
@@ -94,9 +95,9 @@ OpDecorate %40 BuiltIn GlobalInvocationId
|
||||
%40 = OpVariable %41 Input
|
||||
%44 = OpTypeFunction %2
|
||||
%47 = OpTypeBool
|
||||
%51 = OpTypePointer Uniform %18
|
||||
%52 = OpTypePointer Uniform %16
|
||||
%53 = OpTypePointer Uniform %15
|
||||
%51 = OpTypePointer StorageBuffer %18
|
||||
%52 = OpTypePointer StorageBuffer %16
|
||||
%53 = OpTypePointer StorageBuffer %15
|
||||
%54 = OpConstant %8 0
|
||||
%55 = OpConstant %8 0
|
||||
%58 = OpConstant %8 1
|
||||
|
||||
@@ -7,6 +7,7 @@ expression: dis
|
||||
; Generator: rspirv
|
||||
; Bound: 62
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %48 "main" %45
|
||||
@@ -22,7 +23,7 @@ OpName %45 "global_id"
|
||||
OpName %48 "main"
|
||||
OpName %48 "main"
|
||||
OpDecorate %8 ArrayStride 4
|
||||
OpDecorate %9 BufferBlock
|
||||
OpDecorate %9 Block
|
||||
OpMemberDecorate %9 0 Offset 0
|
||||
OpDecorate %11 DescriptorSet 0
|
||||
OpDecorate %11 Binding 0
|
||||
@@ -36,16 +37,16 @@ OpDecorate %45 BuiltIn GlobalInvocationId
|
||||
%8 = OpTypeRuntimeArray %4
|
||||
%9 = OpTypeStruct %8
|
||||
%10 = OpTypeVector %4 3
|
||||
%12 = OpTypePointer Uniform %9
|
||||
%11 = OpVariable %12 Uniform
|
||||
%12 = OpTypePointer StorageBuffer %9
|
||||
%11 = OpVariable %12 StorageBuffer
|
||||
%14 = OpTypePointer Function %4
|
||||
%19 = OpTypeFunction %4 %4
|
||||
%26 = OpTypeBool
|
||||
%46 = OpTypePointer Input %10
|
||||
%45 = OpVariable %46 Input
|
||||
%49 = OpTypeFunction %2
|
||||
%51 = OpTypePointer Uniform %8
|
||||
%53 = OpTypePointer Uniform %4
|
||||
%51 = OpTypePointer StorageBuffer %8
|
||||
%53 = OpTypePointer StorageBuffer %4
|
||||
%55 = OpTypeInt 32 1
|
||||
%56 = OpConstant %55 0
|
||||
%60 = OpConstant %55 0
|
||||
|
||||
@@ -15,6 +15,8 @@ OpExecutionMode %47 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %3 "c_scale"
|
||||
OpName %9 "VertexOutput"
|
||||
OpMemberName %9 0 "uv"
|
||||
OpMemberName %9 1 "position"
|
||||
OpName %12 "u_texture"
|
||||
OpName %14 "u_sampler"
|
||||
OpName %16 "out"
|
||||
@@ -27,6 +29,8 @@ OpName %28 "main"
|
||||
OpName %44 "uv"
|
||||
OpName %47 "main"
|
||||
OpName %47 "main"
|
||||
OpMemberDecorate %9 0 Offset 0
|
||||
OpMemberDecorate %9 1 Offset 8
|
||||
OpDecorate %12 DescriptorSet 0
|
||||
OpDecorate %12 Binding 0
|
||||
OpDecorate %14 DescriptorSet 0
|
||||
|
||||
@@ -150,7 +150,7 @@ expression: output
|
||||
(
|
||||
name: Some("Light"),
|
||||
inner: Struct(
|
||||
block: true,
|
||||
block: false,
|
||||
members: [
|
||||
(
|
||||
name: Some("proj"),
|
||||
|
||||
@@ -7,6 +7,7 @@ expression: dis
|
||||
; Generator: rspirv
|
||||
; Bound: 137
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %81 "fs_main" %73 %76 %79
|
||||
@@ -41,7 +42,7 @@ OpMemberDecorate %17 0 MatrixStride 16
|
||||
OpMemberDecorate %17 1 Offset 64
|
||||
OpMemberDecorate %17 2 Offset 80
|
||||
OpDecorate %18 ArrayStride 96
|
||||
OpDecorate %19 BufferBlock
|
||||
OpDecorate %19 Block
|
||||
OpMemberDecorate %19 0 Offset 0
|
||||
OpDecorate %25 DescriptorSet 0
|
||||
OpDecorate %25 Binding 0
|
||||
@@ -80,8 +81,8 @@ OpDecorate %79 Location 0
|
||||
%24 = OpConstantComposite %23 %8 %8 %8
|
||||
%26 = OpTypePointer Uniform %14
|
||||
%25 = OpVariable %26 Uniform
|
||||
%28 = OpTypePointer Uniform %19
|
||||
%27 = OpVariable %28 Uniform
|
||||
%28 = OpTypePointer StorageBuffer %19
|
||||
%27 = OpVariable %28 StorageBuffer
|
||||
%30 = OpTypePointer UniformConstant %20
|
||||
%29 = OpVariable %30 UniformConstant
|
||||
%32 = OpTypePointer UniformConstant %21
|
||||
@@ -102,8 +103,8 @@ OpDecorate %79 Location 0
|
||||
%82 = OpTypeFunction %2
|
||||
%92 = OpTypePointer Uniform %13
|
||||
%93 = OpConstant %56 0
|
||||
%101 = OpTypePointer Uniform %18
|
||||
%103 = OpTypePointer Uniform %17
|
||||
%101 = OpTypePointer StorageBuffer %18
|
||||
%103 = OpTypePointer StorageBuffer %17
|
||||
%104 = OpConstant %56 0
|
||||
%36 = OpFunction %4 None %37
|
||||
%34 = OpFunctionParameter %10
|
||||
|
||||
@@ -14,6 +14,8 @@ OpEntryPoint Fragment %108 "fs_main" %101 %104 %107
|
||||
OpExecutionMode %108 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %12 "VertexOutput"
|
||||
OpMemberName %12 0 "position"
|
||||
OpMemberName %12 1 "uv"
|
||||
OpName %14 "Data"
|
||||
OpMemberName %14 0 "proj_inv"
|
||||
OpMemberName %14 1 "view"
|
||||
@@ -32,6 +34,8 @@ OpName %101 "position"
|
||||
OpName %104 "uv"
|
||||
OpName %108 "fs_main"
|
||||
OpName %108 "fs_main"
|
||||
OpMemberDecorate %12 0 Offset 0
|
||||
OpMemberDecorate %12 1 Offset 16
|
||||
OpDecorate %14 Block
|
||||
OpMemberDecorate %14 0 Offset 0
|
||||
OpMemberDecorate %14 0 ColMajor
|
||||
|
||||
Reference in New Issue
Block a user