/* Copyright (c) 2021-2024 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * The Shader Module file is in charge of all things around creating and parsing an internal representation of a shader module */ #pragma once #include <cassert> #include <cstdlib> #include <cstring> #include <vector> #include "state_tracker/shader_instruction.h" #include "state_tracker/state_object.h" #include "state_tracker/sampler_state.h" #include <spirv/unified1/spirv.hpp> namespace vvl { class Pipeline; } // namespace vvl namespace spirv { struct EntryPoint; struct Module; static constexpr uint32_t kInvalidValue = …; // Need to find a way to know if actually array lenght of zero, or a runtime array. static constexpr uint32_t kRuntimeArray = …; // This is the common info for both OpDecorate and OpMemberDecorate // Used to keep track of all decorations applied to any instruction struct DecorationBase { … }; // subset only for OpDecorate // Can't have nested structs with OpMemberDecorate, this class prevents accidently creating a 2nd level of member decorations, struct DecorationSet : public DecorationBase { … }; // Tracking of OpExecutionMode / OpExecutionModeId values struct ExecutionModeSet { … }; struct AtomicInstructionInfo { … }; // This info *could* be found/saved in TypeStructInfo, but since // - Only a few places (Push Constants, workgroup size) use this // - It is only good when you know there are no nested strcuts // we only get this info when needed, not for every struct struct TypeStructSize { … }; // Contains all the details for a OpTypeStruct struct TypeStructInfo { … }; namespace AccessBit { const uint32_t empty = …; const uint32_t read = …; const uint32_t write = …; const uint32_t atomic_read = …; const uint32_t atomic_write = …; const uint32_t image_read = …; const uint32_t image_write = …; constexpr uint32_t atomic_mask = …; constexpr uint32_t image_mask = …; constexpr uint32_t read_mask = …; constexpr uint32_t write_mask = …; } // namespace AccessBit // Mapping of < variable ID, AccessBit > VariableAccessMap; // Track all paths from %param to %arg so can walk back functions // // %arg = OpVariable // %call = OpFunctionCall %result %func %arg // %param = OpFunctionParameter // // < %param, vector<%arg> > FuncParameterMap; // Represents the OpImage* instructions and how it maps to the variable // This is created in the Module but then used with VariableBase objects struct ImageAccess { … }; // <Image OpVariable Result ID, [ImageAccess, ImageAccess, etc] > - used for faster lookup // Many ImageAccess can point to a single Image Variable ImageAccessMap; // < Variable ID, [ OpAccessChain ] > // Allows for grouping the access chains by which variables they are actually accessing AccessChainVariableMap; // Mapping of OpName instructions DebugNameMap; // A slot is a <Location, Component> mapping struct InterfaceSlot { … }; // Represents the Image formats that can map to a SPIR-V format enum NumericType { … }; uint32_t GetFormatType(VkFormat format); char const *string_NumericType(uint32_t type); // Common info needed for all OpVariable struct VariableBase { … }; // These are Input/Output OpVariable that go in-between stages // (also for example the input to a Vertex and output of the Fragment). // These are always ints/floats (not images or samplers). // Besides the input vertex binding, all of these are fully known at pipeline creation time // // These include both BuiltIns and User Defined, while there are difference in member variables, the variables are needed for the // common logic so its easier using the same object in the end struct StageInterfaceVariable : public VariableBase { … }; // vkspec.html#interfaces-resources describes 'Shader Resource Interface' // These are the OpVariable attached to descriptors. // The slots are known at Pipeline creation time, but the type images/sampler/etc is // not known until the descriptors are bound. // The main purpose of this struct is to track what operations are statically done so // at draw/submit time we can cross reference with the last bound descriptor. struct ResourceInterfaceVariable : public VariableBase { … }; // Used to help detect if different variable is being used inline bool operator==(const ResourceInterfaceVariable &a, const ResourceInterfaceVariable &b) noexcept { … } inline bool operator<(const ResourceInterfaceVariable &a, const ResourceInterfaceVariable &b) noexcept { … } // vkspec.html#interfaces-resources-pushconst // Push constants need to be statically used in shader // Push constants are always OpTypeStruct and Block decorated struct PushConstantVariable : public VariableBase { … }; // Represents a single Entrypoint into a Shader Module struct EntryPoint { … }; // Info to capture while parsing the SPIR-V, but will only be used by ValidateSpirvStateless and don't need to save after struct StatelessData { … }; // Represents a SPIR-V Module // This holds the SPIR-V source and parse it struct Module { … }; } // namespace spirv // Represents a VkShaderModule handle namespace vvl { struct ShaderModule : public StateObject { … }; } // namespace vvl