| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // DxilOperations.cpp // |
| // Copyright (C) Microsoft Corporation. All rights reserved. // |
| // This file is distributed under the University of Illinois Open Source // |
| // License. See LICENSE.TXT for details. // |
| // // |
| // Implementation of DXIL operation tables. // |
| // // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #include "dxc/DXIL/DxilOperations.h" |
| #include "dxc/DXIL/DxilInstructions.h" |
| #include "dxc/DXIL/DxilModule.h" |
| #include "dxc/Support/Global.h" |
| |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/IR/Constants.h" |
| #include "llvm/IR/Instructions.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace llvm; |
| using std::string; |
| using std::vector; |
| |
| namespace hlsl { |
| |
| using OC = OP::OpCode; |
| using OCC = OP::OpCodeClass; |
| |
| //------------------------------------------------------------------------------ |
| // |
| // OP class const-static data and related static methods. |
| // |
| /* <py> |
| import hctdb_instrhelp |
| </py> */ |
| /* <py::lines('OPCODE-OLOADS')>hctdb_instrhelp.get_oloads_props()</py>*/ |
| // OPCODE-OLOADS:BEGIN |
| const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = { |
| // OpCode OpCode name, OpCodeClass |
| // OpCodeClass name, void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj, function attribute |
| // Temporary, indexable, input, output registers void, h, f, d, |
| // i1, i8, i16, i32, i64, udt, obj , function attribute |
| { |
| OC::TempRegLoad, |
| "TempRegLoad", |
| OCC::TempRegLoad, |
| "tempRegLoad", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::TempRegStore, |
| "TempRegStore", |
| OCC::TempRegStore, |
| "tempRegStore", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::MinPrecXRegLoad, |
| "MinPrecXRegLoad", |
| OCC::MinPrecXRegLoad, |
| "minPrecXRegLoad", |
| {false, true, false, false, false, false, true, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::MinPrecXRegStore, |
| "MinPrecXRegStore", |
| OCC::MinPrecXRegStore, |
| "minPrecXRegStore", |
| {false, true, false, false, false, false, true, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::LoadInput, |
| "LoadInput", |
| OCC::LoadInput, |
| "loadInput", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::StoreOutput, |
| "StoreOutput", |
| OCC::StoreOutput, |
| "storeOutput", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Unary float void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::FAbs, |
| "FAbs", |
| OCC::Unary, |
| "unary", |
| {false, true, true, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Saturate, |
| "Saturate", |
| OCC::Unary, |
| "unary", |
| {false, true, true, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IsNaN, |
| "IsNaN", |
| OCC::IsSpecialFloat, |
| "isSpecialFloat", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IsInf, |
| "IsInf", |
| OCC::IsSpecialFloat, |
| "isSpecialFloat", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IsFinite, |
| "IsFinite", |
| OCC::IsSpecialFloat, |
| "isSpecialFloat", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IsNormal, |
| "IsNormal", |
| OCC::IsSpecialFloat, |
| "isSpecialFloat", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Cos, |
| "Cos", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Sin, |
| "Sin", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Tan, |
| "Tan", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Acos, |
| "Acos", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Asin, |
| "Asin", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Atan, |
| "Atan", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Hcos, |
| "Hcos", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Hsin, |
| "Hsin", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Htan, |
| "Htan", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Exp, |
| "Exp", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Frc, |
| "Frc", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Log, |
| "Log", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Sqrt, |
| "Sqrt", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Rsqrt, |
| "Rsqrt", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Unary float - rounding void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::Round_ne, |
| "Round_ne", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Round_ni, |
| "Round_ni", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Round_pi, |
| "Round_pi", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Round_z, |
| "Round_z", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Unary int void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::Bfrev, |
| "Bfrev", |
| OCC::Unary, |
| "unary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Countbits, |
| "Countbits", |
| OCC::UnaryBits, |
| "unaryBits", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::FirstbitLo, |
| "FirstbitLo", |
| OCC::UnaryBits, |
| "unaryBits", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Unary uint void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::FirstbitHi, |
| "FirstbitHi", |
| OCC::UnaryBits, |
| "unaryBits", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Unary int void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::FirstbitSHi, |
| "FirstbitSHi", |
| OCC::UnaryBits, |
| "unaryBits", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary float void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::FMax, |
| "FMax", |
| OCC::Binary, |
| "binary", |
| {false, true, true, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::FMin, |
| "FMin", |
| OCC::Binary, |
| "binary", |
| {false, true, true, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary int void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::IMax, |
| "IMax", |
| OCC::Binary, |
| "binary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IMin, |
| "IMin", |
| OCC::Binary, |
| "binary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary uint void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::UMax, |
| "UMax", |
| OCC::Binary, |
| "binary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::UMin, |
| "UMin", |
| OCC::Binary, |
| "binary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary int with two outputs void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::IMul, |
| "IMul", |
| OCC::BinaryWithTwoOuts, |
| "binaryWithTwoOuts", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary uint with two outputs void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::UMul, |
| "UMul", |
| OCC::BinaryWithTwoOuts, |
| "binaryWithTwoOuts", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::UDiv, |
| "UDiv", |
| OCC::BinaryWithTwoOuts, |
| "binaryWithTwoOuts", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Binary uint with carry or borrow void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::UAddc, |
| "UAddc", |
| OCC::BinaryWithCarryOrBorrow, |
| "binaryWithCarryOrBorrow", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::USubb, |
| "USubb", |
| OCC::BinaryWithCarryOrBorrow, |
| "binaryWithCarryOrBorrow", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Tertiary float void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::FMad, |
| "FMad", |
| OCC::Tertiary, |
| "tertiary", |
| {false, true, true, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Fma, |
| "Fma", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Tertiary int void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::IMad, |
| "IMad", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Tertiary uint void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::UMad, |
| "UMad", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Tertiary int void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::Msad, |
| "Msad", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, false, false, false, false, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Ibfe, |
| "Ibfe", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, false, false, false, false, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Tertiary uint void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::Ubfe, |
| "Ubfe", |
| OCC::Tertiary, |
| "tertiary", |
| {false, false, false, false, false, false, false, true, true, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Quaternary void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::Bfi, |
| "Bfi", |
| OCC::Quaternary, |
| "quaternary", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Dot void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::Dot2, |
| "Dot2", |
| OCC::Dot2, |
| "dot2", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Dot3, |
| "Dot3", |
| OCC::Dot3, |
| "dot3", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Dot4, |
| "Dot4", |
| OCC::Dot4, |
| "dot4", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Resources void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::CreateHandle, |
| "CreateHandle", |
| OCC::CreateHandle, |
| "createHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::CBufferLoad, |
| "CBufferLoad", |
| OCC::CBufferLoad, |
| "cbufferLoad", |
| {false, true, true, true, false, true, true, true, true, false, false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::CBufferLoadLegacy, |
| "CBufferLoadLegacy", |
| OCC::CBufferLoadLegacy, |
| "cbufferLoadLegacy", |
| {false, true, true, true, false, false, true, true, true, false, false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources - sample void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::Sample, |
| "Sample", |
| OCC::Sample, |
| "sample", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleBias, |
| "SampleBias", |
| OCC::SampleBias, |
| "sampleBias", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleLevel, |
| "SampleLevel", |
| OCC::SampleLevel, |
| "sampleLevel", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleGrad, |
| "SampleGrad", |
| OCC::SampleGrad, |
| "sampleGrad", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleCmp, |
| "SampleCmp", |
| OCC::SampleCmp, |
| "sampleCmp", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleCmpLevelZero, |
| "SampleCmpLevelZero", |
| OCC::SampleCmpLevelZero, |
| "sampleCmpLevelZero", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::TextureLoad, |
| "TextureLoad", |
| OCC::TextureLoad, |
| "textureLoad", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::TextureStore, |
| "TextureStore", |
| OCC::TextureStore, |
| "textureStore", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::BufferLoad, |
| "BufferLoad", |
| OCC::BufferLoad, |
| "bufferLoad", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::BufferStore, |
| "BufferStore", |
| OCC::BufferStore, |
| "bufferStore", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::BufferUpdateCounter, |
| "BufferUpdateCounter", |
| OCC::BufferUpdateCounter, |
| "bufferUpdateCounter", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::CheckAccessFullyMapped, |
| "CheckAccessFullyMapped", |
| OCC::CheckAccessFullyMapped, |
| "checkAccessFullyMapped", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::GetDimensions, |
| "GetDimensions", |
| OCC::GetDimensions, |
| "getDimensions", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources - gather void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::TextureGather, |
| "TextureGather", |
| OCC::TextureGather, |
| "textureGather", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::TextureGatherCmp, |
| "TextureGatherCmp", |
| OCC::TextureGatherCmp, |
| "textureGatherCmp", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources - sample void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::Texture2DMSGetSamplePosition, |
| "Texture2DMSGetSamplePosition", |
| OCC::Texture2DMSGetSamplePosition, |
| "texture2DMSGetSamplePosition", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RenderTargetGetSamplePosition, |
| "RenderTargetGetSamplePosition", |
| OCC::RenderTargetGetSamplePosition, |
| "renderTargetGetSamplePosition", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RenderTargetGetSampleCount, |
| "RenderTargetGetSampleCount", |
| OCC::RenderTargetGetSampleCount, |
| "renderTargetGetSampleCount", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Synchronization void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::AtomicBinOp, |
| "AtomicBinOp", |
| OCC::AtomicBinOp, |
| "atomicBinOp", |
| {false, false, false, false, false, false, false, true, true, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::AtomicCompareExchange, |
| "AtomicCompareExchange", |
| OCC::AtomicCompareExchange, |
| "atomicCompareExchange", |
| {false, false, false, false, false, false, false, true, true, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::Barrier, |
| "Barrier", |
| OCC::Barrier, |
| "barrier", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoDuplicate, |
| }, |
| |
| // Derivatives void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::CalculateLOD, |
| "CalculateLOD", |
| OCC::CalculateLOD, |
| "calculateLOD", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Pixel shader void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::Discard, |
| "Discard", |
| OCC::Discard, |
| "discard", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Derivatives void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::DerivCoarseX, |
| "DerivCoarseX", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::DerivCoarseY, |
| "DerivCoarseY", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::DerivFineX, |
| "DerivFineX", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::DerivFineY, |
| "DerivFineY", |
| OCC::Unary, |
| "unary", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Pixel shader void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::EvalSnapped, |
| "EvalSnapped", |
| OCC::EvalSnapped, |
| "evalSnapped", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::EvalSampleIndex, |
| "EvalSampleIndex", |
| OCC::EvalSampleIndex, |
| "evalSampleIndex", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::EvalCentroid, |
| "EvalCentroid", |
| OCC::EvalCentroid, |
| "evalCentroid", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::SampleIndex, |
| "SampleIndex", |
| OCC::SampleIndex, |
| "sampleIndex", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Coverage, |
| "Coverage", |
| OCC::Coverage, |
| "coverage", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::InnerCoverage, |
| "InnerCoverage", |
| OCC::InnerCoverage, |
| "innerCoverage", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Compute/Mesh/Amplification/Node shader void, h, f, d, i1, |
| // i8, i16, i32, i64, udt, obj , function attribute |
| { |
| OC::ThreadId, |
| "ThreadId", |
| OCC::ThreadId, |
| "threadId", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::GroupId, |
| "GroupId", |
| OCC::GroupId, |
| "groupId", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::ThreadIdInGroup, |
| "ThreadIdInGroup", |
| OCC::ThreadIdInGroup, |
| "threadIdInGroup", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::FlattenedThreadIdInGroup, |
| "FlattenedThreadIdInGroup", |
| OCC::FlattenedThreadIdInGroup, |
| "flattenedThreadIdInGroup", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Geometry shader void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::EmitStream, |
| "EmitStream", |
| OCC::EmitStream, |
| "emitStream", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::CutStream, |
| "CutStream", |
| OCC::CutStream, |
| "cutStream", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::EmitThenCutStream, |
| "EmitThenCutStream", |
| OCC::EmitThenCutStream, |
| "emitThenCutStream", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::GSInstanceID, |
| "GSInstanceID", |
| OCC::GSInstanceID, |
| "gsInstanceID", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Double precision void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::MakeDouble, |
| "MakeDouble", |
| OCC::MakeDouble, |
| "makeDouble", |
| {false, false, false, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::SplitDouble, |
| "SplitDouble", |
| OCC::SplitDouble, |
| "splitDouble", |
| {false, false, false, true, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Domain and hull shader void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::LoadOutputControlPoint, |
| "LoadOutputControlPoint", |
| OCC::LoadOutputControlPoint, |
| "loadOutputControlPoint", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::LoadPatchConstant, |
| "LoadPatchConstant", |
| OCC::LoadPatchConstant, |
| "loadPatchConstant", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Domain shader void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::DomainLocation, |
| "DomainLocation", |
| OCC::DomainLocation, |
| "domainLocation", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Hull shader void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::StorePatchConstant, |
| "StorePatchConstant", |
| OCC::StorePatchConstant, |
| "storePatchConstant", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::OutputControlPointID, |
| "OutputControlPointID", |
| OCC::OutputControlPointID, |
| "outputControlPointID", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Hull, Domain and Geometry shaders void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::PrimitiveID, |
| "PrimitiveID", |
| OCC::PrimitiveID, |
| "primitiveID", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Other void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::CycleCounterLegacy, |
| "CycleCounterLegacy", |
| OCC::CycleCounterLegacy, |
| "cycleCounterLegacy", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Wave void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::WaveIsFirstLane, |
| "WaveIsFirstLane", |
| OCC::WaveIsFirstLane, |
| "waveIsFirstLane", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveGetLaneIndex, |
| "WaveGetLaneIndex", |
| OCC::WaveGetLaneIndex, |
| "waveGetLaneIndex", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::WaveGetLaneCount, |
| "WaveGetLaneCount", |
| OCC::WaveGetLaneCount, |
| "waveGetLaneCount", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::WaveAnyTrue, |
| "WaveAnyTrue", |
| OCC::WaveAnyTrue, |
| "waveAnyTrue", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveAllTrue, |
| "WaveAllTrue", |
| OCC::WaveAllTrue, |
| "waveAllTrue", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveActiveAllEqual, |
| "WaveActiveAllEqual", |
| OCC::WaveActiveAllEqual, |
| "waveActiveAllEqual", |
| {false, true, true, true, true, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveActiveBallot, |
| "WaveActiveBallot", |
| OCC::WaveActiveBallot, |
| "waveActiveBallot", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveReadLaneAt, |
| "WaveReadLaneAt", |
| OCC::WaveReadLaneAt, |
| "waveReadLaneAt", |
| {false, true, true, true, true, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveReadLaneFirst, |
| "WaveReadLaneFirst", |
| OCC::WaveReadLaneFirst, |
| "waveReadLaneFirst", |
| {false, true, true, true, true, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveActiveOp, |
| "WaveActiveOp", |
| OCC::WaveActiveOp, |
| "waveActiveOp", |
| {false, true, true, true, true, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveActiveBit, |
| "WaveActiveBit", |
| OCC::WaveActiveBit, |
| "waveActiveBit", |
| {false, false, false, false, false, true, true, true, true, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WavePrefixOp, |
| "WavePrefixOp", |
| OCC::WavePrefixOp, |
| "wavePrefixOp", |
| {false, true, true, true, false, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| |
| // Quad Wave Ops void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::QuadReadLaneAt, |
| "QuadReadLaneAt", |
| OCC::QuadReadLaneAt, |
| "quadReadLaneAt", |
| {false, true, true, true, true, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::QuadOp, |
| "QuadOp", |
| OCC::QuadOp, |
| "quadOp", |
| {false, true, true, true, false, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| |
| // Bitcasts with different sizes void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::BitcastI16toF16, |
| "BitcastI16toF16", |
| OCC::BitcastI16toF16, |
| "bitcastI16toF16", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::BitcastF16toI16, |
| "BitcastF16toI16", |
| OCC::BitcastF16toI16, |
| "bitcastF16toI16", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::BitcastI32toF32, |
| "BitcastI32toF32", |
| OCC::BitcastI32toF32, |
| "bitcastI32toF32", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::BitcastF32toI32, |
| "BitcastF32toI32", |
| OCC::BitcastF32toI32, |
| "bitcastF32toI32", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::BitcastI64toF64, |
| "BitcastI64toF64", |
| OCC::BitcastI64toF64, |
| "bitcastI64toF64", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::BitcastF64toI64, |
| "BitcastF64toI64", |
| OCC::BitcastF64toI64, |
| "bitcastF64toI64", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Legacy floating-point void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::LegacyF32ToF16, |
| "LegacyF32ToF16", |
| OCC::LegacyF32ToF16, |
| "legacyF32ToF16", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::LegacyF16ToF32, |
| "LegacyF16ToF32", |
| OCC::LegacyF16ToF32, |
| "legacyF16ToF32", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Double precision void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::LegacyDoubleToFloat, |
| "LegacyDoubleToFloat", |
| OCC::LegacyDoubleToFloat, |
| "legacyDoubleToFloat", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::LegacyDoubleToSInt32, |
| "LegacyDoubleToSInt32", |
| OCC::LegacyDoubleToSInt32, |
| "legacyDoubleToSInt32", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::LegacyDoubleToUInt32, |
| "LegacyDoubleToUInt32", |
| OCC::LegacyDoubleToUInt32, |
| "legacyDoubleToUInt32", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Wave void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::WaveAllBitCount, |
| "WaveAllBitCount", |
| OCC::WaveAllOp, |
| "waveAllOp", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WavePrefixBitCount, |
| "WavePrefixBitCount", |
| OCC::WavePrefixOp, |
| "wavePrefixOp", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Pixel shader void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::AttributeAtVertex, |
| "AttributeAtVertex", |
| OCC::AttributeAtVertex, |
| "attributeAtVertex", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Graphics shader void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::ViewID, |
| "ViewID", |
| OCC::ViewID, |
| "viewID", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Resources void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::RawBufferLoad, |
| "RawBufferLoad", |
| OCC::RawBufferLoad, |
| "rawBufferLoad", |
| {false, true, true, true, false, false, true, true, true, false, false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RawBufferStore, |
| "RawBufferStore", |
| OCC::RawBufferStore, |
| "rawBufferStore", |
| {false, true, true, true, false, false, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| |
| // Raytracing object space uint System Values void, h, f, d, i1, |
| // i8, i16, i32, i64, udt, obj , function attribute |
| { |
| OC::InstanceID, |
| "InstanceID", |
| OCC::InstanceID, |
| "instanceID", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::InstanceIndex, |
| "InstanceIndex", |
| OCC::InstanceIndex, |
| "instanceIndex", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Raytracing hit uint System Values void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::HitKind, |
| "HitKind", |
| OCC::HitKind, |
| "hitKind", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Raytracing uint System Values void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::RayFlags, |
| "RayFlags", |
| OCC::RayFlags, |
| "rayFlags", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Ray Dispatch Arguments void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::DispatchRaysIndex, |
| "DispatchRaysIndex", |
| OCC::DispatchRaysIndex, |
| "dispatchRaysIndex", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::DispatchRaysDimensions, |
| "DispatchRaysDimensions", |
| OCC::DispatchRaysDimensions, |
| "dispatchRaysDimensions", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Ray Vectors void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::WorldRayOrigin, |
| "WorldRayOrigin", |
| OCC::WorldRayOrigin, |
| "worldRayOrigin", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::WorldRayDirection, |
| "WorldRayDirection", |
| OCC::WorldRayDirection, |
| "worldRayDirection", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Ray object space Vectors void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::ObjectRayOrigin, |
| "ObjectRayOrigin", |
| OCC::ObjectRayOrigin, |
| "objectRayOrigin", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::ObjectRayDirection, |
| "ObjectRayDirection", |
| OCC::ObjectRayDirection, |
| "objectRayDirection", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Ray Transforms void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::ObjectToWorld, |
| "ObjectToWorld", |
| OCC::ObjectToWorld, |
| "objectToWorld", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::WorldToObject, |
| "WorldToObject", |
| OCC::WorldToObject, |
| "worldToObject", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // RayT void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::RayTMin, |
| "RayTMin", |
| OCC::RayTMin, |
| "rayTMin", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::RayTCurrent, |
| "RayTCurrent", |
| OCC::RayTCurrent, |
| "rayTCurrent", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // AnyHit Terminals void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::IgnoreHit, |
| "IgnoreHit", |
| OCC::IgnoreHit, |
| "ignoreHit", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoReturn, |
| }, |
| { |
| OC::AcceptHitAndEndSearch, |
| "AcceptHitAndEndSearch", |
| OCC::AcceptHitAndEndSearch, |
| "acceptHitAndEndSearch", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoReturn, |
| }, |
| |
| // Indirect Shader Invocation void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::TraceRay, |
| "TraceRay", |
| OCC::TraceRay, |
| "traceRay", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::ReportHit, |
| "ReportHit", |
| OCC::ReportHit, |
| "reportHit", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::CallShader, |
| "CallShader", |
| OCC::CallShader, |
| "callShader", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Library create handle from resource struct (like HL intrinsic) void, h, |
| // f, d, i1, i8, i16, i32, i64, udt, obj , function |
| // attribute |
| { |
| OC::CreateHandleForLib, |
| "CreateHandleForLib", |
| OCC::CreateHandleForLib, |
| "createHandleForLib", |
| {false, false, false, false, false, false, false, false, false, false, |
| true}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Raytracing object space uint System Values void, h, f, d, i1, |
| // i8, i16, i32, i64, udt, obj , function attribute |
| { |
| OC::PrimitiveIndex, |
| "PrimitiveIndex", |
| OCC::PrimitiveIndex, |
| "primitiveIndex", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Dot product with accumulate void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::Dot2AddHalf, |
| "Dot2AddHalf", |
| OCC::Dot2AddHalf, |
| "dot2AddHalf", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Dot4AddI8Packed, |
| "Dot4AddI8Packed", |
| OCC::Dot4AddPacked, |
| "dot4AddPacked", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::Dot4AddU8Packed, |
| "Dot4AddU8Packed", |
| OCC::Dot4AddPacked, |
| "dot4AddPacked", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Wave void, h, f, d, i1, i8, i16, i32, i64, udt, |
| // obj , function attribute |
| { |
| OC::WaveMatch, |
| "WaveMatch", |
| OCC::WaveMatch, |
| "waveMatch", |
| {false, true, true, true, false, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveMultiPrefixOp, |
| "WaveMultiPrefixOp", |
| OCC::WaveMultiPrefixOp, |
| "waveMultiPrefixOp", |
| {false, true, true, true, false, true, true, true, true, false, false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveMultiPrefixBitCount, |
| "WaveMultiPrefixBitCount", |
| OCC::WaveMultiPrefixBitCount, |
| "waveMultiPrefixBitCount", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Mesh shader instructions void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::SetMeshOutputCounts, |
| "SetMeshOutputCounts", |
| OCC::SetMeshOutputCounts, |
| "setMeshOutputCounts", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::EmitIndices, |
| "EmitIndices", |
| OCC::EmitIndices, |
| "emitIndices", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::GetMeshPayload, |
| "GetMeshPayload", |
| OCC::GetMeshPayload, |
| "getMeshPayload", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::StoreVertexOutput, |
| "StoreVertexOutput", |
| OCC::StoreVertexOutput, |
| "storeVertexOutput", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::StorePrimitiveOutput, |
| "StorePrimitiveOutput", |
| OCC::StorePrimitiveOutput, |
| "storePrimitiveOutput", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Amplification shader instructions void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::DispatchMesh, |
| "DispatchMesh", |
| OCC::DispatchMesh, |
| "dispatchMesh", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Sampler Feedback void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::WriteSamplerFeedback, |
| "WriteSamplerFeedback", |
| OCC::WriteSamplerFeedback, |
| "writeSamplerFeedback", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WriteSamplerFeedbackBias, |
| "WriteSamplerFeedbackBias", |
| OCC::WriteSamplerFeedbackBias, |
| "writeSamplerFeedbackBias", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WriteSamplerFeedbackLevel, |
| "WriteSamplerFeedbackLevel", |
| OCC::WriteSamplerFeedbackLevel, |
| "writeSamplerFeedbackLevel", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WriteSamplerFeedbackGrad, |
| "WriteSamplerFeedbackGrad", |
| OCC::WriteSamplerFeedbackGrad, |
| "writeSamplerFeedbackGrad", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Inline Ray Query void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::AllocateRayQuery, |
| "AllocateRayQuery", |
| OCC::AllocateRayQuery, |
| "allocateRayQuery", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_TraceRayInline, |
| "RayQuery_TraceRayInline", |
| OCC::RayQuery_TraceRayInline, |
| "rayQuery_TraceRayInline", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_Proceed, |
| "RayQuery_Proceed", |
| OCC::RayQuery_Proceed, |
| "rayQuery_Proceed", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_Abort, |
| "RayQuery_Abort", |
| OCC::RayQuery_Abort, |
| "rayQuery_Abort", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_CommitNonOpaqueTriangleHit, |
| "RayQuery_CommitNonOpaqueTriangleHit", |
| OCC::RayQuery_CommitNonOpaqueTriangleHit, |
| "rayQuery_CommitNonOpaqueTriangleHit", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_CommitProceduralPrimitiveHit, |
| "RayQuery_CommitProceduralPrimitiveHit", |
| OCC::RayQuery_CommitProceduralPrimitiveHit, |
| "rayQuery_CommitProceduralPrimitiveHit", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::RayQuery_CommittedStatus, |
| "RayQuery_CommittedStatus", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateType, |
| "RayQuery_CandidateType", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateObjectToWorld3x4, |
| "RayQuery_CandidateObjectToWorld3x4", |
| OCC::RayQuery_StateMatrix, |
| "rayQuery_StateMatrix", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateWorldToObject3x4, |
| "RayQuery_CandidateWorldToObject3x4", |
| OCC::RayQuery_StateMatrix, |
| "rayQuery_StateMatrix", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedObjectToWorld3x4, |
| "RayQuery_CommittedObjectToWorld3x4", |
| OCC::RayQuery_StateMatrix, |
| "rayQuery_StateMatrix", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedWorldToObject3x4, |
| "RayQuery_CommittedWorldToObject3x4", |
| OCC::RayQuery_StateMatrix, |
| "rayQuery_StateMatrix", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateProceduralPrimitiveNonOpaque, |
| "RayQuery_CandidateProceduralPrimitiveNonOpaque", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateTriangleFrontFace, |
| "RayQuery_CandidateTriangleFrontFace", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedTriangleFrontFace, |
| "RayQuery_CommittedTriangleFrontFace", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateTriangleBarycentrics, |
| "RayQuery_CandidateTriangleBarycentrics", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedTriangleBarycentrics, |
| "RayQuery_CommittedTriangleBarycentrics", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_RayFlags, |
| "RayQuery_RayFlags", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_WorldRayOrigin, |
| "RayQuery_WorldRayOrigin", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_WorldRayDirection, |
| "RayQuery_WorldRayDirection", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_RayTMin, |
| "RayQuery_RayTMin", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateTriangleRayT, |
| "RayQuery_CandidateTriangleRayT", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedRayT, |
| "RayQuery_CommittedRayT", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateInstanceIndex, |
| "RayQuery_CandidateInstanceIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateInstanceID, |
| "RayQuery_CandidateInstanceID", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateGeometryIndex, |
| "RayQuery_CandidateGeometryIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidatePrimitiveIndex, |
| "RayQuery_CandidatePrimitiveIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateObjectRayOrigin, |
| "RayQuery_CandidateObjectRayOrigin", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CandidateObjectRayDirection, |
| "RayQuery_CandidateObjectRayDirection", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedInstanceIndex, |
| "RayQuery_CommittedInstanceIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedInstanceID, |
| "RayQuery_CommittedInstanceID", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedGeometryIndex, |
| "RayQuery_CommittedGeometryIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedPrimitiveIndex, |
| "RayQuery_CommittedPrimitiveIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedObjectRayOrigin, |
| "RayQuery_CommittedObjectRayOrigin", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedObjectRayDirection, |
| "RayQuery_CommittedObjectRayDirection", |
| OCC::RayQuery_StateVector, |
| "rayQuery_StateVector", |
| {false, false, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Raytracing object space uint System Values, raytracing tier 1.1 void, h, |
| // f, d, i1, i8, i16, i32, i64, udt, obj , function |
| // attribute |
| { |
| OC::GeometryIndex, |
| "GeometryIndex", |
| OCC::GeometryIndex, |
| "geometryIndex", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Inline Ray Query void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::RayQuery_CandidateInstanceContributionToHitGroupIndex, |
| "RayQuery_CandidateInstanceContributionToHitGroupIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::RayQuery_CommittedInstanceContributionToHitGroupIndex, |
| "RayQuery_CommittedInstanceContributionToHitGroupIndex", |
| OCC::RayQuery_StateScalar, |
| "rayQuery_StateScalar", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Get handle from heap void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::AnnotateHandle, |
| "AnnotateHandle", |
| OCC::AnnotateHandle, |
| "annotateHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::CreateHandleFromBinding, |
| "CreateHandleFromBinding", |
| OCC::CreateHandleFromBinding, |
| "createHandleFromBinding", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::CreateHandleFromHeap, |
| "CreateHandleFromHeap", |
| OCC::CreateHandleFromHeap, |
| "createHandleFromHeap", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Unpacking intrinsics void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::Unpack4x8, |
| "Unpack4x8", |
| OCC::Unpack4x8, |
| "unpack4x8", |
| {false, false, false, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Packing intrinsics void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::Pack4x8, |
| "Pack4x8", |
| OCC::Pack4x8, |
| "pack4x8", |
| {false, false, false, false, false, false, true, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Helper Lanes void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::IsHelperLane, |
| "IsHelperLane", |
| OCC::IsHelperLane, |
| "isHelperLane", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Quad Wave Ops void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::QuadVote, |
| "QuadVote", |
| OCC::QuadVote, |
| "quadVote", |
| {false, false, false, false, true, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Resources - gather void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::TextureGatherRaw, |
| "TextureGatherRaw", |
| OCC::TextureGatherRaw, |
| "textureGatherRaw", |
| {false, false, false, false, false, false, true, true, true, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources - sample void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::SampleCmpLevel, |
| "SampleCmpLevel", |
| OCC::SampleCmpLevel, |
| "sampleCmpLevel", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Resources void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::TextureStoreSample, |
| "TextureStoreSample", |
| OCC::TextureStoreSample, |
| "textureStoreSample", |
| {false, true, true, false, false, false, true, true, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // WaveMatrix void, h, f, d, i1, i8, i16, i32, i64, |
| // udt, obj , function attribute |
| { |
| OC::WaveMatrix_Annotate, |
| "WaveMatrix_Annotate", |
| OCC::WaveMatrix_Annotate, |
| "waveMatrix_Annotate", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_Depth, |
| "WaveMatrix_Depth", |
| OCC::WaveMatrix_Depth, |
| "waveMatrix_Depth", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::WaveMatrix_Fill, |
| "WaveMatrix_Fill", |
| OCC::WaveMatrix_Fill, |
| "waveMatrix_Fill", |
| {false, true, true, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_LoadRawBuf, |
| "WaveMatrix_LoadRawBuf", |
| OCC::WaveMatrix_LoadRawBuf, |
| "waveMatrix_LoadRawBuf", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveMatrix_LoadGroupShared, |
| "WaveMatrix_LoadGroupShared", |
| OCC::WaveMatrix_LoadGroupShared, |
| "waveMatrix_LoadGroupShared", |
| {false, true, true, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_StoreRawBuf, |
| "WaveMatrix_StoreRawBuf", |
| OCC::WaveMatrix_StoreRawBuf, |
| "waveMatrix_StoreRawBuf", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::WaveMatrix_StoreGroupShared, |
| "WaveMatrix_StoreGroupShared", |
| OCC::WaveMatrix_StoreGroupShared, |
| "waveMatrix_StoreGroupShared", |
| {false, true, true, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_Multiply, |
| "WaveMatrix_Multiply", |
| OCC::WaveMatrix_Multiply, |
| "waveMatrix_Multiply", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_MultiplyAccumulate, |
| "WaveMatrix_MultiplyAccumulate", |
| OCC::WaveMatrix_Multiply, |
| "waveMatrix_Multiply", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_ScalarOp, |
| "WaveMatrix_ScalarOp", |
| OCC::WaveMatrix_ScalarOp, |
| "waveMatrix_ScalarOp", |
| {false, true, true, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_SumAccumulate, |
| "WaveMatrix_SumAccumulate", |
| OCC::WaveMatrix_Accumulate, |
| "waveMatrix_Accumulate", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| { |
| OC::WaveMatrix_Add, |
| "WaveMatrix_Add", |
| OCC::WaveMatrix_Accumulate, |
| "waveMatrix_Accumulate", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ArgMemOnly, |
| }, |
| |
| // Create/Annotate Node Handles void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::AllocateNodeOutputRecords, |
| "AllocateNodeOutputRecords", |
| OCC::AllocateNodeOutputRecords, |
| "allocateNodeOutputRecords", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Get Pointer to Node Record in Address Space 6 void, h, f, d, |
| // i1, i8, i16, i32, i64, udt, obj , function attribute |
| { |
| OC::GetNodeRecordPtr, |
| "GetNodeRecordPtr", |
| OCC::GetNodeRecordPtr, |
| "getNodeRecordPtr", |
| {false, false, false, false, false, false, false, false, false, true, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Work Graph intrinsics void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::IncrementOutputCount, |
| "IncrementOutputCount", |
| OCC::IncrementOutputCount, |
| "incrementOutputCount", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::OutputComplete, |
| "OutputComplete", |
| OCC::OutputComplete, |
| "outputComplete", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| { |
| OC::GetInputRecordCount, |
| "GetInputRecordCount", |
| OCC::GetInputRecordCount, |
| "getInputRecordCount", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::FinishedCrossGroupSharing, |
| "FinishedCrossGroupSharing", |
| OCC::FinishedCrossGroupSharing, |
| "finishedCrossGroupSharing", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::None, |
| }, |
| |
| // Synchronization void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::BarrierByMemoryType, |
| "BarrierByMemoryType", |
| OCC::BarrierByMemoryType, |
| "barrierByMemoryType", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoDuplicate, |
| }, |
| { |
| OC::BarrierByMemoryHandle, |
| "BarrierByMemoryHandle", |
| OCC::BarrierByMemoryHandle, |
| "barrierByMemoryHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoDuplicate, |
| }, |
| { |
| OC::BarrierByNodeRecordHandle, |
| "BarrierByNodeRecordHandle", |
| OCC::BarrierByNodeRecordHandle, |
| "barrierByNodeRecordHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::NoDuplicate, |
| }, |
| |
| // Create/Annotate Node Handles void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::CreateNodeOutputHandle, |
| "CreateNodeOutputHandle", |
| OCC::createNodeOutputHandle, |
| "createNodeOutputHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::IndexNodeHandle, |
| "IndexNodeHandle", |
| OCC::IndexNodeHandle, |
| "indexNodeHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::AnnotateNodeHandle, |
| "AnnotateNodeHandle", |
| OCC::AnnotateNodeHandle, |
| "annotateNodeHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::CreateNodeInputRecordHandle, |
| "CreateNodeInputRecordHandle", |
| OCC::CreateNodeInputRecordHandle, |
| "createNodeInputRecordHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::AnnotateNodeRecordHandle, |
| "AnnotateNodeRecordHandle", |
| OCC::AnnotateNodeRecordHandle, |
| "annotateNodeRecordHandle", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| |
| // Work Graph intrinsics void, h, f, d, i1, i8, i16, |
| // i32, i64, udt, obj , function attribute |
| { |
| OC::NodeOutputIsValid, |
| "NodeOutputIsValid", |
| OCC::NodeOutputIsValid, |
| "nodeOutputIsValid", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::GetRemainingRecursionLevels, |
| "GetRemainingRecursionLevels", |
| OCC::GetRemainingRecursionLevels, |
| "getRemainingRecursionLevels", |
| {true, false, false, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Comparison Samples void, h, f, d, i1, i8, i16, i32, |
| // i64, udt, obj , function attribute |
| { |
| OC::SampleCmpGrad, |
| "SampleCmpGrad", |
| OCC::SampleCmpGrad, |
| "sampleCmpGrad", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| { |
| OC::SampleCmpBias, |
| "SampleCmpBias", |
| OCC::SampleCmpBias, |
| "sampleCmpBias", |
| {false, true, true, false, false, false, false, false, false, false, |
| false}, |
| Attribute::ReadOnly, |
| }, |
| |
| // Extended Command Information void, h, f, d, i1, i8, |
| // i16, i32, i64, udt, obj , function attribute |
| { |
| OC::StartVertexLocation, |
| "StartVertexLocation", |
| OCC::StartVertexLocation, |
| "startVertexLocation", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| { |
| OC::StartInstanceLocation, |
| "StartInstanceLocation", |
| OCC::StartInstanceLocation, |
| "startInstanceLocation", |
| {false, false, false, false, false, false, false, true, false, false, |
| false}, |
| Attribute::ReadNone, |
| }, |
| }; |
| // OPCODE-OLOADS:END |
| |
| const char *OP::m_OverloadTypeName[kNumTypeOverloads] = { |
| "void", "f16", "f32", "f64", "i1", "i8", |
| "i16", "i32", "i64", "udt", "obj", // These should not be used |
| }; |
| |
| const char *OP::m_NamePrefix = "dx.op."; |
| const char *OP::m_TypePrefix = "dx.types."; |
| const char *OP::m_MatrixTypePrefix = "class.matrix."; // Allowed in library |
| |
| // Keep sync with DXIL::AtomicBinOpCode |
| static const char *AtomicBinOpCodeName[] = { |
| "AtomicAdd", "AtomicAnd", "AtomicOr", "AtomicXor", "AtomicIMin", |
| "AtomicIMax", "AtomicUMin", "AtomicUMax", "AtomicExchange", |
| "AtomicInvalid" // Must be last. |
| }; |
| |
| unsigned OP::GetTypeSlot(Type *pType) { |
| Type::TypeID T = pType->getTypeID(); |
| switch (T) { |
| case Type::VoidTyID: |
| return 0; |
| case Type::HalfTyID: |
| return 1; |
| case Type::FloatTyID: |
| return 2; |
| case Type::DoubleTyID: |
| return 3; |
| case Type::IntegerTyID: { |
| IntegerType *pIT = dyn_cast<IntegerType>(pType); |
| unsigned Bits = pIT->getBitWidth(); |
| switch (Bits) { |
| case 1: |
| return 4; |
| case 8: |
| return 5; |
| case 16: |
| return 6; |
| case 32: |
| return 7; |
| case 64: |
| return 8; |
| } |
| llvm_unreachable("Invalid Bits size"); |
| } |
| case Type::PointerTyID: { |
| pType = cast<PointerType>(pType)->getElementType(); |
| if (pType->isStructTy()) |
| return kUserDefineTypeSlot; |
| DXASSERT(!pType->isPointerTy(), "pointer-to-pointer type unsupported"); |
| return GetTypeSlot(pType); |
| } |
| case Type::StructTyID: |
| return kObjectTypeSlot; |
| default: |
| break; |
| } |
| return UINT_MAX; |
| } |
| |
| const char *OP::GetOverloadTypeName(unsigned TypeSlot) { |
| DXASSERT(TypeSlot < kUserDefineTypeSlot, "otherwise caller passed OOB index"); |
| return m_OverloadTypeName[TypeSlot]; |
| } |
| |
| llvm::StringRef OP::GetTypeName(Type *Ty, std::string &str) { |
| unsigned TypeSlot = OP::GetTypeSlot(Ty); |
| if (TypeSlot < kUserDefineTypeSlot) { |
| return GetOverloadTypeName(TypeSlot); |
| } else if (TypeSlot == kUserDefineTypeSlot) { |
| if (Ty->isPointerTy()) |
| Ty = Ty->getPointerElementType(); |
| StructType *ST = cast<StructType>(Ty); |
| return ST->getStructName(); |
| } else if (TypeSlot == kObjectTypeSlot) { |
| StructType *ST = cast<StructType>(Ty); |
| return ST->getStructName(); |
| } else { |
| raw_string_ostream os(str); |
| Ty->print(os); |
| os.flush(); |
| return str; |
| } |
| } |
| |
| llvm::StringRef OP::ConstructOverloadName(Type *Ty, DXIL::OpCode opCode, |
| std::string &funcNameStorage) { |
| if (Ty == Type::getVoidTy(Ty->getContext())) { |
| funcNameStorage = |
| (Twine(OP::m_NamePrefix) + Twine(GetOpCodeClassName(opCode))).str(); |
| } else { |
| funcNameStorage = |
| (Twine(OP::m_NamePrefix) + Twine(GetOpCodeClassName(opCode)) + "." + |
| GetTypeName(Ty, funcNameStorage)) |
| .str(); |
| } |
| return funcNameStorage; |
| } |
| |
| const char *OP::GetOpCodeName(OpCode opCode) { |
| return m_OpCodeProps[(unsigned)opCode].pOpCodeName; |
| } |
| |
| const char *OP::GetAtomicOpName(DXIL::AtomicBinOpCode OpCode) { |
| unsigned opcode = static_cast<unsigned>(OpCode); |
| DXASSERT_LOCALVAR( |
| opcode, opcode < static_cast<unsigned>(DXIL::AtomicBinOpCode::Invalid), |
| "otherwise caller passed OOB index"); |
| return AtomicBinOpCodeName[static_cast<unsigned>(OpCode)]; |
| } |
| |
| OP::OpCodeClass OP::GetOpCodeClass(OpCode opCode) { |
| return m_OpCodeProps[(unsigned)opCode].opCodeClass; |
| } |
| |
| const char *OP::GetOpCodeClassName(OpCode opCode) { |
| return m_OpCodeProps[(unsigned)opCode].pOpCodeClassName; |
| } |
| |
| llvm::Attribute::AttrKind OP::GetMemAccessAttr(OpCode opCode) { |
| return m_OpCodeProps[(unsigned)opCode].FuncAttr; |
| } |
| |
| bool OP::IsOverloadLegal(OpCode opCode, Type *pType) { |
| if (!pType) |
| return false; |
| if (opCode == OpCode::NumOpCodes) |
| return false; |
| unsigned TypeSlot = GetTypeSlot(pType); |
| return TypeSlot != UINT_MAX && |
| m_OpCodeProps[(unsigned)opCode].bAllowOverload[TypeSlot]; |
| } |
| |
| bool OP::CheckOpCodeTable() { |
| for (unsigned i = 0; i < (unsigned)OpCode::NumOpCodes; i++) { |
| if ((unsigned)m_OpCodeProps[i].opCode != i) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool OP::IsDxilOpFuncName(StringRef name) { |
| return name.startswith(OP::m_NamePrefix); |
| } |
| |
| bool OP::IsDxilOpFunc(const llvm::Function *F) { |
| // Test for null to allow IsDxilOpFunc(Call.getCalledFunc()) to be resilient |
| // to indirect calls |
| if (F == nullptr || !F->hasName()) |
| return false; |
| return IsDxilOpFuncName(F->getName()); |
| } |
| |
| bool OP::IsDxilOpTypeName(StringRef name) { |
| return name.startswith(m_TypePrefix) || name.startswith(m_MatrixTypePrefix); |
| } |
| |
| bool OP::IsDxilOpType(llvm::StructType *ST) { |
| if (!ST->hasName()) |
| return false; |
| StringRef Name = ST->getName(); |
| return IsDxilOpTypeName(Name); |
| } |
| |
| bool OP::IsDupDxilOpType(llvm::StructType *ST) { |
| if (!ST->hasName()) |
| return false; |
| StringRef Name = ST->getName(); |
| if (!IsDxilOpTypeName(Name)) |
| return false; |
| size_t DotPos = Name.rfind('.'); |
| if (DotPos == 0 || DotPos == StringRef::npos || Name.back() == '.' || |
| !isdigit(static_cast<unsigned char>(Name[DotPos + 1]))) |
| return false; |
| return true; |
| } |
| |
| StructType *OP::GetOriginalDxilOpType(llvm::StructType *ST, llvm::Module &M) { |
| DXASSERT(IsDupDxilOpType(ST), "else should not call GetOriginalDxilOpType"); |
| StringRef Name = ST->getName(); |
| size_t DotPos = Name.rfind('.'); |
| StructType *OriginalST = M.getTypeByName(Name.substr(0, DotPos)); |
| DXASSERT(OriginalST, "else name collison without original type"); |
| DXASSERT(ST->isLayoutIdentical(OriginalST), |
| "else invalid layout for dxil types"); |
| return OriginalST; |
| } |
| |
| bool OP::IsDxilOpFuncCallInst(const llvm::Instruction *I) { |
| const CallInst *CI = dyn_cast<CallInst>(I); |
| if (CI == nullptr) |
| return false; |
| return IsDxilOpFunc(CI->getCalledFunction()); |
| } |
| |
| bool OP::IsDxilOpFuncCallInst(const llvm::Instruction *I, OpCode opcode) { |
| if (!IsDxilOpFuncCallInst(I)) |
| return false; |
| return (unsigned)getOpCode(I) == (unsigned)opcode; |
| } |
| |
| OP::OpCode OP::getOpCode(const llvm::Instruction *I) { |
| auto *OpConst = llvm::dyn_cast<llvm::ConstantInt>(I->getOperand(0)); |
| if (!OpConst) |
| return OpCode::NumOpCodes; |
| uint64_t OpCodeVal = OpConst->getZExtValue(); |
| if (OpCodeVal >= static_cast<uint64_t>(OP::OpCode::NumOpCodes)) |
| return OP::OpCode::NumOpCodes; |
| return static_cast<OP::OpCode>(OpCodeVal); |
| } |
| |
| OP::OpCode OP::GetDxilOpFuncCallInst(const llvm::Instruction *I) { |
| DXASSERT(IsDxilOpFuncCallInst(I), |
| "else caller didn't call IsDxilOpFuncCallInst to check"); |
| return getOpCode(I); |
| } |
| |
| bool OP::IsDxilOpWave(OpCode C) { |
| unsigned op = (unsigned)C; |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-WAVE')>hctdb_instrhelp.get_instrs_pred("op", "is_wave")</py>*/ |
| // clang-format on |
| // OPCODE-WAVE:BEGIN |
| // Instructions: WaveIsFirstLane=110, WaveGetLaneIndex=111, |
| // WaveGetLaneCount=112, WaveAnyTrue=113, WaveAllTrue=114, |
| // WaveActiveAllEqual=115, WaveActiveBallot=116, WaveReadLaneAt=117, |
| // WaveReadLaneFirst=118, WaveActiveOp=119, WaveActiveBit=120, |
| // WavePrefixOp=121, QuadReadLaneAt=122, QuadOp=123, WaveAllBitCount=135, |
| // WavePrefixBitCount=136, WaveMatch=165, WaveMultiPrefixOp=166, |
| // WaveMultiPrefixBitCount=167, QuadVote=222, WaveMatrix_Annotate=226, |
| // WaveMatrix_Depth=227, WaveMatrix_Fill=228, WaveMatrix_LoadRawBuf=229, |
| // WaveMatrix_LoadGroupShared=230, WaveMatrix_StoreRawBuf=231, |
| // WaveMatrix_StoreGroupShared=232, WaveMatrix_Multiply=233, |
| // WaveMatrix_MultiplyAccumulate=234, WaveMatrix_ScalarOp=235, |
| // WaveMatrix_SumAccumulate=236, WaveMatrix_Add=237 |
| return (110 <= op && op <= 123) || (135 <= op && op <= 136) || |
| (165 <= op && op <= 167) || op == 222 || (226 <= op && op <= 237); |
| // OPCODE-WAVE:END |
| } |
| |
| bool OP::IsDxilOpGradient(OpCode C) { |
| unsigned op = (unsigned)C; |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-GRADIENT')>hctdb_instrhelp.get_instrs_pred("op", "is_gradient")</py>*/ |
| // clang-format on |
| // OPCODE-GRADIENT:BEGIN |
| // Instructions: Sample=60, SampleBias=61, SampleCmp=64, CalculateLOD=81, |
| // DerivCoarseX=83, DerivCoarseY=84, DerivFineX=85, DerivFineY=86, |
| // WriteSamplerFeedback=174, WriteSamplerFeedbackBias=175, SampleCmpBias=255 |
| return (60 <= op && op <= 61) || op == 64 || op == 81 || |
| (83 <= op && op <= 86) || (174 <= op && op <= 175) || op == 255; |
| // OPCODE-GRADIENT:END |
| } |
| |
| bool OP::IsDxilOpFeedback(OpCode C) { |
| unsigned op = (unsigned)C; |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-FEEDBACK')>hctdb_instrhelp.get_instrs_pred("op", "is_feedback")</py>*/ |
| // clang-format on |
| // OPCODE-FEEDBACK:BEGIN |
| // Instructions: WriteSamplerFeedback=174, WriteSamplerFeedbackBias=175, |
| // WriteSamplerFeedbackLevel=176, WriteSamplerFeedbackGrad=177 |
| return (174 <= op && op <= 177); |
| // OPCODE-FEEDBACK:END |
| } |
| |
| bool OP::IsDxilOpBarrier(OpCode C) { |
| unsigned op = (unsigned)C; |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-BARRIER')>hctdb_instrhelp.get_instrs_pred("op", "is_barrier")</py>*/ |
| // clang-format on |
| // OPCODE-BARRIER:BEGIN |
| // Instructions: Barrier=80, BarrierByMemoryType=244, |
| // BarrierByMemoryHandle=245, BarrierByNodeRecordHandle=246 |
| return op == 80 || (244 <= op && op <= 246); |
| // OPCODE-BARRIER:END |
| } |
| |
| static unsigned MaskMemoryTypeFlagsIfAllowed(unsigned memoryTypeFlags, |
| unsigned allowedMask) { |
| // If the memory type is AllMemory, masking inapplicable flags is allowed. |
| if (memoryTypeFlags != (unsigned)DXIL::MemoryTypeFlag::AllMemory) |
| return memoryTypeFlags; |
| return memoryTypeFlags & allowedMask; |
| } |
| |
| bool OP::BarrierRequiresGroup(const llvm::CallInst *CI) { |
| OpCode opcode = OP::GetDxilOpFuncCallInst(CI); |
| switch (opcode) { |
| case OpCode::Barrier: { |
| DxilInst_Barrier barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_barrierMode())) { |
| unsigned mode = barrier.get_barrierMode_val(); |
| return (mode != (unsigned)DXIL::BarrierMode::UAVFenceGlobal); |
| } |
| return false; |
| } |
| case OpCode::BarrierByMemoryType: { |
| DxilInst_BarrierByMemoryType barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_MemoryTypeFlags())) { |
| unsigned memoryTypeFlags = barrier.get_MemoryTypeFlags_val(); |
| memoryTypeFlags = MaskMemoryTypeFlagsIfAllowed( |
| memoryTypeFlags, ~(unsigned)DXIL::MemoryTypeFlag::GroupFlags); |
| if (memoryTypeFlags & (unsigned)DXIL::MemoryTypeFlag::GroupFlags) |
| return true; |
| } |
| } |
| LLVM_FALLTHROUGH; |
| case OpCode::BarrierByMemoryHandle: |
| case OpCode::BarrierByNodeRecordHandle: { |
| // BarrierByMemoryType, BarrierByMemoryHandle, and BarrierByNodeRecordHandle |
| // all have semanticFlags as the second operand. |
| DxilInst_BarrierByMemoryType barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_SemanticFlags())) { |
| unsigned semanticFlags = barrier.get_SemanticFlags_val(); |
| if (semanticFlags & (unsigned)DXIL::BarrierSemanticFlag::GroupFlags) |
| return true; |
| } |
| return false; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| bool OP::BarrierRequiresNode(const llvm::CallInst *CI) { |
| OpCode opcode = OP::GetDxilOpFuncCallInst(CI); |
| switch (opcode) { |
| case OpCode::BarrierByNodeRecordHandle: |
| return true; |
| case OpCode::BarrierByMemoryType: { |
| DxilInst_BarrierByMemoryType barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_MemoryTypeFlags())) { |
| unsigned memoryTypeFlags = barrier.get_MemoryTypeFlags_val(); |
| // Mask off node flags, if allowed. |
| memoryTypeFlags = MaskMemoryTypeFlagsIfAllowed( |
| memoryTypeFlags, ~(unsigned)DXIL::MemoryTypeFlag::NodeFlags); |
| return (memoryTypeFlags & (unsigned)DXIL::MemoryTypeFlag::NodeFlags) != 0; |
| } |
| return false; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| DXIL::BarrierMode OP::TranslateToBarrierMode(const llvm::CallInst *CI) { |
| OpCode opcode = OP::GetDxilOpFuncCallInst(CI); |
| switch (opcode) { |
| case OpCode::Barrier: { |
| DxilInst_Barrier barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_barrierMode())) { |
| unsigned mode = barrier.get_barrierMode_val(); |
| return static_cast<DXIL::BarrierMode>(mode); |
| } |
| return DXIL::BarrierMode::Invalid; |
| } |
| case OpCode::BarrierByMemoryType: { |
| unsigned memoryTypeFlags = 0; |
| unsigned semanticFlags = 0; |
| DxilInst_BarrierByMemoryType barrier(const_cast<CallInst *>(CI)); |
| if (isa<ConstantInt>(barrier.get_MemoryTypeFlags())) { |
| memoryTypeFlags = barrier.get_MemoryTypeFlags_val(); |
| } |
| if (isa<ConstantInt>(barrier.get_SemanticFlags())) { |
| semanticFlags = barrier.get_SemanticFlags_val(); |
| } |
| |
| // Mask to legacy flags, if allowed. |
| memoryTypeFlags = MaskMemoryTypeFlagsIfAllowed( |
| memoryTypeFlags, (unsigned)DXIL::MemoryTypeFlag::LegacyFlags); |
| if (memoryTypeFlags & ~(unsigned)DXIL::MemoryTypeFlag::LegacyFlags) |
| return DXIL::BarrierMode::Invalid; |
| |
| unsigned mode = 0; |
| if (memoryTypeFlags & (unsigned)DXIL::MemoryTypeFlag::GroupSharedMemory) |
| mode |= (unsigned)DXIL::BarrierMode::TGSMFence; |
| if (memoryTypeFlags & (unsigned)DXIL::MemoryTypeFlag::UavMemory) { |
| if (semanticFlags & (unsigned)DXIL::BarrierSemanticFlag::DeviceScope) { |
| mode |= (unsigned)DXIL::BarrierMode::UAVFenceGlobal; |
| } else if (semanticFlags & |
| (unsigned)DXIL::BarrierSemanticFlag::GroupScope) { |
| mode |= (unsigned)DXIL::BarrierMode::UAVFenceThreadGroup; |
| } |
| } |
| if (semanticFlags & (unsigned)DXIL::BarrierSemanticFlag::GroupSync) |
| mode |= (unsigned)DXIL::BarrierMode::SyncThreadGroup; |
| return static_cast<DXIL::BarrierMode>(mode); |
| } |
| default: |
| return DXIL::BarrierMode::Invalid; |
| } |
| } |
| |
| #define SFLAG(stage) ((unsigned)1 << (unsigned)DXIL::ShaderKind::stage) |
| void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation, |
| unsigned &major, unsigned &minor, |
| unsigned &mask) { |
| unsigned op = (unsigned)C; |
| // Default is 6.0, all stages |
| major = 6; |
| minor = 0; |
| mask = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Invalid) - 1; |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-SMMASK')>hctdb_instrhelp.get_min_sm_and_mask_text()</py>*/ |
| // clang-format on |
| // OPCODE-SMMASK:BEGIN |
| // Instructions: ThreadId=93, GroupId=94, ThreadIdInGroup=95, |
| // FlattenedThreadIdInGroup=96 |
| if ((93 <= op && op <= 96)) { |
| mask = SFLAG(Compute) | SFLAG(Mesh) | SFLAG(Amplification) | SFLAG(Node); |
| return; |
| } |
| // Instructions: DomainLocation=105 |
| if (op == 105) { |
| mask = SFLAG(Domain); |
| return; |
| } |
| // Instructions: LoadOutputControlPoint=103, LoadPatchConstant=104 |
| if ((103 <= op && op <= 104)) { |
| mask = SFLAG(Domain) | SFLAG(Hull); |
| return; |
| } |
| // Instructions: EmitStream=97, CutStream=98, EmitThenCutStream=99, |
| // GSInstanceID=100 |
| if ((97 <= op && op <= 100)) { |
| mask = SFLAG(Geometry); |
| return; |
| } |
| // Instructions: PrimitiveID=108 |
| if (op == 108) { |
| mask = SFLAG(Geometry) | SFLAG(Domain) | SFLAG(Hull); |
| return; |
| } |
| // Instructions: StorePatchConstant=106, OutputControlPointID=107 |
| if ((106 <= op && op <= 107)) { |
| mask = SFLAG(Hull); |
| return; |
| } |
| // Instructions: QuadReadLaneAt=122, QuadOp=123 |
| if ((122 <= op && op <= 123)) { |
| mask = SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) | |
| SFLAG(Mesh) | SFLAG(Pixel) | SFLAG(Node); |
| return; |
| } |
| // Instructions: WaveIsFirstLane=110, WaveGetLaneIndex=111, |
| // WaveGetLaneCount=112, WaveAnyTrue=113, WaveAllTrue=114, |
| // WaveActiveAllEqual=115, WaveActiveBallot=116, WaveReadLaneAt=117, |
| // WaveReadLaneFirst=118, WaveActiveOp=119, WaveActiveBit=120, |
| // WavePrefixOp=121, WaveAllBitCount=135, WavePrefixBitCount=136 |
| if ((110 <= op && op <= 121) || (135 <= op && op <= 136)) { |
| mask = SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) | |
| SFLAG(Mesh) | SFLAG(Pixel) | SFLAG(Vertex) | SFLAG(Hull) | |
| SFLAG(Domain) | SFLAG(Geometry) | SFLAG(RayGeneration) | |
| SFLAG(Intersection) | SFLAG(AnyHit) | SFLAG(ClosestHit) | |
| SFLAG(Miss) | SFLAG(Callable) | SFLAG(Node); |
| return; |
| } |
| // Instructions: Sample=60, SampleBias=61, SampleCmp=64, CalculateLOD=81, |
| // DerivCoarseX=83, DerivCoarseY=84, DerivFineX=85, DerivFineY=86 |
| if ((60 <= op && op <= 61) || op == 64 || op == 81 || |
| (83 <= op && op <= 86)) { |
| mask = SFLAG(Library) | SFLAG(Pixel) | SFLAG(Compute) | |
| SFLAG(Amplification) | SFLAG(Mesh) | SFLAG(Node); |
| return; |
| } |
| // Instructions: RenderTargetGetSamplePosition=76, |
| // RenderTargetGetSampleCount=77, Discard=82, EvalSnapped=87, |
| // EvalSampleIndex=88, EvalCentroid=89, SampleIndex=90, Coverage=91, |
| // InnerCoverage=92 |
| if ((76 <= op && op <= 77) || op == 82 || (87 <= op && op <= 92)) { |
| mask = SFLAG(Pixel); |
| return; |
| } |
| // Instructions: AttributeAtVertex=137 |
| if (op == 137) { |
| major = 6; |
| minor = 1; |
| mask = SFLAG(Pixel); |
| return; |
| } |
| // Instructions: ViewID=138 |
| if (op == 138) { |
| major = 6; |
| minor = 1; |
| mask = SFLAG(Vertex) | SFLAG(Hull) | SFLAG(Domain) | SFLAG(Geometry) | |
| SFLAG(Pixel) | SFLAG(Mesh); |
| return; |
| } |
| // Instructions: RawBufferLoad=139, RawBufferStore=140 |
| if ((139 <= op && op <= 140)) { |
| if (bWithTranslation) { |
| major = 6; |
| minor = 0; |
| } else { |
| major = 6; |
| minor = 2; |
| } |
| return; |
| } |
| // Instructions: IgnoreHit=155, AcceptHitAndEndSearch=156 |
| if ((155 <= op && op <= 156)) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(AnyHit); |
| return; |
| } |
| // Instructions: CallShader=159 |
| if (op == 159) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(Library) | SFLAG(ClosestHit) | SFLAG(RayGeneration) | |
| SFLAG(Miss) | SFLAG(Callable); |
| return; |
| } |
| // Instructions: ReportHit=158 |
| if (op == 158) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(Library) | SFLAG(Intersection); |
| return; |
| } |
| // Instructions: InstanceID=141, InstanceIndex=142, HitKind=143, |
| // ObjectRayOrigin=149, ObjectRayDirection=150, ObjectToWorld=151, |
| // WorldToObject=152, PrimitiveIndex=161 |
| if ((141 <= op && op <= 143) || (149 <= op && op <= 152) || op == 161) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(Library) | SFLAG(Intersection) | SFLAG(AnyHit) | |
| SFLAG(ClosestHit); |
| return; |
| } |
| // Instructions: RayFlags=144, WorldRayOrigin=147, WorldRayDirection=148, |
| // RayTMin=153, RayTCurrent=154 |
| if (op == 144 || (147 <= op && op <= 148) || (153 <= op && op <= 154)) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(Library) | SFLAG(Intersection) | SFLAG(AnyHit) | |
| SFLAG(ClosestHit) | SFLAG(Miss); |
| return; |
| } |
| // Instructions: TraceRay=157 |
| if (op == 157) { |
| major = 6; |
| minor = 3; |
| mask = |
| SFLAG(Library) | SFLAG(RayGeneration) | SFLAG(ClosestHit) | SFLAG(Miss); |
| return; |
| } |
| // Instructions: DispatchRaysIndex=145, DispatchRaysDimensions=146 |
| if ((145 <= op && op <= 146)) { |
| major = 6; |
| minor = 3; |
| mask = SFLAG(Library) | SFLAG(RayGeneration) | SFLAG(Intersection) | |
| SFLAG(AnyHit) | SFLAG(ClosestHit) | SFLAG(Miss) | SFLAG(Callable); |
| return; |
| } |
| // Instructions: CreateHandleForLib=160 |
| if (op == 160) { |
| if (bWithTranslation) { |
| major = 6; |
| minor = 0; |
| } else { |
| major = 6; |
| minor = 3; |
| } |
| return; |
| } |
| // Instructions: Dot2AddHalf=162, Dot4AddI8Packed=163, Dot4AddU8Packed=164 |
| if ((162 <= op && op <= 164)) { |
| major = 6; |
| minor = 4; |
| return; |
| } |
| // Instructions: WriteSamplerFeedbackLevel=176, WriteSamplerFeedbackGrad=177, |
| // AllocateRayQuery=178, RayQuery_TraceRayInline=179, RayQuery_Proceed=180, |
| // RayQuery_Abort=181, RayQuery_CommitNonOpaqueTriangleHit=182, |
| // RayQuery_CommitProceduralPrimitiveHit=183, RayQuery_CommittedStatus=184, |
| // RayQuery_CandidateType=185, RayQuery_CandidateObjectToWorld3x4=186, |
| // RayQuery_CandidateWorldToObject3x4=187, |
| // RayQuery_CommittedObjectToWorld3x4=188, |
| // RayQuery_CommittedWorldToObject3x4=189, |
| // RayQuery_CandidateProceduralPrimitiveNonOpaque=190, |
| // RayQuery_CandidateTriangleFrontFace=191, |
| // RayQuery_CommittedTriangleFrontFace=192, |
| // RayQuery_CandidateTriangleBarycentrics=193, |
| // RayQuery_CommittedTriangleBarycentrics=194, RayQuery_RayFlags=195, |
| // RayQuery_WorldRayOrigin=196, RayQuery_WorldRayDirection=197, |
| // RayQuery_RayTMin=198, RayQuery_CandidateTriangleRayT=199, |
| // RayQuery_CommittedRayT=200, RayQuery_CandidateInstanceIndex=201, |
| // RayQuery_CandidateInstanceID=202, RayQuery_CandidateGeometryIndex=203, |
| // RayQuery_CandidatePrimitiveIndex=204, |
| // RayQuery_CandidateObjectRayOrigin=205, |
| // RayQuery_CandidateObjectRayDirection=206, |
| // RayQuery_CommittedInstanceIndex=207, RayQuery_CommittedInstanceID=208, |
| // RayQuery_CommittedGeometryIndex=209, RayQuery_CommittedPrimitiveIndex=210, |
| // RayQuery_CommittedObjectRayOrigin=211, |
| // RayQuery_CommittedObjectRayDirection=212, |
| // RayQuery_CandidateInstanceContributionToHitGroupIndex=214, |
| // RayQuery_CommittedInstanceContributionToHitGroupIndex=215 |
| if ((176 <= op && op <= 212) || (214 <= op && op <= 215)) { |
| major = 6; |
| minor = 5; |
| return; |
| } |
| // Instructions: DispatchMesh=173 |
| if (op == 173) { |
| major = 6; |
| minor = 5; |
| mask = SFLAG(Amplification); |
| return; |
| } |
| // Instructions: WaveMatch=165, WaveMultiPrefixOp=166, |
| // WaveMultiPrefixBitCount=167 |
| if ((165 <= op && op <= 167)) { |
| major = 6; |
| minor = 5; |
| mask = SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) | |
| SFLAG(Mesh) | SFLAG(Pixel) | SFLAG(Vertex) | SFLAG(Hull) | |
| SFLAG(Domain) | SFLAG(Geometry) | SFLAG(RayGeneration) | |
| SFLAG(Intersection) | SFLAG(AnyHit) | SFLAG(ClosestHit) | |
| SFLAG(Miss) | SFLAG(Callable) | SFLAG(Node); |
| return; |
| } |
| // Instructions: GeometryIndex=213 |
| if (op == 213) { |
| major = 6; |
| minor = 5; |
| mask = SFLAG(Library) | SFLAG(Intersection) | SFLAG(AnyHit) | |
| SFLAG(ClosestHit); |
| return; |
| } |
| // Instructions: WriteSamplerFeedback=174, WriteSamplerFeedbackBias=175 |
| if ((174 <= op && op <= 175)) { |
| major = 6; |
| minor = 5; |
| mask = SFLAG(Library) | SFLAG(Pixel); |
| return; |
| } |
| // Instructions: SetMeshOutputCounts=168, EmitIndices=169, GetMeshPayload=170, |
| // StoreVertexOutput=171, StorePrimitiveOutput=172 |
| if ((168 <= op && op <= 172)) { |
| major = 6; |
| minor = 5; |
| mask = SFLAG(Mesh); |
| return; |
| } |
| // Instructions: CreateHandleFromHeap=218, Unpack4x8=219, Pack4x8=220, |
| // IsHelperLane=221 |
| if ((218 <= op && op <= 221)) { |
| major = 6; |
| minor = 6; |
| return; |
| } |
| // Instructions: AnnotateHandle=216, CreateHandleFromBinding=217 |
| if ((216 <= op && op <= 217)) { |
| if (bWithTranslation) { |
| major = 6; |
| minor = 0; |
| } else { |
| major = 6; |
| minor = 6; |
| } |
| return; |
| } |
| // Instructions: TextureGatherRaw=223, SampleCmpLevel=224, |
| // TextureStoreSample=225 |
| if ((223 <= op && op <= 225)) { |
| major = 6; |
| minor = 7; |
| return; |
| } |
| // Instructions: QuadVote=222 |
| if (op == 222) { |
| if (bWithTranslation) { |
| major = 6; |
| minor = 0; |
| } else { |
| major = 6; |
| minor = 7; |
| } |
| mask = SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) | |
| SFLAG(Mesh) | SFLAG(Pixel) | SFLAG(Node); |
| return; |
| } |
| // Instructions: BarrierByMemoryHandle=245, SampleCmpGrad=254 |
| if (op == 245 || op == 254) { |
| major = 6; |
| minor = 8; |
| return; |
| } |
| // Instructions: SampleCmpBias=255 |
| if (op == 255) { |
| major = 6; |
| minor = 8; |
| mask = SFLAG(Library) | SFLAG(Pixel) | SFLAG(Compute) | |
| SFLAG(Amplification) | SFLAG(Mesh) | SFLAG(Node); |
| return; |
| } |
| // Instructions: AllocateNodeOutputRecords=238, GetNodeRecordPtr=239, |
| // IncrementOutputCount=240, OutputComplete=241, GetInputRecordCount=242, |
| // FinishedCrossGroupSharing=243, BarrierByNodeRecordHandle=246, |
| // CreateNodeOutputHandle=247, IndexNodeHandle=248, AnnotateNodeHandle=249, |
| // CreateNodeInputRecordHandle=250, AnnotateNodeRecordHandle=251, |
| // NodeOutputIsValid=252, GetRemainingRecursionLevels=253 |
| if ((238 <= op && op <= 243) || (246 <= op && op <= 253)) { |
| major = 6; |
| minor = 8; |
| mask = SFLAG(Node); |
| return; |
| } |
| // Instructions: StartVertexLocation=256, StartInstanceLocation=257 |
| if ((256 <= op && op <= 257)) { |
| major = 6; |
| minor = 8; |
| mask = SFLAG(Vertex); |
| return; |
| } |
| // Instructions: BarrierByMemoryType=244 |
| if (op == 244) { |
| if (bWithTranslation) { |
| major = 6; |
| minor = 0; |
| } else { |
| major = 6; |
| minor = 8; |
| } |
| return; |
| } |
| // Instructions: WaveMatrix_Annotate=226, WaveMatrix_Depth=227, |
| // WaveMatrix_Fill=228, WaveMatrix_LoadRawBuf=229, |
| // WaveMatrix_LoadGroupShared=230, WaveMatrix_StoreRawBuf=231, |
| // WaveMatrix_StoreGroupShared=232, WaveMatrix_Multiply=233, |
| // WaveMatrix_MultiplyAccumulate=234, WaveMatrix_ScalarOp=235, |
| // WaveMatrix_SumAccumulate=236, WaveMatrix_Add=237 |
| if ((226 <= op && op <= 237)) { |
| major = 6; |
| minor = 9; |
| mask = SFLAG(Library) | SFLAG(Compute); |
| return; |
| } |
| // OPCODE-SMMASK:END |
| } |
| |
| void OP::GetMinShaderModelAndMask(const llvm::CallInst *CI, |
| bool bWithTranslation, unsigned valMajor, |
| unsigned valMinor, unsigned &major, |
| unsigned &minor, unsigned &mask) { |
| OpCode opcode = OP::GetDxilOpFuncCallInst(CI); |
| GetMinShaderModelAndMask(opcode, bWithTranslation, major, minor, mask); |
| |
| unsigned op = (unsigned)opcode; |
| if (DXIL::CompareVersions(valMajor, valMinor, 1, 8) < 0) { |
| // In prior validator versions, these ops excluded CS/MS/AS from mask. |
| // In 1.8, we now have a mechanism to indicate derivative use with an |
| // independent feature bit. This allows us to fix up the min shader model |
| // once all bits have been marged from the call graph to the entry point. |
| // Instructions: Sample=60, SampleBias=61, SampleCmp=64, CalculateLOD=81, |
| // DerivCoarseX=83, DerivCoarseY=84, DerivFineX=85, DerivFineY=86 |
| if ((60 <= op && op <= 61) || op == 64 || op == 81 || |
| (83 <= op && op <= 86)) { |
| mask &= ~(SFLAG(Compute) | SFLAG(Amplification) | SFLAG(Mesh)); |
| return; |
| } |
| } |
| |
| if (DXIL::CompareVersions(valMajor, valMinor, 1, 5) < 0) { |
| // validator 1.4 didn't exclude wave ops in mask |
| if (IsDxilOpWave(opcode)) |
| mask = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Mesh) - 1; |
| // validator 1.4 didn't have any additional rules applied: |
| return; |
| } |
| |
| // Additional rules are applied manually here. |
| |
| // Barrier requiring node or group limit shader kinds. |
| if (IsDxilOpBarrier(opcode)) { |
| // If BarrierByMemoryType, check if translatable, or set min to 6.8. |
| if (bWithTranslation && opcode == DXIL::OpCode::BarrierByMemoryType) { |
| if (TranslateToBarrierMode(CI) == DXIL::BarrierMode::Invalid) { |
| major = 6; |
| minor = 8; |
| } |
| } |
| if (BarrierRequiresNode(CI)) { |
| mask &= SFLAG(Library) | SFLAG(Node); |
| return; |
| } else if (BarrierRequiresGroup(CI)) { |
| mask &= SFLAG(Library) | SFLAG(Compute) | SFLAG(Amplification) | |
| SFLAG(Mesh) | SFLAG(Node); |
| return; |
| } |
| } |
| |
| // 64-bit integer atomic ops require 6.6 |
| else if (opcode == DXIL::OpCode::AtomicBinOp || |
| opcode == DXIL::OpCode::AtomicCompareExchange) { |
| Type *pOverloadType = GetOverloadType(opcode, CI->getCalledFunction()); |
| if (pOverloadType->isIntegerTy(64)) { |
| major = 6; |
| minor = 6; |
| } |
| } |
| |
| // AnnotateHandle and CreateHandleFromBinding can be translated down to |
| // SM 6.0, but this wasn't set properly in validator version 6.6, so make it |
| // match when using that version. |
| else if (bWithTranslation && |
| DXIL::CompareVersions(valMajor, valMinor, 1, 6) == 0 && |
| (opcode == DXIL::OpCode::AnnotateHandle || |
| opcode == DXIL::OpCode::CreateHandleFromBinding)) { |
| major = 6; |
| minor = 6; |
| } |
| } |
| #undef SFLAG |
| |
| static Type *GetOrCreateStructType(LLVMContext &Ctx, ArrayRef<Type *> types, |
| StringRef Name, Module *pModule) { |
| if (StructType *ST = pModule->getTypeByName(Name)) { |
| // TODO: validate the exist type match types if needed. |
| return ST; |
| } else |
| return StructType::create(Ctx, types, Name); |
| } |
| |
| //------------------------------------------------------------------------------ |
| // |
| // OP methods. |
| // |
| OP::OP(LLVMContext &Ctx, Module *pModule) |
| : m_Ctx(Ctx), m_pModule(pModule), |
| m_LowPrecisionMode(DXIL::LowPrecisionMode::Undefined) { |
| memset(m_pResRetType, 0, sizeof(m_pResRetType)); |
| memset(m_pCBufferRetType, 0, sizeof(m_pCBufferRetType)); |
| memset(m_OpCodeClassCache, 0, sizeof(m_OpCodeClassCache)); |
| static_assert(_countof(OP::m_OpCodeProps) == (size_t)OP::OpCode::NumOpCodes, |
| "forgot to update OP::m_OpCodeProps"); |
| |
| m_pHandleType = GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx), |
| "dx.types.Handle", pModule); |
| m_pNodeHandleType = GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx), |
| "dx.types.NodeHandle", pModule); |
| m_pNodeRecordHandleType = GetOrCreateStructType( |
| m_Ctx, Type::getInt8PtrTy(m_Ctx), "dx.types.NodeRecordHandle", pModule); |
| m_pResourcePropertiesType = GetOrCreateStructType( |
| m_Ctx, {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx)}, |
| "dx.types.ResourceProperties", pModule); |
| m_pNodePropertiesType = GetOrCreateStructType( |
| m_Ctx, {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx)}, |
| "dx.types.NodeInfo", pModule); |
| m_pNodeRecordPropertiesType = GetOrCreateStructType( |
| m_Ctx, {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx)}, |
| "dx.types.NodeRecordInfo", pModule); |
| |
| m_pResourceBindingType = |
| GetOrCreateStructType(m_Ctx, |
| {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx), Type::getInt8Ty(m_Ctx)}, |
| "dx.types.ResBind", pModule); |
| |
| Type *DimsType[4] = {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx)}; |
| m_pDimensionsType = |
| GetOrCreateStructType(m_Ctx, DimsType, "dx.types.Dimensions", pModule); |
| |
| Type *SamplePosType[2] = {Type::getFloatTy(m_Ctx), Type::getFloatTy(m_Ctx)}; |
| m_pSamplePosType = GetOrCreateStructType(m_Ctx, SamplePosType, |
| "dx.types.SamplePos", pModule); |
| |
| Type *I32cTypes[2] = {Type::getInt32Ty(m_Ctx), Type::getInt1Ty(m_Ctx)}; |
| m_pBinaryWithCarryType = |
| GetOrCreateStructType(m_Ctx, I32cTypes, "dx.types.i32c", pModule); |
| |
| Type *TwoI32Types[2] = {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx)}; |
| m_pBinaryWithTwoOutputsType = |
| GetOrCreateStructType(m_Ctx, TwoI32Types, "dx.types.twoi32", pModule); |
| |
| Type *SplitDoubleTypes[2] = {Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx)}; // Lo, Hi. |
| m_pSplitDoubleType = GetOrCreateStructType(m_Ctx, SplitDoubleTypes, |
| "dx.types.splitdouble", pModule); |
| |
| Type *FourI32Types[4] = {Type::getInt32Ty(m_Ctx), Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx)}; // HiHi, HiLo, LoHi, LoLo |
| m_pFourI32Type = |
| GetOrCreateStructType(m_Ctx, FourI32Types, "dx.types.fouri32", pModule); |
| |
| Type *FourI16Types[4] = {Type::getInt16Ty(m_Ctx), Type::getInt16Ty(m_Ctx), |
| Type::getInt16Ty(m_Ctx), |
| Type::getInt16Ty(m_Ctx)}; // HiHi, HiLo, LoHi, LoLo |
| m_pFourI16Type = |
| GetOrCreateStructType(m_Ctx, FourI16Types, "dx.types.fouri16", pModule); |
| |
| Type *WaveMatInfoTypes[4] = {Type::getInt8Ty(m_Ctx), Type::getInt8Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx), |
| Type::getInt32Ty(m_Ctx)}; |
| m_pWaveMatInfoType = cast<StructType>(GetOrCreateStructType( |
| m_Ctx, WaveMatInfoTypes, "dx.types.waveMatProps", pModule)); |
| m_pWaveMatPtrType = |
| PointerType::get(GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx), |
| "dx.types.waveMatrix", pModule), |
| 0); |
| } |
| |
| void OP::RefreshCache() { |
| for (Function &F : m_pModule->functions()) { |
| if (OP::IsDxilOpFunc(&F) && !F.user_empty()) { |
| CallInst *CI = cast<CallInst>(*F.user_begin()); |
| OpCode OpCode = OP::GetDxilOpFuncCallInst(CI); |
| Type *pOverloadType = OP::GetOverloadType(OpCode, &F); |
| GetOpFunc(OpCode, pOverloadType); |
| } |
| } |
| } |
| |
| void OP::FixOverloadNames() { |
| // When merging code from multiple sources, such as with linking, |
| // type names that collide, but don't have the same type will be |
| // automically renamed with .0+ name disambiguation. However, |
| // DXIL intrinsic overloads will not be renamed to disambiguate them, |
| // since they exist in separate modules at the time. |
| // This leads to name collisions between different types when linking. |
| // Do this after loading into a shared context, and before copying |
| // code into a common module, to prevent this problem. |
| for (Function &F : m_pModule->functions()) { |
| if (F.isDeclaration() && OP::IsDxilOpFunc(&F) && !F.user_empty()) { |
| CallInst *CI = cast<CallInst>(*F.user_begin()); |
| DXIL::OpCode opCode = OP::GetDxilOpFuncCallInst(CI); |
| llvm::Type *Ty = OP::GetOverloadType(opCode, &F); |
| if (!OP::IsOverloadLegal(opCode, Ty)) |
| continue; |
| if (!isa<StructType>(Ty) && !isa<PointerType>(Ty)) |
| continue; |
| |
| std::string funcName; |
| if (OP::ConstructOverloadName(Ty, opCode, funcName) |
| .compare(F.getName()) != 0) |
| F.setName(funcName); |
| } |
| } |
| } |
| |
| void OP::UpdateCache(OpCodeClass opClass, Type *Ty, llvm::Function *F) { |
| m_OpCodeClassCache[(unsigned)opClass].pOverloads[Ty] = F; |
| m_FunctionToOpClass[F] = opClass; |
| } |
| |
| Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) { |
| if (opCode == OpCode::NumOpCodes) |
| return nullptr; |
| if (!IsOverloadLegal(opCode, pOverloadType)) |
| return nullptr; |
| |
| OpCodeClass opClass = m_OpCodeProps[(unsigned)opCode].opCodeClass; |
| Function *&F = |
| m_OpCodeClassCache[(unsigned)opClass].pOverloads[pOverloadType]; |
| if (F != nullptr) { |
| UpdateCache(opClass, pOverloadType, F); |
| return F; |
| } |
| |
| vector<Type *> ArgTypes; // RetType is ArgTypes[0] |
| Type *pETy = pOverloadType; |
| Type *pRes = GetHandleType(); |
| Type *pNodeHandle = GetNodeHandleType(); |
| Type *pNodeRecordHandle = GetNodeRecordHandleType(); |
| Type *pDim = GetDimensionsType(); |
| Type *pPos = GetSamplePosType(); |
| Type *pV = Type::getVoidTy(m_Ctx); |
| Type *pI1 = Type::getInt1Ty(m_Ctx); |
| Type *pI8 = Type::getInt8Ty(m_Ctx); |
| Type *pI16 = Type::getInt16Ty(m_Ctx); |
| Type *pI32 = Type::getInt32Ty(m_Ctx); |
| Type *pPI32 = Type::getInt32PtrTy(m_Ctx); |
| (void)(pPI32); // Currently unused. |
| Type *pI64 = Type::getInt64Ty(m_Ctx); |
| (void)(pI64); // Currently unused. |
| Type *pF16 = Type::getHalfTy(m_Ctx); |
| Type *pF32 = Type::getFloatTy(m_Ctx); |
| Type *pPF32 = Type::getFloatPtrTy(m_Ctx); |
| Type *pI32C = GetBinaryWithCarryType(); |
| Type *p2I32 = GetBinaryWithTwoOutputsType(); |
| Type *pF64 = Type::getDoubleTy(m_Ctx); |
| Type *pSDT = GetSplitDoubleType(); // Split double type. |
| Type *p4I32 = GetFourI32Type(); // 4 i32s in a struct. |
| |
| Type *udt = pOverloadType; |
| Type *obj = pOverloadType; |
| Type *resProperty = GetResourcePropertiesType(); |
| Type *resBind = GetResourceBindingType(); |
| Type *nodeProperty = GetNodePropertiesType(); |
| Type *nodeRecordProperty = GetNodeRecordPropertiesType(); |
| |
| Type *pWaveMatProps = GetWaveMatrixPropertiesType(); |
| Type *pWaveMatPtr = GetWaveMatPtrType(); |
| Type *pGSEltPtrTy = |
| pETy->isVoidTy() ? nullptr : pETy->getPointerTo(DXIL::kTGSMAddrSpace); |
| |
| #define A(_x) ArgTypes.emplace_back(_x) |
| #define RRT(_y) A(GetResRetType(_y)) |
| #define CBRT(_y) A(GetCBufferRetType(_y)) |
| #define VEC4(_y) A(GetVectorType(4, _y)) |
| |
| /* <py::lines('OPCODE-OLOAD-FUNCS')>hctdb_instrhelp.get_oloads_funcs()</py>*/ |
| switch (opCode) { // return opCode |
| // OPCODE-OLOAD-FUNCS:BEGIN |
| // Temporary, indexable, input, output registers |
| case OpCode::TempRegLoad: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::TempRegStore: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::MinPrecXRegLoad: |
| A(pETy); |
| A(pI32); |
| A(pPF32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::MinPrecXRegStore: |
| A(pV); |
| A(pI32); |
| A(pPF32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| break; |
| case OpCode::LoadInput: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| break; |
| case OpCode::StoreOutput: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| break; |
| |
| // Unary float |
| case OpCode::FAbs: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Saturate: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::IsNaN: |
| A(pI1); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::IsInf: |
| A(pI1); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::IsFinite: |
| A(pI1); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::IsNormal: |
| A(pI1); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Cos: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Sin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Tan: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Acos: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Asin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Atan: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Hcos: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Hsin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Htan: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Exp: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Frc: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Log: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Sqrt: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Rsqrt: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Unary float - rounding |
| case OpCode::Round_ne: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Round_ni: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Round_pi: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Round_z: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Unary int |
| case OpCode::Bfrev: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::Countbits: |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::FirstbitLo: |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Unary uint |
| case OpCode::FirstbitHi: |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Unary int |
| case OpCode::FirstbitSHi: |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Binary float |
| case OpCode::FMax: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::FMin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Binary int |
| case OpCode::IMax: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::IMin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Binary uint |
| case OpCode::UMax: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::UMin: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Binary int with two outputs |
| case OpCode::IMul: |
| A(p2I32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Binary uint with two outputs |
| case OpCode::UMul: |
| A(p2I32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::UDiv: |
| A(p2I32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Binary uint with carry or borrow |
| case OpCode::UAddc: |
| A(pI32C); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::USubb: |
| A(pI32C); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Tertiary float |
| case OpCode::FMad: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::Fma: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Tertiary int |
| case OpCode::IMad: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Tertiary uint |
| case OpCode::UMad: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Tertiary int |
| case OpCode::Msad: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::Ibfe: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Tertiary uint |
| case OpCode::Ubfe: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Quaternary |
| case OpCode::Bfi: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Dot |
| case OpCode::Dot2: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::Dot3: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::Dot4: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Resources |
| case OpCode::CreateHandle: |
| A(pRes); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::CBufferLoad: |
| A(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::CBufferLoadLegacy: |
| CBRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| break; |
| |
| // Resources - sample |
| case OpCode::Sample: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| case OpCode::SampleBias: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::SampleLevel: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| case OpCode::SampleGrad: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::SampleCmp: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::SampleCmpLevelZero: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| |
| // Resources |
| case OpCode::TextureLoad: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::TextureStore: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pI8); |
| break; |
| case OpCode::BufferLoad: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::BufferStore: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pI8); |
| break; |
| case OpCode::BufferUpdateCounter: |
| A(pI32); |
| A(pI32); |
| A(pRes); |
| A(pI8); |
| break; |
| case OpCode::CheckAccessFullyMapped: |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::GetDimensions: |
| A(pDim); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| break; |
| |
| // Resources - gather |
| case OpCode::TextureGather: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::TextureGatherCmp: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| |
| // Resources - sample |
| case OpCode::Texture2DMSGetSamplePosition: |
| A(pPos); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| break; |
| case OpCode::RenderTargetGetSamplePosition: |
| A(pPos); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RenderTargetGetSampleCount: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Synchronization |
| case OpCode::AtomicBinOp: |
| A(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::AtomicCompareExchange: |
| A(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| break; |
| case OpCode::Barrier: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Derivatives |
| case OpCode::CalculateLOD: |
| A(pF32); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI1); |
| break; |
| |
| // Pixel shader |
| case OpCode::Discard: |
| A(pV); |
| A(pI32); |
| A(pI1); |
| break; |
| |
| // Derivatives |
| case OpCode::DerivCoarseX: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::DerivCoarseY: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::DerivFineX: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::DerivFineY: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Pixel shader |
| case OpCode::EvalSnapped: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::EvalSampleIndex: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| break; |
| case OpCode::EvalCentroid: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::SampleIndex: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::Coverage: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::InnerCoverage: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Compute/Mesh/Amplification/Node shader |
| case OpCode::ThreadId: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::GroupId: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::ThreadIdInGroup: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::FlattenedThreadIdInGroup: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Geometry shader |
| case OpCode::EmitStream: |
| A(pV); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::CutStream: |
| A(pV); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::EmitThenCutStream: |
| A(pV); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::GSInstanceID: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Double precision |
| case OpCode::MakeDouble: |
| A(pF64); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::SplitDouble: |
| A(pSDT); |
| A(pI32); |
| A(pF64); |
| break; |
| |
| // Domain and hull shader |
| case OpCode::LoadOutputControlPoint: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| break; |
| case OpCode::LoadPatchConstant: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Domain shader |
| case OpCode::DomainLocation: |
| A(pF32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Hull shader |
| case OpCode::StorePatchConstant: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| break; |
| case OpCode::OutputControlPointID: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Hull, Domain and Geometry shaders |
| case OpCode::PrimitiveID: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Other |
| case OpCode::CycleCounterLegacy: |
| A(p2I32); |
| A(pI32); |
| break; |
| |
| // Wave |
| case OpCode::WaveIsFirstLane: |
| A(pI1); |
| A(pI32); |
| break; |
| case OpCode::WaveGetLaneIndex: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::WaveGetLaneCount: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::WaveAnyTrue: |
| A(pI1); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WaveAllTrue: |
| A(pI1); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WaveActiveAllEqual: |
| A(pI1); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::WaveActiveBallot: |
| A(p4I32); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WaveReadLaneAt: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI32); |
| break; |
| case OpCode::WaveReadLaneFirst: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::WaveActiveOp: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI8); |
| A(pI8); |
| break; |
| case OpCode::WaveActiveBit: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI8); |
| break; |
| case OpCode::WavePrefixOp: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI8); |
| A(pI8); |
| break; |
| |
| // Quad Wave Ops |
| case OpCode::QuadReadLaneAt: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI32); |
| break; |
| case OpCode::QuadOp: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI8); |
| break; |
| |
| // Bitcasts with different sizes |
| case OpCode::BitcastI16toF16: |
| A(pF16); |
| A(pI32); |
| A(pI16); |
| break; |
| case OpCode::BitcastF16toI16: |
| A(pI16); |
| A(pI32); |
| A(pF16); |
| break; |
| case OpCode::BitcastI32toF32: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::BitcastF32toI32: |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| case OpCode::BitcastI64toF64: |
| A(pF64); |
| A(pI32); |
| A(pI64); |
| break; |
| case OpCode::BitcastF64toI64: |
| A(pI64); |
| A(pI32); |
| A(pF64); |
| break; |
| |
| // Legacy floating-point |
| case OpCode::LegacyF32ToF16: |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| case OpCode::LegacyF16ToF32: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Double precision |
| case OpCode::LegacyDoubleToFloat: |
| A(pF32); |
| A(pI32); |
| A(pF64); |
| break; |
| case OpCode::LegacyDoubleToSInt32: |
| A(pI32); |
| A(pI32); |
| A(pF64); |
| break; |
| case OpCode::LegacyDoubleToUInt32: |
| A(pI32); |
| A(pI32); |
| A(pF64); |
| break; |
| |
| // Wave |
| case OpCode::WaveAllBitCount: |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WavePrefixBitCount: |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| break; |
| |
| // Pixel shader |
| case OpCode::AttributeAtVertex: |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI8); |
| break; |
| |
| // Graphics shader |
| case OpCode::ViewID: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Resources |
| case OpCode::RawBufferLoad: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| break; |
| case OpCode::RawBufferStore: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pI8); |
| A(pI32); |
| break; |
| |
| // Raytracing object space uint System Values |
| case OpCode::InstanceID: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::InstanceIndex: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Raytracing hit uint System Values |
| case OpCode::HitKind: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Raytracing uint System Values |
| case OpCode::RayFlags: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Ray Dispatch Arguments |
| case OpCode::DispatchRaysIndex: |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::DispatchRaysDimensions: |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Ray Vectors |
| case OpCode::WorldRayOrigin: |
| A(pF32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::WorldRayDirection: |
| A(pF32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Ray object space Vectors |
| case OpCode::ObjectRayOrigin: |
| A(pF32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::ObjectRayDirection: |
| A(pF32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Ray Transforms |
| case OpCode::ObjectToWorld: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::WorldToObject: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // RayT |
| case OpCode::RayTMin: |
| A(pF32); |
| A(pI32); |
| break; |
| case OpCode::RayTCurrent: |
| A(pF32); |
| A(pI32); |
| break; |
| |
| // AnyHit Terminals |
| case OpCode::IgnoreHit: |
| A(pV); |
| A(pI32); |
| break; |
| case OpCode::AcceptHitAndEndSearch: |
| A(pV); |
| A(pI32); |
| break; |
| |
| // Indirect Shader Invocation |
| case OpCode::TraceRay: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(udt); |
| break; |
| case OpCode::ReportHit: |
| A(pI1); |
| A(pI32); |
| A(pF32); |
| A(pI32); |
| A(udt); |
| break; |
| case OpCode::CallShader: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(udt); |
| break; |
| |
| // Library create handle from resource struct (like HL intrinsic) |
| case OpCode::CreateHandleForLib: |
| A(pRes); |
| A(pI32); |
| A(obj); |
| break; |
| |
| // Raytracing object space uint System Values |
| case OpCode::PrimitiveIndex: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Dot product with accumulate |
| case OpCode::Dot2AddHalf: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pF16); |
| A(pF16); |
| A(pF16); |
| A(pF16); |
| break; |
| case OpCode::Dot4AddI8Packed: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::Dot4AddU8Packed: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Wave |
| case OpCode::WaveMatch: |
| A(p4I32); |
| A(pI32); |
| A(pETy); |
| break; |
| case OpCode::WaveMultiPrefixOp: |
| A(pETy); |
| A(pI32); |
| A(pETy); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI8); |
| break; |
| case OpCode::WaveMultiPrefixBitCount: |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Mesh shader instructions |
| case OpCode::SetMeshOutputCounts: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::EmitIndices: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::GetMeshPayload: |
| A(pETy); |
| A(pI32); |
| break; |
| case OpCode::StoreVertexOutput: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| A(pI32); |
| break; |
| case OpCode::StorePrimitiveOutput: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| A(pI32); |
| break; |
| |
| // Amplification shader instructions |
| case OpCode::DispatchMesh: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| break; |
| |
| // Sampler Feedback |
| case OpCode::WriteSamplerFeedback: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::WriteSamplerFeedbackBias: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::WriteSamplerFeedbackLevel: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::WriteSamplerFeedbackGrad: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| |
| // Inline Ray Query |
| case OpCode::AllocateRayQuery: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_TraceRayInline: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::RayQuery_Proceed: |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_Abort: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommitNonOpaqueTriangleHit: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommitProceduralPrimitiveHit: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| break; |
| case OpCode::RayQuery_CommittedStatus: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateType: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateObjectToWorld3x4: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CandidateWorldToObject3x4: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CommittedObjectToWorld3x4: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CommittedWorldToObject3x4: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CandidateProceduralPrimitiveNonOpaque: |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateTriangleFrontFace: |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedTriangleFrontFace: |
| A(pI1); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateTriangleBarycentrics: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CommittedTriangleBarycentrics: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_RayFlags: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_WorldRayOrigin: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_WorldRayDirection: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_RayTMin: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateTriangleRayT: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedRayT: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateInstanceIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateInstanceID: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateGeometryIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidatePrimitiveIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CandidateObjectRayOrigin: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CandidateObjectRayDirection: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CommittedInstanceIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedInstanceID: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedGeometryIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedPrimitiveIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedObjectRayOrigin: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| case OpCode::RayQuery_CommittedObjectRayDirection: |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| break; |
| |
| // Raytracing object space uint System Values, raytracing tier 1.1 |
| case OpCode::GeometryIndex: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Inline Ray Query |
| case OpCode::RayQuery_CandidateInstanceContributionToHitGroupIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::RayQuery_CommittedInstanceContributionToHitGroupIndex: |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Get handle from heap |
| case OpCode::AnnotateHandle: |
| A(pRes); |
| A(pI32); |
| A(pRes); |
| A(resProperty); |
| break; |
| case OpCode::CreateHandleFromBinding: |
| A(pRes); |
| A(pI32); |
| A(resBind); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::CreateHandleFromHeap: |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| A(pI1); |
| break; |
| |
| // Unpacking intrinsics |
| case OpCode::Unpack4x8: |
| VEC4(pETy); |
| A(pI32); |
| A(pI8); |
| A(pI32); |
| break; |
| |
| // Packing intrinsics |
| case OpCode::Pack4x8: |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| break; |
| |
| // Helper Lanes |
| case OpCode::IsHelperLane: |
| A(pI1); |
| A(pI32); |
| break; |
| |
| // Quad Wave Ops |
| case OpCode::QuadVote: |
| A(pI1); |
| A(pI32); |
| A(pI1); |
| A(pI8); |
| break; |
| |
| // Resources - gather |
| case OpCode::TextureGatherRaw: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Resources - sample |
| case OpCode::SampleCmpLevel: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| break; |
| |
| // Resources |
| case OpCode::TextureStoreSample: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pETy); |
| A(pI8); |
| A(pI32); |
| break; |
| |
| // WaveMatrix |
| case OpCode::WaveMatrix_Annotate: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pWaveMatProps); |
| break; |
| case OpCode::WaveMatrix_Depth: |
| A(pI32); |
| A(pI32); |
| A(pWaveMatProps); |
| break; |
| case OpCode::WaveMatrix_Fill: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pETy); |
| break; |
| case OpCode::WaveMatrix_LoadRawBuf: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI1); |
| break; |
| case OpCode::WaveMatrix_LoadGroupShared: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pGSEltPtrTy); |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WaveMatrix_StoreRawBuf: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pRes); |
| A(pI32); |
| A(pI32); |
| A(pI8); |
| A(pI1); |
| break; |
| case OpCode::WaveMatrix_StoreGroupShared: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pGSEltPtrTy); |
| A(pI32); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::WaveMatrix_Multiply: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| break; |
| case OpCode::WaveMatrix_MultiplyAccumulate: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| break; |
| case OpCode::WaveMatrix_ScalarOp: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pI8); |
| A(pETy); |
| break; |
| case OpCode::WaveMatrix_SumAccumulate: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| break; |
| case OpCode::WaveMatrix_Add: |
| A(pV); |
| A(pI32); |
| A(pWaveMatPtr); |
| A(pWaveMatPtr); |
| break; |
| |
| // Create/Annotate Node Handles |
| case OpCode::AllocateNodeOutputRecords: |
| A(pNodeRecordHandle); |
| A(pI32); |
| A(pNodeHandle); |
| A(pI32); |
| A(pI1); |
| break; |
| |
| // Get Pointer to Node Record in Address Space 6 |
| case OpCode::GetNodeRecordPtr: |
| A(pETy); |
| A(pI32); |
| A(pNodeRecordHandle); |
| A(pI32); |
| break; |
| |
| // Work Graph intrinsics |
| case OpCode::IncrementOutputCount: |
| A(pV); |
| A(pI32); |
| A(pNodeHandle); |
| A(pI32); |
| A(pI1); |
| break; |
| case OpCode::OutputComplete: |
| A(pV); |
| A(pI32); |
| A(pNodeRecordHandle); |
| break; |
| case OpCode::GetInputRecordCount: |
| A(pI32); |
| A(pI32); |
| A(pNodeRecordHandle); |
| break; |
| case OpCode::FinishedCrossGroupSharing: |
| A(pI1); |
| A(pI32); |
| A(pNodeRecordHandle); |
| break; |
| |
| // Synchronization |
| case OpCode::BarrierByMemoryType: |
| A(pV); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::BarrierByMemoryHandle: |
| A(pV); |
| A(pI32); |
| A(pRes); |
| A(pI32); |
| break; |
| case OpCode::BarrierByNodeRecordHandle: |
| A(pV); |
| A(pI32); |
| A(pNodeRecordHandle); |
| A(pI32); |
| break; |
| |
| // Create/Annotate Node Handles |
| case OpCode::CreateNodeOutputHandle: |
| A(pNodeHandle); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::IndexNodeHandle: |
| A(pNodeHandle); |
| A(pI32); |
| A(pNodeHandle); |
| A(pI32); |
| break; |
| case OpCode::AnnotateNodeHandle: |
| A(pNodeHandle); |
| A(pI32); |
| A(pNodeHandle); |
| A(nodeProperty); |
| break; |
| case OpCode::CreateNodeInputRecordHandle: |
| A(pNodeRecordHandle); |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::AnnotateNodeRecordHandle: |
| A(pNodeRecordHandle); |
| A(pI32); |
| A(pNodeRecordHandle); |
| A(nodeRecordProperty); |
| break; |
| |
| // Work Graph intrinsics |
| case OpCode::NodeOutputIsValid: |
| A(pI1); |
| A(pI32); |
| A(pNodeHandle); |
| break; |
| case OpCode::GetRemainingRecursionLevels: |
| A(pI32); |
| A(pI32); |
| break; |
| |
| // Comparison Samples |
| case OpCode::SampleCmpGrad: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| case OpCode::SampleCmpBias: |
| RRT(pETy); |
| A(pI32); |
| A(pRes); |
| A(pRes); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| A(pI32); |
| A(pI32); |
| A(pI32); |
| A(pF32); |
| A(pF32); |
| A(pF32); |
| break; |
| |
| // Extended Command Information |
| case OpCode::StartVertexLocation: |
| A(pI32); |
| A(pI32); |
| break; |
| case OpCode::StartInstanceLocation: |
| A(pI32); |
| A(pI32); |
| break; |
| // OPCODE-OLOAD-FUNCS:END |
| default: |
| DXASSERT(false, "otherwise unhandled case"); |
| break; |
| } |
| #undef RRT |
| #undef A |
| |
| FunctionType *pFT; |
| DXASSERT(ArgTypes.size() > 1, "otherwise forgot to initialize arguments"); |
| pFT = FunctionType::get( |
| ArgTypes[0], ArrayRef<Type *>(&ArgTypes[1], ArgTypes.size() - 1), false); |
| |
| std::string funcName; |
| ConstructOverloadName(pOverloadType, opCode, funcName); |
| |
| // Try to find existing function with the same name in the module. |
| // This needs to happen after the switch statement that constructs arguments |
| // and return values to ensure that ResRetType is constructed in the |
| // RefreshCache case. |
| if (Function *existF = m_pModule->getFunction(funcName)) { |
| if (existF->getFunctionType() != pFT) |
| return nullptr; |
| F = existF; |
| UpdateCache(opClass, pOverloadType, F); |
| return F; |
| } |
| |
| F = cast<Function>(m_pModule->getOrInsertFunction(funcName, pFT)); |
| |
| UpdateCache(opClass, pOverloadType, F); |
| F->setCallingConv(CallingConv::C); |
| F->addFnAttr(Attribute::NoUnwind); |
| if (m_OpCodeProps[(unsigned)opCode].FuncAttr != Attribute::None) |
| F->addFnAttr(m_OpCodeProps[(unsigned)opCode].FuncAttr); |
| |
| return F; |
| } |
| |
| const SmallMapVector<llvm::Type *, llvm::Function *, 8> & |
| OP::GetOpFuncList(OpCode opCode) const { |
| return m_OpCodeClassCache[(unsigned)m_OpCodeProps[(unsigned)opCode] |
| .opCodeClass] |
| .pOverloads; |
| } |
| |
| bool OP::IsDxilOpUsed(OpCode opcode) const { |
| auto &FnList = GetOpFuncList(opcode); |
| for (auto &it : FnList) { |
| llvm::Function *F = it.second; |
| if (!F) { |
| continue; |
| } |
| if (!F->user_empty()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void OP::RemoveFunction(Function *F) { |
| if (OP::IsDxilOpFunc(F)) { |
| OpCodeClass opClass = m_FunctionToOpClass[F]; |
| for (auto it : m_OpCodeClassCache[(unsigned)opClass].pOverloads) { |
| if (it.second == F) { |
| m_OpCodeClassCache[(unsigned)opClass].pOverloads.erase(it.first); |
| m_FunctionToOpClass.erase(F); |
| break; |
| } |
| } |
| } |
| } |
| |
| bool OP::GetOpCodeClass(const Function *F, OP::OpCodeClass &opClass) { |
| auto iter = m_FunctionToOpClass.find(F); |
| if (iter == m_FunctionToOpClass.end()) { |
| // When no user, cannot get opcode. |
| DXASSERT(F->user_empty() || !IsDxilOpFunc(F), |
| "dxil function without an opcode class mapping?"); |
| opClass = OP::OpCodeClass::NumOpClasses; |
| return false; |
| } |
| opClass = iter->second; |
| return true; |
| } |
| |
| bool OP::UseMinPrecision() { |
| return m_LowPrecisionMode == DXIL::LowPrecisionMode::UseMinPrecision; |
| } |
| |
| void OP::InitWithMinPrecision(bool bMinPrecision) { |
| DXIL::LowPrecisionMode mode = |
| bMinPrecision ? DXIL::LowPrecisionMode::UseMinPrecision |
| : DXIL::LowPrecisionMode::UseNativeLowPrecision; |
| DXASSERT((mode == m_LowPrecisionMode || |
| m_LowPrecisionMode == DXIL::LowPrecisionMode::Undefined), |
| "LowPrecisionMode should only be set once."); |
| |
| if (mode != m_LowPrecisionMode) { |
| m_LowPrecisionMode = mode; |
| |
| // The following FixOverloadNames() and RefreshCache() calls interact with |
| // the type cache, which can only be correctly constructed once we know |
| // the min precision mode. That's why they are called here, rather than |
| // in the constructor. |
| |
| // When loading a module into an existing context where types are merged, |
| // type names may change. When this happens, any intrinsics overloaded on |
| // UDT types will no longer have matching overload names. |
| // This causes RefreshCache() to assert. |
| // This fixes the function names to they match the expected types, |
| // preventing RefreshCache() from failing due to this issue. |
| FixOverloadNames(); |
| |
| // Try to find existing intrinsic function. |
| RefreshCache(); |
| } |
| } |
| |
| uint64_t OP::GetAllocSizeForType(llvm::Type *Ty) { |
| return m_pModule->getDataLayout().getTypeAllocSize(Ty); |
| } |
| |
| llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) { |
| DXASSERT(F, "not work on nullptr"); |
| Type *Ty = F->getReturnType(); |
| FunctionType *FT = F->getFunctionType(); |
| LLVMContext &Ctx = F->getContext(); |
| // clang-format off |
| // Python lines need to be not formatted. |
| /* <py::lines('OPCODE-OLOAD-TYPES')>hctdb_instrhelp.get_funcs_oload_type()</py>*/ |
| // clang-format on |
| switch (opCode) { // return OpCode |
| // OPCODE-OLOAD-TYPES:BEGIN |
| case OpCode::TempRegStore: |
| case OpCode::CallShader: |
| case OpCode::Pack4x8: |
| case OpCode::WaveMatrix_Fill: |
| if (FT->getNumParams() <= 2) |
| return nullptr; |
| return FT->getParamType(2); |
| case OpCode::MinPrecXRegStore: |
| case OpCode::StoreOutput: |
| case OpCode::BufferStore: |
| case OpCode::StorePatchConstant: |
| case OpCode::RawBufferStore: |
| case OpCode::StoreVertexOutput: |
| case OpCode::StorePrimitiveOutput: |
| case OpCode::DispatchMesh: |
| if (FT->getNumParams() <= 4) |
| return nullptr; |
| return FT->getParamType(4); |
| case OpCode::IsNaN: |
| case OpCode::IsInf: |
| case OpCode::IsFinite: |
| case OpCode::IsNormal: |
| case OpCode::Countbits: |
| case OpCode::FirstbitLo: |
| case OpCode::FirstbitHi: |
| case OpCode::FirstbitSHi: |
| case OpCode::IMul: |
| case OpCode::UMul: |
| case OpCode::UDiv: |
| case OpCode::UAddc: |
| case OpCode::USubb: |
| case OpCode::WaveActiveAllEqual: |
| case OpCode::CreateHandleForLib: |
| case OpCode::WaveMatch: |
| if (FT->getNumParams() <= 1) |
| return nullptr; |
| return FT->getParamType(1); |
| case OpCode::TextureStore: |
| case OpCode::TextureStoreSample: |
| if (FT->getNumParams() <= 5) |
| return nullptr; |
| return FT->getParamType(5); |
| case OpCode::TraceRay: |
| if (FT->getNumParams() <= 15) |
| return nullptr; |
| return FT->getParamType(15); |
| case OpCode::ReportHit: |
| case OpCode::WaveMatrix_ScalarOp: |
| if (FT->getNumParams() <= 3) |
| return nullptr; |
| return FT->getParamType(3); |
| case OpCode::WaveMatrix_LoadGroupShared: |
| case OpCode::WaveMatrix_StoreGroupShared: |
| if (FT->getNumParams() <= 2) |
| return nullptr; |
| return FT->getParamType(2)->getPointerElementType(); |
| case OpCode::CreateHandle: |
| case OpCode::BufferUpdateCounter: |
| case OpCode::GetDimensions: |
| case OpCode::Texture2DMSGetSamplePosition: |
| case OpCode::RenderTargetGetSamplePosition: |
| case OpCode::RenderTargetGetSampleCount: |
| case OpCode::Barrier: |
| case OpCode::Discard: |
| case OpCode::EmitStream: |
| case OpCode::CutStream: |
| case OpCode::EmitThenCutStream: |
| case OpCode::CycleCounterLegacy: |
| case OpCode::WaveIsFirstLane: |
| case OpCode::WaveGetLaneIndex: |
| case OpCode::WaveGetLaneCount: |
| case OpCode::WaveAnyTrue: |
| case OpCode::WaveAllTrue: |
| case OpCode::WaveActiveBallot: |
| case OpCode::BitcastI16toF16: |
| case OpCode::BitcastF16toI16: |
| case OpCode::BitcastI32toF32: |
| case OpCode::BitcastF32toI32: |
| case OpCode::BitcastI64toF64: |
| case OpCode::BitcastF64toI64: |
| case OpCode::LegacyF32ToF16: |
| case OpCode::LegacyF16ToF32: |
| case OpCode::LegacyDoubleToFloat: |
| case OpCode::LegacyDoubleToSInt32: |
| case OpCode::LegacyDoubleToUInt32: |
| case OpCode::WaveAllBitCount: |
| case OpCode::WavePrefixBitCount: |
| case OpCode::IgnoreHit: |
| case OpCode::AcceptHitAndEndSearch: |
| case OpCode::WaveMultiPrefixBitCount: |
| case OpCode::SetMeshOutputCounts: |
| case OpCode::EmitIndices: |
| case OpCode::WriteSamplerFeedback: |
| case OpCode::WriteSamplerFeedbackBias: |
| case OpCode::WriteSamplerFeedbackLevel: |
| case OpCode::WriteSamplerFeedbackGrad: |
| case OpCode::AllocateRayQuery: |
| case OpCode::RayQuery_TraceRayInline: |
| case OpCode::RayQuery_Abort: |
| case OpCode::RayQuery_CommitNonOpaqueTriangleHit: |
| case OpCode::RayQuery_CommitProceduralPrimitiveHit: |
| case OpCode::AnnotateHandle: |
| case OpCode::CreateHandleFromBinding: |
| case OpCode::CreateHandleFromHeap: |
| case OpCode::WaveMatrix_Annotate: |
| case OpCode::WaveMatrix_Depth: |
| case OpCode::WaveMatrix_LoadRawBuf: |
| case OpCode::WaveMatrix_StoreRawBuf: |
| case OpCode::WaveMatrix_Multiply: |
| case OpCode::WaveMatrix_MultiplyAccumulate: |
| case OpCode::WaveMatrix_SumAccumulate: |
| case OpCode::WaveMatrix_Add: |
| case OpCode::AllocateNodeOutputRecords: |
| case OpCode::IncrementOutputCount: |
| case OpCode::OutputComplete: |
| case OpCode::GetInputRecordCount: |
| case OpCode::FinishedCrossGroupSharing: |
| case OpCode::BarrierByMemoryType: |
| case OpCode::BarrierByMemoryHandle: |
| case OpCode::BarrierByNodeRecordHandle: |
| case OpCode::CreateNodeOutputHandle: |
| case OpCode::IndexNodeHandle: |
| case OpCode::AnnotateNodeHandle: |
| case OpCode::CreateNodeInputRecordHandle: |
| case OpCode::AnnotateNodeRecordHandle: |
| case OpCode::NodeOutputIsValid: |
| case OpCode::GetRemainingRecursionLevels: |
| return Type::getVoidTy(Ctx); |
| case OpCode::CheckAccessFullyMapped: |
| case OpCode::SampleIndex: |
| case OpCode::Coverage: |
| case OpCode::InnerCoverage: |
| case OpCode::ThreadId: |
| case OpCode::GroupId: |
| case OpCode::ThreadIdInGroup: |
| case OpCode::FlattenedThreadIdInGroup: |
| case OpCode::GSInstanceID: |
| case OpCode::OutputControlPointID: |
| case OpCode::PrimitiveID: |
| case OpCode::ViewID: |
| case OpCode::InstanceID: |
| case OpCode::InstanceIndex: |
| case OpCode::HitKind: |
| case OpCode::RayFlags: |
| case OpCode::DispatchRaysIndex: |
| case OpCode::DispatchRaysDimensions: |
| case OpCode::PrimitiveIndex: |
| case OpCode::Dot4AddI8Packed: |
| case OpCode::Dot4AddU8Packed: |
| case OpCode::RayQuery_CommittedStatus: |
| case OpCode::RayQuery_CandidateType: |
| case OpCode::RayQuery_RayFlags: |
| case OpCode::RayQuery_CandidateInstanceIndex: |
| case OpCode::RayQuery_CandidateInstanceID: |
| case OpCode::RayQuery_CandidateGeometryIndex: |
| case OpCode::RayQuery_CandidatePrimitiveIndex: |
| case OpCode::RayQuery_CommittedInstanceIndex: |
| case OpCode::RayQuery_CommittedInstanceID: |
| case OpCode::RayQuery_CommittedGeometryIndex: |
| case OpCode::RayQuery_CommittedPrimitiveIndex: |
| case OpCode::GeometryIndex: |
| case OpCode::RayQuery_CandidateInstanceContributionToHitGroupIndex: |
| case OpCode::RayQuery_CommittedInstanceContributionToHitGroupIndex: |
| case OpCode::StartVertexLocation: |
| case OpCode::StartInstanceLocation: |
| return IntegerType::get(Ctx, 32); |
| case OpCode::CalculateLOD: |
| case OpCode::DomainLocation: |
| case OpCode::WorldRayOrigin: |
| case OpCode::WorldRayDirection: |
| case OpCode::ObjectRayOrigin: |
| case OpCode::ObjectRayDirection: |
| case OpCode::ObjectToWorld: |
| case OpCode::WorldToObject: |
| case OpCode::RayTMin: |
| case OpCode::RayTCurrent: |
| case OpCode::RayQuery_CandidateObjectToWorld3x4: |
| case OpCode::RayQuery_CandidateWorldToObject3x4: |
| case OpCode::RayQuery_CommittedObjectToWorld3x4: |
| case OpCode::RayQuery_CommittedWorldToObject3x4: |
| case OpCode::RayQuery_CandidateTriangleBarycentrics: |
| case OpCode::RayQuery_CommittedTriangleBarycentrics: |
| case OpCode::RayQuery_WorldRayOrigin: |
| case OpCode::RayQuery_WorldRayDirection: |
| case OpCode::RayQuery_RayTMin: |
| case OpCode::RayQuery_CandidateTriangleRayT: |
| case OpCode::RayQuery_CommittedRayT: |
| case OpCode::RayQuery_CandidateObjectRayOrigin: |
| case OpCode::RayQuery_CandidateObjectRayDirection: |
| case OpCode::RayQuery_CommittedObjectRayOrigin: |
| case OpCode::RayQuery_CommittedObjectRayDirection: |
| return Type::getFloatTy(Ctx); |
| case OpCode::MakeDouble: |
| case OpCode::SplitDouble: |
| return Type::getDoubleTy(Ctx); |
| case OpCode::RayQuery_Proceed: |
| case OpCode::RayQuery_CandidateProceduralPrimitiveNonOpaque: |
| case OpCode::RayQuery_CandidateTriangleFrontFace: |
| case OpCode::RayQuery_CommittedTriangleFrontFace: |
| case OpCode::IsHelperLane: |
| case OpCode::QuadVote: |
| return IntegerType::get(Ctx, 1); |
| case OpCode::CBufferLoadLegacy: |
| case OpCode::Sample: |
| case OpCode::SampleBias: |
| case OpCode::SampleLevel: |
| case OpCode::SampleGrad: |
| case OpCode::SampleCmp: |
| case OpCode::SampleCmpLevelZero: |
| case OpCode::TextureLoad: |
| case OpCode::BufferLoad: |
| case OpCode::TextureGather: |
| case OpCode::TextureGatherCmp: |
| case OpCode::RawBufferLoad: |
| case OpCode::Unpack4x8: |
| case OpCode::TextureGatherRaw: |
| case OpCode::SampleCmpLevel: |
| case OpCode::SampleCmpGrad: |
| case OpCode::SampleCmpBias: { |
| StructType *ST = cast<StructType>(Ty); |
| return ST->getElementType(0); |
| } |
| // OPCODE-OLOAD-TYPES:END |
| default: |
| return Ty; |
| } |
| } |
| |
| Type *OP::GetHandleType() const { return m_pHandleType; } |
| |
| Type *OP::GetNodeHandleType() const { return m_pNodeHandleType; } |
| |
| Type *OP::GetNodeRecordHandleType() const { return m_pNodeRecordHandleType; } |
| |
| Type *OP::GetResourcePropertiesType() const { |
| return m_pResourcePropertiesType; |
| } |
| |
| Type *OP::GetNodePropertiesType() const { return m_pNodePropertiesType; } |
| |
| Type *OP::GetNodeRecordPropertiesType() const { |
| return m_pNodeRecordPropertiesType; |
| } |
| |
| Type *OP::GetResourceBindingType() const { return m_pResourceBindingType; } |
| |
| Type *OP::GetDimensionsType() const { return m_pDimensionsType; } |
| |
| Type *OP::GetSamplePosType() const { return m_pSamplePosType; } |
| |
| Type *OP::GetBinaryWithCarryType() const { return m_pBinaryWithCarryType; } |
| |
| Type *OP::GetBinaryWithTwoOutputsType() const { |
| return m_pBinaryWithTwoOutputsType; |
| } |
| |
| Type *OP::GetSplitDoubleType() const { return m_pSplitDoubleType; } |
| |
| Type *OP::GetFourI32Type() const { return m_pFourI32Type; } |
| |
| Type *OP::GetFourI16Type() const { return m_pFourI16Type; } |
| |
| StructType *OP::GetWaveMatrixPropertiesType() const { |
| return m_pWaveMatInfoType; |
| } |
| PointerType *OP::GetWaveMatPtrType() const { return m_pWaveMatPtrType; } |
| |
| bool OP::IsResRetType(llvm::Type *Ty) { |
| for (Type *ResTy : m_pResRetType) { |
| if (Ty == ResTy) |
| return true; |
| } |
| return false; |
| } |
| |
| Type *OP::GetResRetType(Type *pOverloadType) { |
| unsigned TypeSlot = GetTypeSlot(pOverloadType); |
| |
| if (m_pResRetType[TypeSlot] == nullptr) { |
| string TypeName("dx.types.ResRet."); |
| TypeName += GetOverloadTypeName(TypeSlot); |
| Type *FieldTypes[5] = {pOverloadType, pOverloadType, pOverloadType, |
| pOverloadType, Type::getInt32Ty(m_Ctx)}; |
| m_pResRetType[TypeSlot] = |
| GetOrCreateStructType(m_Ctx, FieldTypes, TypeName, m_pModule); |
| } |
| |
| return m_pResRetType[TypeSlot]; |
| } |
| |
| Type *OP::GetCBufferRetType(Type *pOverloadType) { |
| unsigned TypeSlot = GetTypeSlot(pOverloadType); |
| |
| if (m_pCBufferRetType[TypeSlot] == nullptr) { |
| DXASSERT(m_LowPrecisionMode != DXIL::LowPrecisionMode::Undefined, |
| "m_LowPrecisionMode must be set before constructing type."); |
| string TypeName("dx.types.CBufRet."); |
| TypeName += GetOverloadTypeName(TypeSlot); |
| Type *i64Ty = Type::getInt64Ty(pOverloadType->getContext()); |
| Type *i16Ty = Type::getInt16Ty(pOverloadType->getContext()); |
| if (pOverloadType->isDoubleTy() || pOverloadType == i64Ty) { |
| Type *FieldTypes[2] = {pOverloadType, pOverloadType}; |
| m_pCBufferRetType[TypeSlot] = |
| GetOrCreateStructType(m_Ctx, FieldTypes, TypeName, m_pModule); |
| } else if (!UseMinPrecision() && |
| (pOverloadType->isHalfTy() || pOverloadType == i16Ty)) { |
| TypeName += ".8"; // dx.types.CBufRet.fp16.8 for buffer of 8 halves |
| Type *FieldTypes[8] = { |
| pOverloadType, pOverloadType, pOverloadType, pOverloadType, |
| pOverloadType, pOverloadType, pOverloadType, pOverloadType, |
| }; |
| m_pCBufferRetType[TypeSlot] = |
| GetOrCreateStructType(m_Ctx, FieldTypes, TypeName, m_pModule); |
| } else { |
| Type *FieldTypes[4] = {pOverloadType, pOverloadType, pOverloadType, |
| pOverloadType}; |
| m_pCBufferRetType[TypeSlot] = |
| GetOrCreateStructType(m_Ctx, FieldTypes, TypeName, m_pModule); |
| } |
| } |
| return m_pCBufferRetType[TypeSlot]; |
| } |
| |
| Type *OP::GetVectorType(unsigned numElements, Type *pOverloadType) { |
| if (numElements == 4) { |
| if (pOverloadType == Type::getInt32Ty(pOverloadType->getContext())) { |
| return m_pFourI32Type; |
| } else if (pOverloadType == Type::getInt16Ty(pOverloadType->getContext())) { |
| return m_pFourI16Type; |
| } |
| } |
| DXASSERT(false, "unexpected overload type"); |
| return nullptr; |
| } |
| |
| //------------------------------------------------------------------------------ |
| // |
| // LLVM utility methods. |
| // |
| Constant *OP::GetI1Const(bool v) { |
| return Constant::getIntegerValue(IntegerType::get(m_Ctx, 1), APInt(1, v)); |
| } |
| |
| Constant *OP::GetI8Const(char v) { |
| return Constant::getIntegerValue(IntegerType::get(m_Ctx, 8), APInt(8, v)); |
| } |
| |
| Constant *OP::GetU8Const(unsigned char v) { return GetI8Const((char)v); } |
| |
| Constant *OP::GetI16Const(int v) { |
| return Constant::getIntegerValue(IntegerType::get(m_Ctx, 16), APInt(16, v)); |
| } |
| |
| Constant *OP::GetU16Const(unsigned v) { return GetI16Const((int)v); } |
| |
| Constant *OP::GetI32Const(int v) { |
| return Constant::getIntegerValue(IntegerType::get(m_Ctx, 32), APInt(32, v)); |
| } |
| |
| Constant *OP::GetU32Const(unsigned v) { return GetI32Const((int)v); } |
| |
| Constant *OP::GetU64Const(unsigned long long v) { |
| return Constant::getIntegerValue(IntegerType::get(m_Ctx, 64), APInt(64, v)); |
| } |
| |
| Constant *OP::GetFloatConst(float v) { |
| return ConstantFP::get(m_Ctx, APFloat(v)); |
| } |
| |
| Constant *OP::GetDoubleConst(double v) { |
| return ConstantFP::get(m_Ctx, APFloat(v)); |
| } |
| |
| } // namespace hlsl |