Files
KytyPS5/src/graphics/shader/recompiler/emitter/spirvEmitterInternal.h
T
nmzik 86a586025f renderer: expand rectangle lists with tessellation
Remove the legacy NGG rectangle workaround and its configuration toggle.
2026-08-03 00:35:02 +02:00

1612 lines
66 KiB
C++

#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SPIRVEMITTER_INTERNAL_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SPIRVEMITTER_INTERNAL_H_
#include "common/common.h"
#include "common/stringUtils.h"
#include "graphics/shader/recompiler/BufferFormat.h"
#include "graphics/shader/recompiler/emitter/SpirvBuilder.h"
#include "graphics/shader/recompiler/ir/BindingLayout.h"
#include "graphics/shader/recompiler/ir/ResourceMaterialization.h"
#include "graphics/shader/recompiler/ir/ShaderIR.h"
#include <algorithm>
#include <array>
#include <cinttypes>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <map>
#include <utility>
#include <vector>
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
enum : uint32_t {
ExecutionModelVertex = 0,
ExecutionModelFragment = 4,
ExecutionModelGLCompute = 5,
ExecutionModeOriginUpperLeft = 7,
ExecutionModeEarlyFragmentTests = 9,
ExecutionModeDepthReplacing = 12,
ExecutionModeLocalSize = 17,
ExecutionModeDerivativeGroupQuadsKHR = 5289,
AddressingModelLogical = 0,
MemoryModelGLSL450 = 1,
CapabilityShader = 1,
CapabilityImageGatherExtended = 25,
CapabilitySampled1D = 43,
CapabilityImage1D = 44,
CapabilityImageQuery = 50,
CapabilityStorageImageReadWithoutFormat = 55,
CapabilityStorageImageWriteWithoutFormat = 56,
CapabilityGroupNonUniform = 61,
CapabilityGroupNonUniformBallot = 64,
CapabilityGroupNonUniformShuffle = 65,
CapabilityComputeDerivativeGroupQuadsKHR = 5288,
StorageClassUniformConstant = 0,
StorageClassInput = 1,
StorageClassOutput = 3,
StorageClassWorkgroup = 4,
StorageClassFunction = 7,
StorageClassPushConstant = 9,
StorageClassImage = 11,
StorageClassStorageBuffer = 12,
FunctionControlNone = 0,
SelectionControlNone = 0,
LoopControlNone = 0,
};
enum : uint32_t {
DecorationBlock = 2,
DecorationBuiltIn = 11,
DecorationNoPerspective = 13,
DecorationFlat = 14,
DecorationLocation = 30,
DecorationArrayStride = 6,
DecorationBinding = 33,
DecorationDescriptorSet = 34,
DecorationOffset = 35,
};
enum : uint32_t {
BuiltInPosition = 0,
BuiltInFragCoord = 15,
BuiltInFrontFacing = 17,
BuiltInSampleMask = 20,
BuiltInFragDepth = 22,
BuiltInWorkgroupId = 26,
BuiltInLocalInvocationId = 27,
BuiltInGlobalInvocationId = 28,
BuiltInLocalInvocationIndex = 29,
BuiltInSubgroupLocalInvocationId = 41,
BuiltInVertexIndex = 42,
BuiltInInstanceIndex = 43,
};
enum : uint32_t {
Dim1D = 0,
Dim3D = 2,
Dim2D = 1,
ImageFormatUnknown = 0,
ImageFormatRgba32f = 1,
ImageFormatR32ui = 33,
};
enum : uint32_t {
ImageOperandsBiasMask = 0x00000001u,
ImageOperandsLodMask = 0x00000002u,
ImageOperandsGradMask = 0x00000004u,
ImageOperandsOffsetMask = 0x00000010u,
ImageOperandsConstOffsetsMask = 0x00000020u,
ImageOperandsSampleMask = 0x00000040u,
};
enum : uint32_t {
ScopeDevice = 1,
ScopeWorkgroup = 2,
ScopeSubgroup = 3,
MemorySemanticsNone = 0,
MemorySemanticsAcquireRelease = 0x00000008u,
MemorySemanticsUniformMemory = 0x00000040u,
MemorySemanticsWorkgroupMemory = 0x00000100u,
};
enum : uint32_t {
OpExtInst = 12,
OpTypeVoid = 19,
OpTypeBool = 20,
OpTypeInt = 21,
OpTypeFloat = 22,
OpTypeVector = 23,
OpTypeImage = 25,
OpTypeSampler = 26,
OpTypeSampledImage = 27,
OpTypeArray = 28,
OpTypeRuntimeArray = 29,
OpTypeStruct = 30,
OpTypePointer = 32,
OpTypeFunction = 33,
OpConstant = 43,
OpConstantComposite = 44,
OpFunction = 54,
OpFunctionEnd = 56,
OpVariable = 59,
OpImageTexelPointer = 60,
OpLoad = 61,
OpStore = 62,
OpAccessChain = 65,
OpArrayLength = 68,
OpDecorate = 71,
OpMemberDecorate = 72,
OpVectorShuffle = 79,
OpCompositeConstruct = 80,
OpCompositeExtract = 81,
OpSampledImage = 86,
OpImageSampleImplicitLod = 87,
OpImageSampleExplicitLod = 88,
OpImageSampleDrefImplicitLod = 89,
OpImageSampleDrefExplicitLod = 90,
OpImageFetch = 95,
OpImageGather = 96,
OpImageDrefGather = 97,
OpImageWrite = 99,
OpImageQuerySizeLod = 103,
OpImageQueryLod = 105,
OpImageQueryLevels = 106,
OpConvertFToU = 109,
OpConvertFToS = 110,
OpConvertSToF = 111,
OpConvertUToF = 112,
OpBitcast = 124,
OpSNegate = 126,
OpFNegate = 127,
OpIAdd = 128,
OpFAdd = 129,
OpISub = 130,
OpFSub = 131,
OpIMul = 132,
OpFMul = 133,
OpUDiv = 134,
OpFDiv = 136,
OpIAddCarry = 149,
OpUMulExtended = 151,
OpSMulExtended = 152,
OpLogicalNotEqual = 165,
OpLogicalOr = 166,
OpLogicalAnd = 167,
OpLogicalNot = 168,
OpSelect = 169,
OpIEqual = 170,
OpINotEqual = 171,
OpUGreaterThan = 172,
OpSGreaterThan = 173,
OpUGreaterThanEqual = 174,
OpSGreaterThanEqual = 175,
OpULessThan = 176,
OpSLessThan = 177,
OpULessThanEqual = 178,
OpSLessThanEqual = 179,
OpFOrdEqual = 180,
OpFUnordEqual = 181,
OpFOrdNotEqual = 182,
OpFUnordNotEqual = 183,
OpFOrdLessThan = 184,
OpFUnordLessThan = 185,
OpFOrdGreaterThan = 186,
OpFUnordGreaterThan = 187,
OpFOrdLessThanEqual = 188,
OpFUnordLessThanEqual = 189,
OpFOrdGreaterThanEqual = 190,
OpFUnordGreaterThanEqual = 191,
OpShiftRightLogical = 194,
OpShiftRightArithmetic = 195,
OpShiftLeftLogical = 196,
OpBitwiseOr = 197,
OpBitwiseXor = 198,
OpBitwiseAnd = 199,
OpNot = 200,
OpBitFieldInsert = 201,
OpBitFieldSExtract = 202,
OpBitFieldUExtract = 203,
OpBitReverse = 204,
OpBitCount = 205,
OpControlBarrier = 224,
OpMemoryBarrier = 225,
OpAtomicLoad = 227,
OpAtomicExchange = 229,
OpAtomicCompareExchange = 230,
OpAtomicIAdd = 234,
OpAtomicISub = 235,
OpAtomicSMin = 236,
OpAtomicUMin = 237,
OpAtomicSMax = 238,
OpAtomicUMax = 239,
OpAtomicAnd = 240,
OpAtomicOr = 241,
OpAtomicXor = 242,
OpPhi = 245,
OpLoopMerge = 246,
OpSelectionMerge = 247,
OpLabel = 248,
OpBranch = 249,
OpBranchConditional = 250,
OpSwitch = 251,
OpKill = 252,
OpReturn = 253,
OpGroupNonUniformBallot = 339,
OpGroupNonUniformBallotFindLSB = 343,
OpGroupNonUniformShuffle = 345,
};
enum : uint32_t {
GlslRoundEven = 2,
GlslTrunc = 3,
GlslFAbs = 4,
GlslFloor = 8,
GlslCeil = 9,
GlslFract = 10,
GlslSin = 13,
GlslCos = 14,
GlslExp2 = 29,
GlslLog2 = 30,
GlslSqrt = 31,
GlslInverseSqrt = 32,
GlslFMin = 37,
GlslFMax = 40,
GlslFClamp = 43,
GlslLdexp = 53,
GlslFma = 50,
GlslPackSnorm2x16 = 56,
GlslPackUnorm2x16 = 57,
GlslPackHalf2x16 = 58,
GlslUnpackHalf2x16 = 62,
GlslFindILsb = 73,
GlslFindUMsb = 75,
};
struct RegisterBinding {
IR::Register reg;
uint32_t pointer_id = 0;
};
struct InputBinding {
IR::StageInputKind kind = IR::StageInputKind::VertexIndex;
uint32_t location = 0;
uint32_t component_count = 1;
uint32_t variable_id = 0;
std::string debug_name;
};
struct OutputBinding {
IR::StageOutputKind kind = IR::StageOutputKind::Parameter;
uint32_t index = 0;
uint32_t location = 0;
uint32_t variable_id = 0;
std::string debug_name;
};
struct DescriptorResourceBinding {
const IR::DescriptorBinding* descriptor = nullptr;
uint32_t array_index = 0;
};
struct SampledImageDescriptors {
uint32_t image_type = 0;
uint32_t sampled_image_type = 0;
uint32_t pointer_type = 0;
uint32_t array_type = 0;
uint32_t array_pointer_type = 0;
uint32_t variable = 0;
};
struct StorageImageDescriptors {
uint32_t image_type = 0;
uint32_t pointer_type = 0;
uint32_t array_type = 0;
uint32_t array_pointer_type = 0;
uint32_t variable = 0;
};
struct EmitterState {
EmitterState(const IR::Program& program_, const IR::ResourceSnapshot& resources_)
: program(program_), resources(resources_) {}
Builder builder;
const IR::Program& program;
const IR::ResourceSnapshot& resources;
const ShaderVertexInputInfo* vertex_input_info = nullptr;
const ShaderPixelInputInfo* pixel_input_info = nullptr;
const ShaderComputeInputInfo* compute_input_info = nullptr;
ShaderType stage = ShaderType::Unknown;
uint32_t wave_size = 64;
bool exact_subgroup_operations = false;
bool per_invocation_masks = false;
uint32_t void_type = 0;
uint32_t bool_type = 0;
uint32_t uint_type = 0;
uint32_t uint_pair_type = 0;
uint32_t int_pair_type = 0;
uint32_t int_type = 0;
uint32_t float_type = 0;
uint32_t vec2_uint_type = 0;
uint32_t vec3_uint_type = 0;
uint32_t vec4_uint_type = 0;
uint32_t vec2_int_type = 0;
uint32_t vec3_int_type = 0;
uint32_t vec4_int_type = 0;
uint32_t vec2_float_type = 0;
uint32_t vec3_float_type = 0;
uint32_t vec4_float_type = 0;
uint32_t ptr_func_uint = 0;
uint32_t ptr_input_float = 0;
uint32_t ptr_input_bool = 0;
uint32_t ptr_input_int = 0;
uint32_t ptr_input_uint = 0;
uint32_t ptr_input_vec2_float = 0;
uint32_t ptr_input_vec3_float = 0;
uint32_t ptr_input_vec2_int = 0;
uint32_t ptr_input_vec3_int = 0;
uint32_t ptr_input_vec4_int = 0;
uint32_t ptr_input_vec2_uint = 0;
uint32_t ptr_input_vec3_uint = 0;
uint32_t ptr_input_vec4_uint = 0;
uint32_t ptr_input_vec4_float = 0;
uint32_t sample_mask_array_type = 0;
uint32_t ptr_output_int = 0;
uint32_t ptr_output_sample_mask_array = 0;
uint32_t ptr_output_float = 0;
uint32_t ptr_output_vec4_float = 0;
uint32_t per_vertex_type = 0;
uint32_t ptr_output_per_vertex = 0;
uint32_t storage_runtime_array_type = 0;
uint32_t storage_buffer_type = 0;
uint32_t ptr_storage_buffer = 0;
uint32_t ptr_storage_buffer_uint = 0;
uint32_t storage_buffer_array_type = 0;
uint32_t ptr_storage_buffer_array = 0;
uint32_t storage_buffer_variable = 0;
std::array<uint32_t, IR::ShaderInfo::MaxBuffers> storage_buffer_offsets {};
uint32_t address_memory_array_type = 0;
uint32_t ptr_address_memory_array = 0;
uint32_t address_memory_variable = 0;
uint32_t gds_variable = 0;
uint32_t push_constant_array_type = 0;
uint32_t push_constant_block_type = 0;
uint32_t ptr_push_constant_block = 0;
uint32_t ptr_push_constant_uint = 0;
uint32_t push_constant_variable = 0;
uint32_t vsharp_storage_variable = 0;
uint32_t flattened_srt_variable = 0;
uint32_t lds_array_type = 0;
uint32_t ptr_workgroup_array = 0;
uint32_t ptr_workgroup_uint = 0;
uint32_t lds_variable = 0;
std::array<SampledImageDescriptors, 14> sampled_images;
std::array<StorageImageDescriptors, 10> storage_images;
uint32_t sampler_type = 0;
uint32_t sampler_array_type = 0;
uint32_t ptr_uniform_sampler = 0;
uint32_t ptr_uniform_sampler_array = 0;
uint32_t sampler_variable = 0;
uint32_t ptr_image_uint = 0;
uint32_t func_type = 0;
uint32_t main_func = 0;
uint32_t entry_label = 0;
uint32_t pixel_valid_mask_variable = 0;
bool dispatcher_fallback = false;
uint32_t dispatch_pc_variable = 0;
uint32_t dispatch_header_label = 0;
uint32_t dispatch_select_label = 0;
uint32_t dispatch_default_label = 0;
uint32_t dispatch_after_switch_label = 0;
uint32_t dispatch_continue_label = 0;
uint32_t dispatch_merge_label = 0;
uint32_t glsl_std450 = 0;
uint32_t subgroup_local_invocation_id_variable = 0;
uint32_t per_vertex_variable = 0;
uint32_t depth_variable = 0;
uint32_t sample_mask_variable = 0;
bool needs_subgroup_ballot = false;
bool needs_subgroup_shuffle = false;
bool needs_subgroup_local_invocation_id = false;
bool needs_compute_derivatives = false;
bool needs_image_gather_extended = false;
bool needs_function_lds = false;
bool needs_pixel_valid_mask = false;
std::vector<RegisterBinding> registers;
std::vector<InputBinding> inputs;
std::vector<OutputBinding> outputs;
std::vector<uint32_t> interface_variables;
std::vector<bool> reachable_blocks;
std::map<uint32_t, uint32_t> block_labels;
std::map<uint32_t, uint32_t> constants;
std::map<uint32_t, uint32_t> signed_constants;
std::map<uint32_t, uint32_t> float_constants;
};
enum class VertexInputScalarKind { Float, Sint, Uint };
constexpr uint32_t NoImageComponent = 0xffffffffu;
struct DppTargetLane {
uint32_t lane = 0;
uint32_t valid = 0;
};
struct ImageSampleLayout {
uint32_t offset = NoImageComponent;
uint32_t dref = NoImageComponent;
uint32_t bias = NoImageComponent;
uint32_t coord = 0;
uint32_t lod = NoImageComponent;
uint32_t grad_x = NoImageComponent;
uint32_t grad_y = NoImageComponent;
};
enum class ImageViewKind {
Dim1D,
Dim1DArray,
Dim2D,
Dim2DArray,
Dim3D,
Dim2DMsaa,
Dim2DMsaaArray,
Count,
};
constexpr uint32_t SampledImageViewKindCount = static_cast<uint32_t>(ImageViewKind::Count);
constexpr uint32_t StorageImageViewKindCount = static_cast<uint32_t>(ImageViewKind::Dim2DMsaa);
constexpr uint32_t SampledImageIndex(bool integer, ImageViewKind view) {
return static_cast<uint32_t>(view) + (integer ? SampledImageViewKindCount : 0u);
}
constexpr uint32_t StorageImageIndex(bool integer, ImageViewKind view) {
return static_cast<uint32_t>(view) + (integer ? StorageImageViewKindCount : 0u);
}
constexpr IR::DescriptorBindingKind SampledBindingKind(bool integer, ImageViewKind view) {
if (integer) {
switch (view) {
case ImageViewKind::Dim1D: return IR::DescriptorBindingKind::SampledUint1D;
case ImageViewKind::Dim1DArray: return IR::DescriptorBindingKind::SampledUint1DArray;
case ImageViewKind::Dim2D: return IR::DescriptorBindingKind::SampledUint2D;
case ImageViewKind::Dim2DArray: return IR::DescriptorBindingKind::SampledUint2DArray;
case ImageViewKind::Dim3D: return IR::DescriptorBindingKind::SampledUint3D;
case ImageViewKind::Dim2DMsaa: return IR::DescriptorBindingKind::SampledUint2DMsaa;
case ImageViewKind::Dim2DMsaaArray:
return IR::DescriptorBindingKind::SampledUint2DMsaaArray;
default: break;
}
}
switch (view) {
case ImageViewKind::Dim1D: return IR::DescriptorBindingKind::Sampled1D;
case ImageViewKind::Dim1DArray: return IR::DescriptorBindingKind::Sampled1DArray;
case ImageViewKind::Dim2D: return IR::DescriptorBindingKind::Sampled2D;
case ImageViewKind::Dim2DArray: return IR::DescriptorBindingKind::Sampled2DArray;
case ImageViewKind::Dim3D: return IR::DescriptorBindingKind::Sampled3D;
case ImageViewKind::Dim2DMsaa: return IR::DescriptorBindingKind::Sampled2DMsaa;
case ImageViewKind::Dim2DMsaaArray: return IR::DescriptorBindingKind::Sampled2DMsaaArray;
default: break;
}
return IR::DescriptorBindingKind::Count;
}
constexpr IR::DescriptorBindingKind StorageBindingKind(bool integer, ImageViewKind view) {
if (integer) {
switch (view) {
case ImageViewKind::Dim1D: return IR::DescriptorBindingKind::StorageUint1D;
case ImageViewKind::Dim1DArray: return IR::DescriptorBindingKind::StorageUint1DArray;
case ImageViewKind::Dim2D: return IR::DescriptorBindingKind::StorageUint2D;
case ImageViewKind::Dim2DArray: return IR::DescriptorBindingKind::StorageUint2DArray;
case ImageViewKind::Dim3D: return IR::DescriptorBindingKind::StorageUint3D;
default: break;
}
}
switch (view) {
case ImageViewKind::Dim1D: return IR::DescriptorBindingKind::Storage1D;
case ImageViewKind::Dim1DArray: return IR::DescriptorBindingKind::Storage1DArray;
case ImageViewKind::Dim2D: return IR::DescriptorBindingKind::Storage2D;
case ImageViewKind::Dim2DArray: return IR::DescriptorBindingKind::Storage2DArray;
case ImageViewKind::Dim3D: return IR::DescriptorBindingKind::Storage3D;
default: break;
}
return IR::DescriptorBindingKind::Count;
}
constexpr uint32_t ImageSpirvDimension(ImageViewKind view) {
switch (view) {
case ImageViewKind::Dim1D:
case ImageViewKind::Dim1DArray: return Dim1D;
case ImageViewKind::Dim2D:
case ImageViewKind::Dim2DArray:
case ImageViewKind::Dim2DMsaa:
case ImageViewKind::Dim2DMsaaArray:
case ImageViewKind::Count: return Dim2D;
case ImageViewKind::Dim3D: return Dim3D;
}
return Dim2D;
}
constexpr uint32_t ImageSpirvArrayed(ImageViewKind view) {
return view == ImageViewKind::Dim1DArray || view == ImageViewKind::Dim2DArray ||
view == ImageViewKind::Dim2DMsaaArray
? 1u
: 0u;
}
constexpr uint32_t ImageSpirvMultisampled(ImageViewKind view) {
return view == ImageViewKind::Dim2DMsaa || view == ImageViewKind::Dim2DMsaaArray ? 1u : 0u;
}
struct AddCarryResult {
uint32_t sum = 0;
uint32_t carry = 0;
};
struct F32Class {
uint32_t bits = 0;
uint32_t nan = 0;
uint32_t snan = 0;
uint32_t zero = 0;
uint32_t quiet_bits = 0;
};
struct CubeF32Values {
uint32_t x = 0;
uint32_t y = 0;
uint32_t z = 0;
uint32_t nx = 0;
uint32_t ny = 0;
uint32_t nz = 0;
uint32_t z_face = 0;
uint32_t y_face = 0;
uint32_t x_neg = 0;
uint32_t y_neg = 0;
uint32_t z_neg = 0;
};
struct F16Class {
uint32_t bits = 0;
uint32_t nan = 0;
uint32_t snan = 0;
uint32_t zero = 0;
uint32_t quiet_bits = 0;
};
uint32_t PixelParameterMappedLocation(const EmitterState& state, uint32_t attr);
uint32_t PixelParameterLocation(const EmitterState& state, uint32_t attr);
bool PixelParameterIsFlat(const EmitterState& state, uint32_t attr);
VertexInputScalarKind VertexParameterScalarKind(const EmitterState& state, uint32_t location);
uint32_t VertexParameterComponentCount(const EmitterState& state, const InputBinding& input);
uint32_t VertexParameterScalarType(const EmitterState& state, VertexInputScalarKind kind);
uint32_t VertexParameterScalarPointerType(const EmitterState& state, VertexInputScalarKind kind);
uint32_t VertexParameterVectorOrScalarType(const EmitterState& state, VertexInputScalarKind kind,
uint32_t components);
uint32_t VertexParameterInputPointerType(const EmitterState& state, VertexInputScalarKind kind,
uint32_t components);
void SetError(std::string* error, const char* message);
void CollectRegister(std::vector<RegisterBinding>& registers, IR::Register reg);
IR::Operand MakeRegisterOperand(IR::RegisterFile file, uint32_t index);
IR::Register SccRegister();
IR::Operand SccOperand();
bool IsInactiveWave32ExecHigh(const EmitterState& state, IR::Register reg);
bool IsMaskRegisterFile(IR::RegisterFile file);
bool IsSccOperand(const IR::Operand& operand);
bool IsCompareOpcode(IR::Opcode op);
void CollectMaskStateRegisters(std::vector<RegisterBinding>& registers);
void CollectSequentialRegisters(std::vector<RegisterBinding>& registers, const IR::Operand& base,
uint32_t count);
uint32_t MaxCollectedVectorRegisterEnd(const std::vector<RegisterBinding>& registers);
void CollectMoveRelSourceRegisters(const IR::Program& program,
std::vector<RegisterBinding>& registers);
bool IsPairDwordOpcode(IR::Opcode op);
uint32_t PairDwordSourceCount(IR::Opcode op, uint32_t src_count);
void CollectRegisters(const IR::Program& program, std::vector<RegisterBinding>& registers);
bool HasOutput(const std::vector<OutputBinding>& outputs, IR::StageOutputKind kind, uint32_t index);
void CopyProgramInputsAndOutputs(EmitterState& state, const IR::Program& program);
uint32_t OutputVariableForExport(const EmitterState& state, const IR::ExportInfo& exp);
bool ProgramNeedsComputeDerivatives(const IR::Program& program);
bool ProgramNeedsImageGatherExtended(const IR::Program& program);
bool IsLdsOpcode(IR::Opcode op);
bool ProgramNeedsFunctionLds(const IR::Program& program);
bool ProgramNeedsPixelValidMask(const IR::Program& program);
bool InstructionHasDppSource(const IR::Instruction& inst);
bool ProgramNeedsSubgroupBallot(const IR::Program& program);
bool ProgramNeedsSubgroupShuffle(const IR::Program& program);
bool IsCompareOpcode(IR::Opcode op);
bool ProgramNeedsSubgroupLocalInvocationId(const IR::Program& program);
uint32_t PointerForRegister(const EmitterState& state, IR::Register reg);
uint32_t ConstantU32(EmitterState& state, uint32_t value);
void EmitStoreU32(EmitterState& state, const IR::Operand& dst, uint32_t value);
uint32_t EmitSubgroupLocalInvocationId(EmitterState& state);
uint32_t EmitLaneIndexActiveBool(EmitterState& state, uint32_t lane);
[[noreturn]] void ExitDescriptorBindingFailure(const EmitterState& state,
IR::DescriptorBindingKind kind, uint32_t resource,
const char* reason);
DescriptorResourceBinding ResourceForDescriptor(const EmitterState& state,
IR::DescriptorBindingKind kind, uint32_t resource);
uint32_t DescriptorElementPointer(EmitterState& state, uint32_t result_ptr_type,
uint32_t variable_id, uint32_t array_index,
IR::DescriptorBindingKind kind, uint32_t resource,
const char* variable_name);
ImageViewKind SampledImageViewKind(const EmitterState& state, const IR::MemoryInfo& mem,
uint32_t use_pc);
uint32_t ImageViewCoordinateComponents(ImageViewKind view);
uint32_t ImageViewSpatialComponents(ImageViewKind view);
uint32_t ImageViewImageType(const EmitterState& state, ImageViewKind view, bool integer);
uint32_t ImageViewSampledImageType(const EmitterState& state, ImageViewKind view, bool integer);
uint32_t ImageViewSizeType(const EmitterState& state, ImageViewKind view);
uint32_t LoadSampledImageDescriptor(EmitterState& state, const IR::MemoryInfo& mem, uint32_t use_pc,
ImageViewKind view);
uint32_t LoadSamplerDescriptor(EmitterState& state, uint32_t sampler, uint32_t use_pc);
uint32_t MakeSampledImage(EmitterState& state, const IR::MemoryInfo& mem, uint32_t use_pc,
ImageViewKind view);
ImageViewKind StorageImageViewKind(const EmitterState& state, const IR::MemoryInfo& mem,
bool uint_image, uint32_t use_pc);
uint32_t StorageImageDescriptorPointer(EmitterState& state, uint32_t resource, bool uint_image,
uint32_t use_pc = UINT32_MAX,
ImageViewKind view = ImageViewKind::Dim2D);
uint32_t LoadStorageImageDescriptor(EmitterState& state, uint32_t resource, bool uint_image,
uint32_t use_pc, ImageViewKind view = ImageViewKind::Dim2D);
uint32_t ExecutionModelForStage(ShaderType stage);
uint32_t ConstantU32(EmitterState& state, uint32_t value);
uint32_t ConstantI32(EmitterState& state, int32_t value);
uint32_t ConstantF32(EmitterState& state, uint32_t bits);
uint32_t FloatBits(float value);
uint32_t ConstantF32Value(EmitterState& state, float value);
void AllocateInputVariables(EmitterState& state);
void AllocateOutputVariables(EmitterState& state);
uint32_t BuiltInForInput(IR::StageInputKind kind);
void AddInputAnnotationsAndNames(EmitterState& state);
void AddOutputAnnotationsAndNames(EmitterState& state);
void DecorateDescriptor(EmitterState& state, uint32_t variable, const char* name, uint32_t set,
uint32_t binding);
void AddDescriptorAnnotationsAndNames(EmitterState& state);
void EmitHeaderAndTypes(EmitterState& state);
void AllocateRegisterVariables(EmitterState& state);
void AllocateDescriptorVariables(EmitterState& state);
bool SdwaSelectorOffsetWidth(uint32_t sel, uint32_t& offset, uint32_t& width);
uint32_t EmitSdwaExtractU32(EmitterState& state, const IR::Operand& operand, uint32_t value);
uint32_t EmitTrueBool(EmitterState& state);
DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uint32_t control);
DppTargetLane EmitDppRowShiftTargetLane(EmitterState& state, uint32_t subid, uint32_t amount,
bool left);
DppTargetLane EmitDppRowRotateRightTargetLane(EmitterState& state, uint32_t subid, uint32_t amount);
DppTargetLane EmitDppMirrorTargetLane(EmitterState& state, uint32_t subid, bool half_row);
DppTargetLane EmitDppTargetLane(EmitterState& state, uint32_t control);
uint32_t EmitDppValueU32(EmitterState& state, const IR::Operand& operand, uint32_t value);
uint32_t EmitValueLoad(EmitterState& state, const IR::Operand& operand);
uint32_t EmitRegisterLoad(EmitterState& state, IR::Register reg);
uint32_t WaveMaskHighLoad(EmitterState& state, IR::RegisterFile file);
uint32_t EmitLaneMaskPartU32(EmitterState& state, uint32_t part);
uint32_t EmitThreadMaskBelowPartU32(EmitterState& state, uint32_t part);
uint32_t EmitMaskActiveBool(EmitterState& state, IR::RegisterFile file);
uint32_t EmitMaskZeroBool(EmitterState& state, IR::RegisterFile file, bool zero);
uint32_t EmitMaskSummaryZeroBool(EmitterState& state, IR::RegisterFile file, bool zero);
uint32_t EmitExecActiveBool(EmitterState& state);
uint32_t EmitConditionBool(EmitterState& state, const IR::Operand& operand);
uint32_t EmitSubgroupLocalInvocationId(EmitterState& state);
uint32_t InputVariableForKind(const EmitterState& state, IR::StageInputKind kind);
uint32_t InputVariableForParameter(const EmitterState& state, uint32_t location);
uint32_t EmitInputComponentU32(EmitterState& state, IR::StageInputKind kind, uint32_t component);
uint32_t EmitLocalInvocationIndex(EmitterState& state);
void EmitLoadInputF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitSccBool(EmitterState& state, bool non_zero);
uint32_t EmitFloatLoad(EmitterState& state, const IR::Operand& operand);
uint32_t ApplyResultModifiersF32(EmitterState& state, uint32_t value, const IR::Operand& dst);
uint32_t EmitMixF32Load(EmitterState& state, const IR::Operand& operand);
IR::Operand OffsetRegisterOperand(const IR::Operand& operand, uint32_t offset);
uint32_t EmitLaneMaskOperandActiveBool(EmitterState& state, const IR::Operand& operand);
uint32_t EmitBallotLaneActiveBool(EmitterState& state, uint32_t ballot, uint32_t lane);
uint32_t EmitLaneIndexActiveBool(EmitterState& state, uint32_t lane);
uint32_t EmitSubgroupLaneActiveBool(EmitterState& state, uint32_t lane);
uint32_t EmitSequentialValueLoad(EmitterState& state, const IR::Operand& operand, uint32_t offset);
uint32_t EmitSequentialFloatLoad(EmitterState& state, const IR::Operand& operand, uint32_t offset);
uint32_t ImageAddressHalfComponent(const IR::Instruction& inst, uint32_t component);
IR::Operand ImageAddressOperand(const IR::Instruction& inst, const IR::Operand& base,
uint32_t component);
uint32_t EmitImageAddressValueLoad(EmitterState& state, const IR::Instruction& inst,
const IR::Operand& base, uint32_t component);
uint32_t EmitImageAddressFloatLoad(EmitterState& state, const IR::Instruction& inst,
const IR::Operand& base, uint32_t component);
uint32_t EmitZeroF32(EmitterState& state);
bool HasImageSampleFlag(const IR::Instruction& inst, uint32_t flag);
ImageSampleLayout MakeImageSampleLayout(const IR::Instruction& inst, ImageViewKind view);
uint32_t EmitImageCoordF32(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout, ImageViewKind view);
uint32_t EmitImageLodF32(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout);
uint32_t EmitImageDrefF32(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout);
uint32_t EmitImageBiasF32(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout);
uint32_t EmitImageGradientF32(EmitterState& state, const IR::Instruction& inst,
uint32_t first_component, ImageViewKind view);
uint32_t EmitImagePackedOffsetI32(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout, ImageViewKind view);
uint32_t EmitImageCoordU32(EmitterState& state, const IR::Instruction& inst,
ImageViewKind view = ImageViewKind::Dim2D);
uint32_t EmitImageLoadCoordU32(EmitterState& state, const IR::Instruction& inst,
ImageViewKind view);
uint32_t EmitImageMipLodU32(EmitterState& state, const IR::Instruction& inst,
const IR::Operand& address, ImageViewKind view);
uint32_t EmitImageQueryCoordF32(EmitterState& state, const IR::Instruction& inst,
ImageViewKind view);
uint32_t DmaskComponentIndex(uint32_t dmask, uint32_t component);
uint32_t EmitImageStoreComponentF32(EmitterState& state, const IR::Instruction& inst,
uint32_t component);
uint32_t EmitImageStoreTexelF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitImageStoreTexelU32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitDppWriteActiveBool(EmitterState& state, const IR::Operand& dst);
uint32_t EmitSdwaDestinationMerge(EmitterState& state, uint32_t pointer, const IR::Operand& dst,
uint32_t value);
void EmitStoreU32(EmitterState& state, const IR::Operand& dst, uint32_t value);
uint32_t EmitAddU32(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitBinaryU32(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs);
uint32_t EmitNotEqualZeroBool(EmitterState& state, uint32_t value);
uint32_t EmitSelectU32Value(EmitterState& state, uint32_t condition, uint32_t true_value,
uint32_t false_value);
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index);
uint32_t EmitByteAddress(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
uint32_t src_count);
uint32_t StorageBufferPackedStride(const EmitterState& state, const IR::MemoryInfo& mem,
uint32_t use_pc);
uint32_t StorageBufferFormat(const EmitterState& state, const IR::MemoryInfo& mem, uint32_t use_pc);
bool ShouldApplyBufferAddTid(const IR::Instruction& inst);
uint32_t EmitBufferIndexWithAddTid(EmitterState& state, const IR::Instruction& inst, uint32_t index,
uint32_t packed);
uint32_t EmitOptionalLogicalAndBool(EmitterState& state, uint32_t lhs, uint32_t rhs);
bool IsStorageBufferMemoryKind(IR::ResourceKind kind);
void EmitStorageBufferOffsets(EmitterState& state);
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
uint32_t index, uint32_t offset, uint32_t soffset);
uint32_t EmitBufferByteAddress(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
uint32_t src_count);
uint32_t EmitMemoryByteAddress(EmitterState& state, const IR::Instruction& inst,
const IR::MemoryInfo& mem, uint32_t first_src, uint32_t src_count);
uint32_t EmitDwordIndex(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
uint32_t src_count);
uint32_t EmitMemoryDwordIndex(EmitterState& state, const IR::Instruction& inst,
const IR::MemoryInfo& mem, uint32_t first_src, uint32_t src_count);
DescriptorResourceBinding StorageBufferBindingForMemory(EmitterState& state,
const IR::MemoryInfo& mem, uint32_t use_pc);
uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInfo& mem,
uint32_t use_pc);
uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryInfo& mem,
uint32_t index, uint32_t use_pc);
uint32_t EmitStorageBufferElementPointer(EmitterState& state, const IR::MemoryInfo& mem,
uint32_t index, uint32_t use_pc);
uint32_t EmitLdsElementPointer(EmitterState& state, uint32_t index);
uint32_t EmitGdsElementInBounds(EmitterState& state, uint32_t index);
uint32_t EmitGdsElementPointer(EmitterState& state, uint32_t index);
uint32_t EmitMemoryElementPointer(EmitterState& state, const IR::MemoryInfo& mem, uint32_t index,
uint32_t use_pc);
uint32_t EmitMemoryLoadDwordValueU32(EmitterState& state, const IR::Instruction& inst,
IR::ResourceKind kind, uint32_t first_src, uint32_t src_count);
void EmitMemoryLoadU32(EmitterState& state, const IR::Instruction& inst, IR::ResourceKind kind,
uint32_t first_src, uint32_t src_count);
uint32_t EmitMemoryLoadSubDwordValueU32(EmitterState& state, const IR::Instruction& inst,
IR::ResourceKind kind, uint32_t first_src,
uint32_t src_count, uint32_t data_bits, bool sign_extend);
void EmitMemoryLoadSubDwordU32(EmitterState& state, const IR::Instruction& inst,
IR::ResourceKind kind, uint32_t first_src, uint32_t src_count,
uint32_t data_bits, bool sign_extend);
void EmitMemoryStoreU32(EmitterState& state, const IR::Instruction& inst, IR::ResourceKind kind,
uint32_t first_src, uint32_t src_count);
void EmitMemoryStoreSubDwordU32(EmitterState& state, const IR::Instruction& inst,
IR::ResourceKind kind, uint32_t first_src, uint32_t src_count,
uint32_t data_bits);
uint32_t AddressSourceCount(const IR::Instruction& inst, uint32_t first_src);
bool IsFormattedBufferComponent(const IR::Instruction& inst);
Prospero::BufferFormat FormattedBufferFormat(const EmitterState& state,
const IR::Instruction& inst);
IR::Instruction WithFormatComponentByteOffset(const IR::Instruction& inst,
Prospero::BufferFormat format);
uint32_t EmitTBufferBitcastF32ToU32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferBitcastU32ToF32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value,
uint32_t constant);
uint32_t EmitTBufferSelectF32(EmitterState& state, uint32_t condition, uint32_t true_value,
uint32_t false_value);
bool IsSignedFormatComponent(Format::ComponentType type);
uint32_t EmitExtractFormatFieldU32(EmitterState& state, uint32_t raw_word, uint32_t offset,
uint32_t bits, bool sign_extend);
uint32_t EmitHalfToF32Bits(EmitterState& state, uint32_t raw);
uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits);
uint32_t EmitFormatRawComponent(EmitterState& state, const IR::Instruction& inst,
const Format::BufferFormatInfo& info);
uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferFormatInfo& info,
uint32_t component, uint32_t raw);
uint32_t UnpackTBufferFormat(EmitterState& state, const IR::Instruction& inst,
const Format::BufferFormatInfo& info);
uint32_t FormattedBufferDwordStoreComponentCount(Prospero::BufferFormat format,
uint32_t opcode_components);
bool EmitBufferIntegerFormatStore(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitAtomicPointer(EmitterState& state, const IR::Instruction& inst);
void EmitDeviceAtomicMemoryBarrier(EmitterState& state);
void EmitAtomicU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitSLoadDword(EmitterState& state, const IR::Instruction& inst);
void EmitLoadSrtDword(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadUbyte(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadSbyte(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadUshort(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadSshort(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadDword(EmitterState& state, const IR::Instruction& inst);
void EmitBufferLoadDwordGroup(EmitterState& state, const IR::Instruction* instructions,
uint32_t count);
void EmitBufferStoreDword(EmitterState& state, const IR::Instruction& inst);
void EmitFlatLoadUbyte(EmitterState& state, const IR::Instruction& inst);
void EmitFlatLoadSbyte(EmitterState& state, const IR::Instruction& inst);
void EmitFlatLoadUshort(EmitterState& state, const IR::Instruction& inst);
void EmitFlatLoadSshort(EmitterState& state, const IR::Instruction& inst);
void EmitFlatLoadDword(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitDsAddtidDwordIndex(EmitterState& state, const IR::Instruction& inst,
uint32_t m0_src_index);
void EmitDsWriteAddtidB32(EmitterState& state, const IR::Instruction& inst);
void EmitDsReadAddtidB32(EmitterState& state, const IR::Instruction& inst);
void EmitDsAppendConsume(EmitterState& state, const IR::Instruction& inst, uint32_t atomic_opcode);
void EmitDsFloatMinMaxF32(EmitterState& state, const IR::Instruction& inst, bool max_value);
uint32_t EmitDsSwizzleTargetLane(EmitterState& state, uint32_t subid, uint32_t control);
void EmitDsSwizzleB32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitImageGetResinfoComponent(EmitterState& state, uint32_t image, uint32_t size,
uint32_t component_index);
void EmitImageGetResinfo(EmitterState& state, const IR::Instruction& inst);
void EmitImageGetLod(EmitterState& state, const IR::Instruction& inst);
void EmitImageLoad(EmitterState& state, const IR::Instruction& inst);
void EmitImageStore(EmitterState& state, const IR::Instruction& inst);
void EmitImageSampleResult(EmitterState& state, const IR::Instruction& inst, uint32_t sample,
bool dref);
bool ImageSampleNeedsExplicitLod(const EmitterState& state, const IR::Instruction& inst);
void AddImageSampleOperands(EmitterState& state, const IR::Instruction& inst,
const ImageSampleLayout& layout, bool explicit_lod,
std::vector<uint32_t>& words);
uint32_t ImageSampleOpcode(const EmitterState& state, const IR::Instruction& inst);
void EmitImageSample(EmitterState& state, const IR::Instruction& inst);
uint32_t ImageGatherComponent(uint32_t dmask);
void EmitImageGather4(EmitterState& state, const IR::Instruction& inst);
void EmitMoveU32(EmitterState& state, const IR::Instruction& inst);
void EmitMoveF32Bits(EmitterState& state, const IR::Instruction& inst);
uint32_t MoveRelRegisterLimit(const EmitterState& state, IR::Register base);
void EmitMoveRelSourceU32(EmitterState& state, const IR::Instruction& inst);
void EmitMoveRelDestU32(EmitterState& state, const IR::Instruction& inst);
void EmitMoveU64(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitWqmLaneU32(EmitterState& state, uint32_t src);
void EmitWqmB64(EmitterState& state, const IR::Instruction& inst);
void EmitSaveexecB32(EmitterState& state, const IR::Instruction& inst);
void EmitSaveexecB64(EmitterState& state, const IR::Instruction& inst);
void EmitReadFirstLaneU32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitLaneIndex(EmitterState& state, const IR::Operand& operand);
void EmitReadLaneU32(EmitterState& state, const IR::Instruction& inst);
void EmitWriteLaneU32(EmitterState& state, const IR::Instruction& inst);
void EmitPermlaneB32(EmitterState& state, const IR::Instruction& inst, bool x16);
void EmitControlNop(EmitterState& state, const IR::Instruction& inst);
void EmitWaitcnt(EmitterState& state, const IR::Instruction& inst);
void EmitBarrier(EmitterState& state, const IR::Instruction& inst);
void EmitAbsI32(EmitterState& state, const IR::Instruction& inst);
void EmitUnaryU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitUnaryU64(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitFindLsbU32(EmitterState& state, const IR::Instruction& inst);
void EmitFindMsbFromHighU32(EmitterState& state, const IR::Instruction& inst);
void EmitFindMsbFromHighU64(EmitterState& state, const IR::Instruction& inst);
void EmitBitCountU64(EmitterState& state, const IR::Instruction& inst);
void EmitBitCountU32(EmitterState& state, const IR::Instruction& inst);
void EmitBitCountAddU32(EmitterState& state, const IR::Instruction& inst);
void EmitBinaryU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitBinaryNotRhsU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitBinaryThenNotU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitMaskedBitCountU32(EmitterState& state, const IR::Instruction& inst, uint32_t exec_index);
uint32_t EmitMask5U32(EmitterState& state, uint32_t value);
void EmitChainedBinaryU32(EmitterState& state, const IR::Instruction& inst, uint32_t first_op,
uint32_t second_op, bool mask_first_rhs = false,
bool mask_second_rhs = false);
void EmitBinaryU64(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitBinaryNotRhsU64(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitBinaryThenNotU64(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitSelectU64(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitSelectValueU32(EmitterState& state, uint32_t cond, uint32_t true_value,
uint32_t false_value);
void EmitStoreSccBool(EmitterState& state, uint32_t cond);
uint32_t EmitAndConstant(EmitterState& state, uint32_t value, uint32_t mask);
void EmitShiftLeftLogicalU64Values(EmitterState& state, uint32_t low, uint32_t high, uint32_t shift,
uint32_t& out_low, uint32_t& out_high);
void EmitShiftLeftLogicalU64(EmitterState& state, const IR::Instruction& inst);
void EmitShiftRightLogicalU64Values(EmitterState& state, uint32_t low, uint32_t high,
uint32_t shift, uint32_t& out_low, uint32_t& out_high);
void EmitShiftRightLogicalU64(EmitterState& state, const IR::Instruction& inst);
void EmitAdd3U32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitAndConstant(EmitterState& state, uint32_t value, uint32_t mask);
void EmitShiftU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
uint32_t EmitU16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane,
bool sign_extend = false);
void EmitShiftU16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode,
bool arithmetic);
void EmitBinaryU16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitMinMaxU16(EmitterState& state, const IR::Instruction& inst, bool signed_value,
bool max_value);
uint32_t EmitXorConstant(EmitterState& state, uint32_t value, uint32_t mask);
AddCarryResult EmitAddCarryValues(EmitterState& state, uint32_t lhs, uint32_t rhs,
uint32_t carry_in);
void EmitLaneMaskPairFromBool(EmitterState& state, const IR::Operand& dst, uint32_t value_bool);
void EmitPerInvocationMask(EmitterState& state, const IR::Operand& dst, uint32_t value_bool);
void EmitIAddCarryU32(EmitterState& state, const IR::Instruction& inst);
void EmitISubBorrowU32(EmitterState& state, const IR::Instruction& inst);
void EmitScalarAddCarryU32(EmitterState& state, const IR::Instruction& inst);
void EmitScalarSubBorrowU32(EmitterState& state, const IR::Instruction& inst);
void EmitScalarSubBorrowCarryU32(EmitterState& state, const IR::Instruction& inst);
void EmitBitClearU32(EmitterState& state, const IR::Instruction& inst);
void EmitBitSetU32(EmitterState& state, const IR::Instruction& inst);
void EmitUMadU64U32(EmitterState& state, const IR::Instruction& inst);
void EmitScalarSignedOverflowI32(EmitterState& state, const IR::Instruction& inst, bool subtract);
void EmitScalarShiftLeftAddCarryU32(EmitterState& state, const IR::Instruction& inst);
void EmitMulU24U32(EmitterState& state, const IR::Instruction& inst);
void EmitMulI24U32(EmitterState& state, const IR::Instruction& inst);
void EmitMulHighU32(EmitterState& state, const IR::Instruction& inst);
void EmitMulHighI32(EmitterState& state, const IR::Instruction& inst);
void EmitMadU32U24(EmitterState& state, const IR::Instruction& inst);
void EmitMadI32I24(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitShiftLeftConstant(EmitterState& state, uint32_t value, uint32_t shift);
uint32_t EmitShiftRightConstant(EmitterState& state, uint32_t value, uint32_t shift);
uint32_t EmitOrU32(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitBitReplicateHalfU32(EmitterState& state, uint32_t value);
void EmitBitReplicateB64B32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitBitFieldExtractConstant(EmitterState& state, uint32_t value, uint32_t offset,
uint32_t count);
uint32_t EmitRightAlignedMaskU32(EmitterState& state, uint32_t count);
void EmitBitFieldMaskU32(EmitterState& state, const IR::Instruction& inst);
void EmitRightAlignedMaskU64(EmitterState& state, uint32_t count, uint32_t& out_low,
uint32_t& out_high);
void EmitBitFieldMaskU64(EmitterState& state, const IR::Instruction& inst);
void EmitBitFieldExtractU64(EmitterState& state, const IR::Instruction& inst);
void EmitBitFieldExtractU32(EmitterState& state, const IR::Instruction& inst);
void EmitBitFieldExtract3U32(EmitterState& state, const IR::Instruction& inst, bool signed_value);
void EmitBitFieldInsertSelectU32(EmitterState& state, const IR::Instruction& inst);
void EmitAlignBitU32(EmitterState& state, const IR::Instruction& inst);
void EmitSelectU32(EmitterState& state, const IR::Instruction& inst);
void EmitSelectMaskU32(EmitterState& state, const IR::Instruction& inst);
void EmitSelectF32Bits(EmitterState& state, const IR::Instruction& inst);
void EmitSelectMaskF32Bits(EmitterState& state, const IR::Instruction& inst);
void EmitPackU16(EmitterState& state, const IR::Instruction& inst, bool high_src0, bool high_src1);
void EmitPackU8F32(EmitterState& state, const IR::Instruction& inst);
void EmitBinaryF32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitLdexpF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value,
uint32_t constant);
uint32_t EmitSubConstantMinusU32(EmitterState& state, uint32_t constant, uint32_t value);
uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32);
void EmitPackF32ToF16Rtz(EmitterState& state, const IR::Instruction& inst);
void EmitPackNormalizedF32(EmitterState& state, const IR::Instruction& inst, uint32_t ext_inst);
uint32_t EmitMinMaxU32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value);
void EmitMinMaxU32(EmitterState& state, const IR::Instruction& inst, bool max_value);
void EmitSadU32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitMinMaxI32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value);
void EmitMinMaxI32(EmitterState& state, const IR::Instruction& inst, bool max_value);
void EmitMinMax3U32(EmitterState& state, const IR::Instruction& inst, bool signed_value,
bool max_value);
void EmitMed3U32(EmitterState& state, const IR::Instruction& inst, bool signed_value);
uint32_t EmitBitcastF32ToU32(EmitterState& state, uint32_t value);
uint32_t EmitBitcastU32ToF32(EmitterState& state, uint32_t value);
uint32_t EmitAndU32(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitLogicalAndBool(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitLogicalOrBool(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitLogicalNotBool(EmitterState& state, uint32_t value);
F32Class EmitClassifyF32(EmitterState& state, uint32_t value);
uint32_t EmitClassMaskBitMatch(EmitterState& state, uint32_t mask, uint32_t bit,
uint32_t class_match);
uint32_t EmitClassMaskF32(EmitterState& state, uint32_t value, uint32_t mask);
uint32_t EmitMinMaxF32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value);
void EmitMinMaxF32(EmitterState& state, const IR::Instruction& inst, bool max_value);
void EmitCompareResult(EmitterState& state, const IR::Operand& dst, uint32_t cond);
void EmitCompareU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitCompareU16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitCompareI16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitBitCompareB32(EmitterState& state, const IR::Instruction& inst, bool bit_set);
void EmitCompareNeU64(EmitterState& state, const IR::Instruction& inst);
void EmitCompareConstant(EmitterState& state, const IR::Instruction& inst, bool value);
void EmitCompareMaskU32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitCompareF32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitCompareOrderedF32(EmitterState& state, const IR::Instruction& inst, bool ordered);
void EmitCompareClassF32(EmitterState& state, const IR::Instruction& inst);
void EmitCompareMaskF32(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitConvertU32ToF32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertI32ToF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitTruncF32Value(EmitterState& state, uint32_t value);
void EmitConvertF32ToU32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertF32ToI32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertF32ToF16(EmitterState& state, const IR::Instruction& inst);
void EmitConvertF16ToF32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertU16ToF16(EmitterState& state, const IR::Instruction& inst);
void EmitConvertF16ToU16(EmitterState& state, const IR::Instruction& inst);
void EmitConvertI16ToF16(EmitterState& state, const IR::Instruction& inst);
void EmitConvertF16ToI16(EmitterState& state, const IR::Instruction& inst);
void EmitConvertRoundPlusInfF32ToI32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertFloorF32ToI32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertI4ToOffsetF32(EmitterState& state, const IR::Instruction& inst);
void EmitConvertByteU32ToF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitFlushF32DenormToSignedZero(EmitterState& state, uint32_t value);
void EmitRcpF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitTrigCycleF32(EmitterState& state, uint32_t src, bool preserve_signed_zero);
void EmitFloatExtInst(EmitterState& state, const IR::Instruction& inst, uint32_t ext_inst,
bool scale_by_two_pi = false, bool flush_denorm = false);
void EmitMadF32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitFNegateValue(EmitterState& state, uint32_t value);
uint32_t EmitFAbsValue(EmitterState& state, uint32_t value);
uint32_t EmitFCompareValue(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs);
uint32_t EmitLogicalAndValue(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitFSelectValue(EmitterState& state, uint32_t cond, uint32_t true_value,
uint32_t false_value);
uint32_t EmitFMulConstant(EmitterState& state, uint32_t value, uint32_t bits);
CubeF32Values EmitCubeF32Values(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitCubeIdF32(EmitterState& state, const CubeF32Values& cube);
uint32_t EmitCubeScF32(EmitterState& state, const CubeF32Values& cube);
uint32_t EmitCubeTcF32(EmitterState& state, const CubeF32Values& cube);
uint32_t EmitCubeMaF32(EmitterState& state, const CubeF32Values& cube);
void EmitCubeF32(EmitterState& state, const IR::Instruction& inst);
void EmitDot2AccF32F16(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitPackedF16Lane(EmitterState& state, const IR::Operand& operand, bool high_lane);
void EmitCompareF16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
uint32_t EmitPackedF16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane);
uint32_t EmitF16BitsToF32(EmitterState& state, uint32_t bits);
uint32_t EmitPackLowF32ToF16Bits(EmitterState& state, uint32_t value);
void EmitPackB32F16(EmitterState& state, const IR::Instruction& inst);
F16Class EmitClassifyF16Bits(EmitterState& state, uint32_t value);
uint32_t EmitNegativeNumericF16Bool(EmitterState& state, const F16Class& cls);
uint32_t EmitRcpF16Bits(EmitterState& state, uint32_t bits);
uint32_t EmitSqrtF16Bits(EmitterState& state, uint32_t bits);
uint32_t EmitRsqF16Bits(EmitterState& state, uint32_t bits);
uint32_t EmitLog2F16Bits(EmitterState& state, uint32_t bits);
uint32_t EmitExp2F16Bits(EmitterState& state, uint32_t bits);
void EmitSpecialF16(EmitterState& state, const IR::Instruction& inst);
void EmitBinaryF16(EmitterState& state, const IR::Instruction& inst, uint32_t opcode);
void EmitFmaF16(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitMinMaxF16Bits(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value);
void EmitMinMaxF16(EmitterState& state, const IR::Instruction& inst, bool max_value);
uint32_t EmitMinMax3F16Bits(EmitterState& state, uint32_t src0, uint32_t src1, uint32_t src2,
bool max_value);
void EmitMinMax3F16(EmitterState& state, const IR::Instruction& inst, bool max_value);
uint32_t EmitF16BitsEqualBool(EmitterState& state, uint32_t lhs, uint32_t rhs);
uint32_t EmitAnyNanF16Bool(EmitterState& state, uint32_t src0, uint32_t src1, uint32_t src2);
void EmitMed3F16(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitPackedMinMaxF16(EmitterState& state, const IR::Instruction& inst, bool max_value);
uint32_t EmitPackedF16BinaryLane(EmitterState& state, const IR::Instruction& inst, bool high_lane,
uint32_t opcode);
uint32_t EmitPackedF16FmaLane(EmitterState& state, const IR::Instruction& inst, bool high_lane);
void EmitPackedF16(EmitterState& state, const IR::Instruction& inst);
void EmitPackedInteger16(EmitterState& state, const IR::Instruction& inst);
void EmitMadMixF16(EmitterState& state, const IR::Instruction& inst);
void EmitMinMax3F32(EmitterState& state, const IR::Instruction& inst, bool max_value);
void EmitMed3F32(EmitterState& state, const IR::Instruction& inst);
uint32_t EmitExportComponentF32(EmitterState& state, const IR::Instruction& inst,
uint32_t component);
uint32_t EmitExportVec4F32(EmitterState& state, const IR::Instruction& inst);
bool ExportWritesData(const IR::Instruction& inst);
void EmitExport(EmitterState& state, const IR::Instruction& inst);
bool ExportUsesPixelValidMask(const EmitterState& state, const IR::Instruction& inst);
void EmitKillIfBoolFalse(EmitterState& state, uint32_t active);
void EmitUpdatePixelValidMask(EmitterState& state);
void EmitKillIfPixelValidMaskInactive(EmitterState& state);
void ComputeReachableBlocks(EmitterState& state, const IR::Program& program);
void AllocateBlockLabels(EmitterState& state, const IR::Program& program);
void AllocateDispatcherState(EmitterState& state, const IR::Program& program);
uint32_t BlockLabel(const EmitterState& state, uint32_t block_id);
uint32_t EmitBranchCondition(EmitterState& state, CFG::BranchCondition condition);
void EmitStructuredPrefix(EmitterState& state, const CFG::Terminator& term);
void EmitReturn(EmitterState& state);
void EmitTerminator(EmitterState& state, const CFG::Terminator& term);
uint32_t InitialRegisterValue(const EmitterState& state, IR::Register reg);
void EmitRegisterVariables(EmitterState& state);
void EmitComputeInputRegisters(EmitterState& state);
void EmitPixelInputRegisters(EmitterState& state);
void EmitInstruction(EmitterState& state, const IR::Instruction& inst);
uint32_t DispatcherTargetValue(EmitterState& state, uint32_t block_id);
void EmitDispatcherStoreTarget(EmitterState& state, uint32_t block_id);
void EmitDispatcherExit(EmitterState& state);
void EmitDispatcherTerminator(EmitterState& state, const CFG::Terminator& term);
void EmitDispatcherSwitch(EmitterState& state, const IR::Program& program);
void EmitDispatcherBlocks(EmitterState& state, const IR::Program& program);
void EmitDispatcherLoopTail(EmitterState& state);
void EmitDispatcherFunction(EmitterState& state, const IR::Program& program);
void EmitFunction(EmitterState& state, const IR::Program& program);
// These templates accept local lambdas from several emitter translation units.
template <typename Fn>
void EmitIfCondition(EmitterState& state, uint32_t condition, Fn&& fn) {
if (condition == 0) {
fn();
return;
}
const auto then_label = state.builder.AllocateId();
const auto merge_label = state.builder.AllocateId();
state.builder.AddFunction({OpSelectionMerge, merge_label, SelectionControlNone});
state.builder.AddFunction({OpBranchConditional, condition, then_label, merge_label});
state.builder.AddFunction({OpLabel, then_label});
fn();
state.builder.AddFunction({OpBranch, merge_label});
state.builder.AddFunction({OpLabel, merge_label});
}
template <typename Fn>
uint32_t EmitValueOrZeroIfCondition(EmitterState& state, uint32_t condition, Fn&& fn) {
if (condition == 0) {
return fn();
}
const auto then_label = state.builder.AllocateId();
const auto else_label = state.builder.AllocateId();
const auto merge_label = state.builder.AllocateId();
state.builder.AddFunction({OpSelectionMerge, merge_label, SelectionControlNone});
state.builder.AddFunction({OpBranchConditional, condition, then_label, else_label});
state.builder.AddFunction({OpLabel, then_label});
const auto then_value = fn();
state.builder.AddFunction({OpBranch, merge_label});
state.builder.AddFunction({OpLabel, else_label});
state.builder.AddFunction({OpBranch, merge_label});
state.builder.AddFunction({OpLabel, merge_label});
const auto value = state.builder.AllocateId();
state.builder.AddFunction(
{OpPhi, state.uint_type, value, then_value, then_label, ConstantU32(state, 0), else_label});
return value;
}
template <typename Fn>
void EmitGuardedByExec(EmitterState& state, Fn&& fn) {
const auto then_label = state.builder.AllocateId();
const auto merge_label = state.builder.AllocateId();
const auto condition = EmitExecActiveBool(state);
state.builder.AddFunction({OpSelectionMerge, merge_label, SelectionControlNone});
state.builder.AddFunction({OpBranchConditional, condition, then_label, merge_label});
state.builder.AddFunction({OpLabel, then_label});
fn();
state.builder.AddFunction({OpBranch, merge_label});
state.builder.AddFunction({OpLabel, merge_label});
}
} // namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SPIRVEMITTER_INTERNAL_H_ */