Path: blob/21.2-virgl/src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
4574 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "spirv_builder.h"2425#include "util/macros.h"26#include "util/set.h"27#include "util/ralloc.h"28#include "util/u_bitcast.h"29#include "util/u_memory.h"30#include "util/half_float.h"31#include "util/hash_table.h"32#define XXH_INLINE_ALL33#include "util/xxhash.h"3435#include <stdbool.h>36#include <inttypes.h>37#include <string.h>3839static bool40spirv_buffer_grow(struct spirv_buffer *b, void *mem_ctx, size_t needed)41{42size_t new_room = MAX3(64, (b->room * 3) / 2, needed);4344uint32_t *new_words = reralloc_size(mem_ctx, b->words,45new_room * sizeof(uint32_t));46if (!new_words)47return false;4849b->words = new_words;50b->room = new_room;51return true;52}5354static inline bool55spirv_buffer_prepare(struct spirv_buffer *b, void *mem_ctx, size_t needed)56{57needed += b->num_words;58if (b->room >= b->num_words + needed)59return true;6061return spirv_buffer_grow(b, mem_ctx, needed);62}6364static inline void65spirv_buffer_emit_word(struct spirv_buffer *b, uint32_t word)66{67assert(b->num_words < b->room);68b->words[b->num_words++] = word;69}7071static int72spirv_buffer_emit_string(struct spirv_buffer *b, void *mem_ctx,73const char *str)74{75int pos = 0;76uint32_t word = 0;77while (str[pos] != '\0') {78word |= str[pos] << (8 * (pos % 4));79if (++pos % 4 == 0) {80spirv_buffer_prepare(b, mem_ctx, 1);81spirv_buffer_emit_word(b, word);82word = 0;83}84}8586spirv_buffer_prepare(b, mem_ctx, 1);87spirv_buffer_emit_word(b, word);8889return 1 + pos / 4;90}9192void93spirv_builder_emit_cap(struct spirv_builder *b, SpvCapability cap)94{95if (!b->caps)96b->caps = _mesa_set_create_u32_keys(b->mem_ctx);9798assert(b->caps);99_mesa_set_add(b->caps, (void*)(uintptr_t)cap);100}101102void103spirv_builder_emit_extension(struct spirv_builder *b, const char *name)104{105size_t pos = b->extensions.num_words;106spirv_buffer_prepare(&b->extensions, b->mem_ctx, 1);107spirv_buffer_emit_word(&b->extensions, SpvOpExtension);108int len = spirv_buffer_emit_string(&b->extensions, b->mem_ctx, name);109b->extensions.words[pos] |= (1 + len) << 16;110}111112void113spirv_builder_emit_source(struct spirv_builder *b, SpvSourceLanguage lang,114uint32_t version)115{116spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 3);117spirv_buffer_emit_word(&b->debug_names, SpvOpSource | (3 << 16));118spirv_buffer_emit_word(&b->debug_names, lang);119spirv_buffer_emit_word(&b->debug_names, version);120}121122void123spirv_builder_emit_mem_model(struct spirv_builder *b,124SpvAddressingModel addr_model,125SpvMemoryModel mem_model)126{127spirv_buffer_prepare(&b->memory_model, b->mem_ctx, 3);128spirv_buffer_emit_word(&b->memory_model, SpvOpMemoryModel | (3 << 16));129spirv_buffer_emit_word(&b->memory_model, addr_model);130spirv_buffer_emit_word(&b->memory_model, mem_model);131}132133void134spirv_builder_emit_entry_point(struct spirv_builder *b,135SpvExecutionModel exec_model, SpvId entry_point,136const char *name, const SpvId interfaces[],137size_t num_interfaces)138{139size_t pos = b->entry_points.num_words;140spirv_buffer_prepare(&b->entry_points, b->mem_ctx, 3);141spirv_buffer_emit_word(&b->entry_points, SpvOpEntryPoint);142spirv_buffer_emit_word(&b->entry_points, exec_model);143spirv_buffer_emit_word(&b->entry_points, entry_point);144int len = spirv_buffer_emit_string(&b->entry_points, b->mem_ctx, name);145b->entry_points.words[pos] |= (3 + len + num_interfaces) << 16;146spirv_buffer_prepare(&b->entry_points, b->mem_ctx, num_interfaces);147for (int i = 0; i < num_interfaces; ++i)148spirv_buffer_emit_word(&b->entry_points, interfaces[i]);149}150151void152spirv_builder_emit_exec_mode_literal(struct spirv_builder *b, SpvId entry_point,153SpvExecutionMode exec_mode, uint32_t param)154{155spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 4);156spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (4 << 16));157spirv_buffer_emit_word(&b->exec_modes, entry_point);158spirv_buffer_emit_word(&b->exec_modes, exec_mode);159spirv_buffer_emit_word(&b->exec_modes, param);160}161162void163spirv_builder_emit_exec_mode_literal3(struct spirv_builder *b, SpvId entry_point,164SpvExecutionMode exec_mode, uint32_t param[3])165{166spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 6);167spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (6 << 16));168spirv_buffer_emit_word(&b->exec_modes, entry_point);169spirv_buffer_emit_word(&b->exec_modes, exec_mode);170for (unsigned i = 0; i < 3; i++)171spirv_buffer_emit_word(&b->exec_modes, param[i]);172}173174void175spirv_builder_emit_exec_mode(struct spirv_builder *b, SpvId entry_point,176SpvExecutionMode exec_mode)177{178spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 3);179spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (3 << 16));180spirv_buffer_emit_word(&b->exec_modes, entry_point);181spirv_buffer_emit_word(&b->exec_modes, exec_mode);182}183184void185spirv_builder_emit_name(struct spirv_builder *b, SpvId target,186const char *name)187{188size_t pos = b->debug_names.num_words;189spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 2);190spirv_buffer_emit_word(&b->debug_names, SpvOpName);191spirv_buffer_emit_word(&b->debug_names, target);192int len = spirv_buffer_emit_string(&b->debug_names, b->mem_ctx, name);193b->debug_names.words[pos] |= (2 + len) << 16;194}195196static void197emit_decoration(struct spirv_builder *b, SpvId target,198SpvDecoration decoration, const uint32_t extra_operands[],199size_t num_extra_operands)200{201int words = 3 + num_extra_operands;202spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);203spirv_buffer_emit_word(&b->decorations, SpvOpDecorate | (words << 16));204spirv_buffer_emit_word(&b->decorations, target);205spirv_buffer_emit_word(&b->decorations, decoration);206for (int i = 0; i < num_extra_operands; ++i)207spirv_buffer_emit_word(&b->decorations, extra_operands[i]);208}209210void211spirv_builder_emit_decoration(struct spirv_builder *b, SpvId target,212SpvDecoration decoration)213{214emit_decoration(b, target, decoration, NULL, 0);215}216217void218spirv_builder_emit_specid(struct spirv_builder *b, SpvId target, uint32_t id)219{220uint32_t args[] = { id };221emit_decoration(b, target, SpvDecorationSpecId, args, ARRAY_SIZE(args));222}223224void225spirv_builder_emit_location(struct spirv_builder *b, SpvId target,226uint32_t location)227{228uint32_t args[] = { location };229emit_decoration(b, target, SpvDecorationLocation, args, ARRAY_SIZE(args));230}231232void233spirv_builder_emit_component(struct spirv_builder *b, SpvId target,234uint32_t component)235{236uint32_t args[] = { component };237emit_decoration(b, target, SpvDecorationComponent, args, ARRAY_SIZE(args));238}239240void241spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,242SpvBuiltIn builtin)243{244uint32_t args[] = { builtin };245emit_decoration(b, target, SpvDecorationBuiltIn, args, ARRAY_SIZE(args));246}247248void249spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream)250{251unsigned words = 1;252SpvOp op = SpvOpEmitVertex;253if (stream > 0) {254op = SpvOpEmitStreamVertex;255words++;256}257spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);258spirv_buffer_emit_word(&b->instructions, op | (words << 16));259if (stream)260spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));261}262263void264spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream)265{266unsigned words = 1;267SpvOp op = SpvOpEndPrimitive;268if (stream > 0) {269op = SpvOpEndStreamPrimitive;270words++;271}272spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);273spirv_buffer_emit_word(&b->instructions, op | (words << 16));274if (stream)275spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));276}277278void279spirv_builder_emit_descriptor_set(struct spirv_builder *b, SpvId target,280uint32_t descriptor_set)281{282uint32_t args[] = { descriptor_set };283emit_decoration(b, target, SpvDecorationDescriptorSet, args,284ARRAY_SIZE(args));285}286287void288spirv_builder_emit_binding(struct spirv_builder *b, SpvId target,289uint32_t binding)290{291uint32_t args[] = { binding };292emit_decoration(b, target, SpvDecorationBinding, args, ARRAY_SIZE(args));293}294295void296spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,297uint32_t stride)298{299uint32_t args[] = { stride };300emit_decoration(b, target, SpvDecorationArrayStride, args, ARRAY_SIZE(args));301}302303void304spirv_builder_emit_offset(struct spirv_builder *b, SpvId target,305uint32_t offset)306{307uint32_t args[] = { offset };308emit_decoration(b, target, SpvDecorationOffset, args, ARRAY_SIZE(args));309}310311void312spirv_builder_emit_xfb_buffer(struct spirv_builder *b, SpvId target,313uint32_t buffer)314{315uint32_t args[] = { buffer };316emit_decoration(b, target, SpvDecorationXfbBuffer, args, ARRAY_SIZE(args));317}318319void320spirv_builder_emit_xfb_stride(struct spirv_builder *b, SpvId target,321uint32_t stride)322{323uint32_t args[] = { stride };324emit_decoration(b, target, SpvDecorationXfbStride, args, ARRAY_SIZE(args));325}326327void328spirv_builder_emit_index(struct spirv_builder *b, SpvId target, int index)329{330uint32_t args[] = { index };331emit_decoration(b, target, SpvDecorationIndex, args, ARRAY_SIZE(args));332}333334void335spirv_builder_emit_stream(struct spirv_builder *b, SpvId target, int stream)336{337uint32_t args[] = { stream };338emit_decoration(b, target, SpvDecorationStream, args, ARRAY_SIZE(args));339}340341static void342emit_member_decoration(struct spirv_builder *b, SpvId target, uint32_t member,343SpvDecoration decoration, const uint32_t extra_operands[],344size_t num_extra_operands)345{346int words = 4 + num_extra_operands;347spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);348spirv_buffer_emit_word(&b->decorations,349SpvOpMemberDecorate | (words << 16));350spirv_buffer_emit_word(&b->decorations, target);351spirv_buffer_emit_word(&b->decorations, member);352spirv_buffer_emit_word(&b->decorations, decoration);353for (int i = 0; i < num_extra_operands; ++i)354spirv_buffer_emit_word(&b->decorations, extra_operands[i]);355}356357void358spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target,359uint32_t member, uint32_t offset)360{361uint32_t args[] = { offset };362emit_member_decoration(b, target, member, SpvDecorationOffset,363args, ARRAY_SIZE(args));364}365366SpvId367spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type)368{369SpvId result = spirv_builder_new_id(b);370spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);371spirv_buffer_emit_word(&b->instructions, SpvOpUndef | (3 << 16));372spirv_buffer_emit_word(&b->instructions, result_type);373spirv_buffer_emit_word(&b->instructions, result);374return result;375}376377void378spirv_builder_function(struct spirv_builder *b, SpvId result,379SpvId return_type,380SpvFunctionControlMask function_control,381SpvId function_type)382{383spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);384spirv_buffer_emit_word(&b->instructions, SpvOpFunction | (5 << 16));385spirv_buffer_emit_word(&b->instructions, return_type);386spirv_buffer_emit_word(&b->instructions, result);387spirv_buffer_emit_word(&b->instructions, function_control);388spirv_buffer_emit_word(&b->instructions, function_type);389}390391void392spirv_builder_function_end(struct spirv_builder *b)393{394spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);395spirv_buffer_emit_word(&b->instructions, SpvOpFunctionEnd | (1 << 16));396}397398void399spirv_builder_label(struct spirv_builder *b, SpvId label)400{401spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);402spirv_buffer_emit_word(&b->instructions, SpvOpLabel | (2 << 16));403spirv_buffer_emit_word(&b->instructions, label);404}405406void407spirv_builder_return(struct spirv_builder *b)408{409spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);410spirv_buffer_emit_word(&b->instructions, SpvOpReturn | (1 << 16));411}412413SpvId414spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type,415SpvId pointer)416{417return spirv_builder_emit_unop(b, SpvOpLoad, result_type, pointer);418}419420void421spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object)422{423spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);424spirv_buffer_emit_word(&b->instructions, SpvOpStore | (3 << 16));425spirv_buffer_emit_word(&b->instructions, pointer);426spirv_buffer_emit_word(&b->instructions, object);427}428429void430spirv_builder_emit_atomic_store(struct spirv_builder *b, SpvId pointer, SpvScope scope,431SpvMemorySemanticsMask semantics, SpvId object)432{433spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);434spirv_buffer_emit_word(&b->instructions, SpvOpAtomicStore | (5 << 16));435spirv_buffer_emit_word(&b->instructions, pointer);436spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));437spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));438spirv_buffer_emit_word(&b->instructions, object);439}440441SpvId442spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,443SpvId base, const SpvId indexes[],444size_t num_indexes)445{446assert(base);447assert(result_type);448SpvId result = spirv_builder_new_id(b);449450int words = 4 + num_indexes;451spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);452spirv_buffer_emit_word(&b->instructions, SpvOpAccessChain | (words << 16));453spirv_buffer_emit_word(&b->instructions, result_type);454spirv_buffer_emit_word(&b->instructions, result);455spirv_buffer_emit_word(&b->instructions, base);456for (int i = 0; i < num_indexes; ++i) {457assert(indexes[i]);458spirv_buffer_emit_word(&b->instructions, indexes[i]);459}460return result;461}462463void464spirv_builder_emit_interlock(struct spirv_builder *b, bool end)465{466spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);467spirv_buffer_emit_word(&b->instructions, (end ? SpvOpEndInvocationInterlockEXT : SpvOpBeginInvocationInterlockEXT) | (1 << 16));468}469470471SpvId472spirv_builder_emit_unop_const(struct spirv_builder *b, SpvOp op, SpvId result_type, uint64_t operand)473{474SpvId result = spirv_builder_new_id(b);475spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);476spirv_buffer_emit_word(&b->instructions, op | (4 << 16));477spirv_buffer_emit_word(&b->instructions, result_type);478spirv_buffer_emit_word(&b->instructions, result);479spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, operand));480return result;481}482483SpvId484spirv_builder_emit_unop(struct spirv_builder *b, SpvOp op, SpvId result_type,485SpvId operand)486{487SpvId result = spirv_builder_new_id(b);488spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);489spirv_buffer_emit_word(&b->instructions, op | (4 << 16));490spirv_buffer_emit_word(&b->instructions, result_type);491spirv_buffer_emit_word(&b->instructions, result);492spirv_buffer_emit_word(&b->instructions, operand);493return result;494}495496SpvId497spirv_builder_emit_binop(struct spirv_builder *b, SpvOp op, SpvId result_type,498SpvId operand0, SpvId operand1)499{500SpvId result = spirv_builder_new_id(b);501spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);502spirv_buffer_emit_word(&b->instructions, op | (5 << 16));503spirv_buffer_emit_word(&b->instructions, result_type);504spirv_buffer_emit_word(&b->instructions, result);505spirv_buffer_emit_word(&b->instructions, operand0);506spirv_buffer_emit_word(&b->instructions, operand1);507return result;508}509510SpvId511spirv_builder_emit_triop(struct spirv_builder *b, SpvOp op, SpvId result_type,512SpvId operand0, SpvId operand1, SpvId operand2)513{514SpvId result = spirv_builder_new_id(b);515spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6);516spirv_buffer_emit_word(&b->instructions, op | (6 << 16));517spirv_buffer_emit_word(&b->instructions, result_type);518spirv_buffer_emit_word(&b->instructions, result);519spirv_buffer_emit_word(&b->instructions, operand0);520spirv_buffer_emit_word(&b->instructions, operand1);521spirv_buffer_emit_word(&b->instructions, operand2);522return result;523}524525SpvId526spirv_builder_emit_quadop(struct spirv_builder *b, SpvOp op, SpvId result_type,527SpvId operand0, SpvId operand1, SpvId operand2, SpvId operand3)528{529SpvId result = spirv_builder_new_id(b);530spirv_buffer_prepare(&b->instructions, b->mem_ctx, 7);531spirv_buffer_emit_word(&b->instructions, op | (7 << 16));532spirv_buffer_emit_word(&b->instructions, result_type);533spirv_buffer_emit_word(&b->instructions, result);534spirv_buffer_emit_word(&b->instructions, operand0);535spirv_buffer_emit_word(&b->instructions, operand1);536spirv_buffer_emit_word(&b->instructions, operand2);537spirv_buffer_emit_word(&b->instructions, operand3);538return result;539}540541SpvId542spirv_builder_emit_hexop(struct spirv_builder *b, SpvOp op, SpvId result_type,543SpvId operand0, SpvId operand1, SpvId operand2, SpvId operand3,544SpvId operand4, SpvId operand5)545{546SpvId result = spirv_builder_new_id(b);547spirv_buffer_prepare(&b->instructions, b->mem_ctx, 9);548spirv_buffer_emit_word(&b->instructions, op | (9 << 16));549spirv_buffer_emit_word(&b->instructions, result_type);550spirv_buffer_emit_word(&b->instructions, result);551spirv_buffer_emit_word(&b->instructions, operand0);552spirv_buffer_emit_word(&b->instructions, operand1);553spirv_buffer_emit_word(&b->instructions, operand2);554spirv_buffer_emit_word(&b->instructions, operand3);555spirv_buffer_emit_word(&b->instructions, operand4);556spirv_buffer_emit_word(&b->instructions, operand5);557return result;558}559560SpvId561spirv_builder_emit_composite_extract(struct spirv_builder *b, SpvId result_type,562SpvId composite, const uint32_t indexes[],563size_t num_indexes)564{565SpvId result = spirv_builder_new_id(b);566567assert(num_indexes > 0);568int words = 4 + num_indexes;569spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);570spirv_buffer_emit_word(&b->instructions,571SpvOpCompositeExtract | (words << 16));572spirv_buffer_emit_word(&b->instructions, result_type);573spirv_buffer_emit_word(&b->instructions, result);574spirv_buffer_emit_word(&b->instructions, composite);575for (int i = 0; i < num_indexes; ++i)576spirv_buffer_emit_word(&b->instructions, indexes[i]);577return result;578}579580SpvId581spirv_builder_emit_composite_construct(struct spirv_builder *b,582SpvId result_type,583const SpvId constituents[],584size_t num_constituents)585{586SpvId result = spirv_builder_new_id(b);587588assert(num_constituents > 0);589int words = 3 + num_constituents;590spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);591spirv_buffer_emit_word(&b->instructions,592SpvOpCompositeConstruct | (words << 16));593spirv_buffer_emit_word(&b->instructions, result_type);594spirv_buffer_emit_word(&b->instructions, result);595for (int i = 0; i < num_constituents; ++i)596spirv_buffer_emit_word(&b->instructions, constituents[i]);597return result;598}599600SpvId601spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,602SpvId vector_1, SpvId vector_2,603const uint32_t components[],604size_t num_components)605{606SpvId result = spirv_builder_new_id(b);607608assert(num_components > 0);609int words = 5 + num_components;610spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);611spirv_buffer_emit_word(&b->instructions, SpvOpVectorShuffle | (words << 16));612spirv_buffer_emit_word(&b->instructions, result_type);613spirv_buffer_emit_word(&b->instructions, result);614spirv_buffer_emit_word(&b->instructions, vector_1);615spirv_buffer_emit_word(&b->instructions, vector_2);616for (int i = 0; i < num_components; ++i)617spirv_buffer_emit_word(&b->instructions, components[i]);618return result;619}620621SpvId622spirv_builder_emit_vector_extract(struct spirv_builder *b, SpvId result_type,623SpvId vector_1,624uint32_t component)625{626SpvId result = spirv_builder_new_id(b);627628int words = 5;629spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);630spirv_buffer_emit_word(&b->instructions, SpvOpVectorExtractDynamic | (words << 16));631spirv_buffer_emit_word(&b->instructions, result_type);632spirv_buffer_emit_word(&b->instructions, result);633spirv_buffer_emit_word(&b->instructions, vector_1);634spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, component));635return result;636}637638SpvId639spirv_builder_emit_vector_insert(struct spirv_builder *b, SpvId result_type,640SpvId vector_1,641SpvId component,642uint32_t index)643{644SpvId result = spirv_builder_new_id(b);645646int words = 6;647spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);648spirv_buffer_emit_word(&b->instructions, SpvOpVectorInsertDynamic | (words << 16));649spirv_buffer_emit_word(&b->instructions, result_type);650spirv_buffer_emit_word(&b->instructions, result);651spirv_buffer_emit_word(&b->instructions, vector_1);652spirv_buffer_emit_word(&b->instructions, component);653spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, index));654return result;655}656657void658spirv_builder_emit_branch(struct spirv_builder *b, SpvId label)659{660spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);661spirv_buffer_emit_word(&b->instructions, SpvOpBranch | (2 << 16));662spirv_buffer_emit_word(&b->instructions, label);663}664665void666spirv_builder_emit_selection_merge(struct spirv_builder *b, SpvId merge_block,667SpvSelectionControlMask selection_control)668{669spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);670spirv_buffer_emit_word(&b->instructions, SpvOpSelectionMerge | (3 << 16));671spirv_buffer_emit_word(&b->instructions, merge_block);672spirv_buffer_emit_word(&b->instructions, selection_control);673}674675void676spirv_builder_loop_merge(struct spirv_builder *b, SpvId merge_block,677SpvId cont_target, SpvLoopControlMask loop_control)678{679spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);680spirv_buffer_emit_word(&b->instructions, SpvOpLoopMerge | (4 << 16));681spirv_buffer_emit_word(&b->instructions, merge_block);682spirv_buffer_emit_word(&b->instructions, cont_target);683spirv_buffer_emit_word(&b->instructions, loop_control);684}685686void687spirv_builder_emit_branch_conditional(struct spirv_builder *b, SpvId condition,688SpvId true_label, SpvId false_label)689{690spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);691spirv_buffer_emit_word(&b->instructions, SpvOpBranchConditional | (4 << 16));692spirv_buffer_emit_word(&b->instructions, condition);693spirv_buffer_emit_word(&b->instructions, true_label);694spirv_buffer_emit_word(&b->instructions, false_label);695}696697SpvId698spirv_builder_emit_phi(struct spirv_builder *b, SpvId result_type,699size_t num_vars, size_t *position)700{701SpvId result = spirv_builder_new_id(b);702703assert(num_vars > 0);704int words = 3 + 2 * num_vars;705spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);706spirv_buffer_emit_word(&b->instructions, SpvOpPhi | (words << 16));707spirv_buffer_emit_word(&b->instructions, result_type);708spirv_buffer_emit_word(&b->instructions, result);709*position = b->instructions.num_words;710for (int i = 0; i < 2 * num_vars; ++i)711spirv_buffer_emit_word(&b->instructions, 0);712return result;713}714715void716spirv_builder_set_phi_operand(struct spirv_builder *b, size_t position,717size_t index, SpvId variable, SpvId parent)718{719b->instructions.words[position + index * 2 + 0] = variable;720b->instructions.words[position + index * 2 + 1] = parent;721}722723void724spirv_builder_emit_kill(struct spirv_builder *b)725{726spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);727spirv_buffer_emit_word(&b->instructions, SpvOpKill | (1 << 16));728}729730SpvId731spirv_builder_emit_vote(struct spirv_builder *b, SpvOp op, SpvId src)732{733return spirv_builder_emit_binop(b, op, spirv_builder_type_bool(b),734spirv_builder_const_uint(b, 32, SpvScopeWorkgroup), src);735}736737SpvId738spirv_builder_emit_image_sample(struct spirv_builder *b,739SpvId result_type,740SpvId sampled_image,741SpvId coordinate,742bool proj,743SpvId lod,744SpvId bias,745SpvId dref,746SpvId dx,747SpvId dy,748SpvId const_offset,749SpvId offset)750{751SpvId result = spirv_builder_new_id(b);752753int opcode = SpvOpImageSampleImplicitLod;754int operands = 5;755if (proj)756opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;757if (lod || (dx && dy))758opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;759if (dref) {760opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;761operands++;762}763764SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;765SpvId extra_operands[5];766int num_extra_operands = 1;767if (bias) {768extra_operands[num_extra_operands++] = bias;769operand_mask |= SpvImageOperandsBiasMask;770}771if (lod) {772extra_operands[num_extra_operands++] = lod;773operand_mask |= SpvImageOperandsLodMask;774} else if (dx && dy) {775extra_operands[num_extra_operands++] = dx;776extra_operands[num_extra_operands++] = dy;777operand_mask |= SpvImageOperandsGradMask;778}779assert(!(const_offset && offset));780if (const_offset) {781extra_operands[num_extra_operands++] = const_offset;782operand_mask |= SpvImageOperandsConstOffsetMask;783} else if (offset) {784extra_operands[num_extra_operands++] = offset;785operand_mask |= SpvImageOperandsOffsetMask;786}787788/* finalize num_extra_operands / extra_operands */789extra_operands[0] = operand_mask;790791spirv_buffer_prepare(&b->instructions, b->mem_ctx, operands + num_extra_operands);792spirv_buffer_emit_word(&b->instructions, opcode | ((operands + num_extra_operands) << 16));793spirv_buffer_emit_word(&b->instructions, result_type);794spirv_buffer_emit_word(&b->instructions, result);795spirv_buffer_emit_word(&b->instructions, sampled_image);796spirv_buffer_emit_word(&b->instructions, coordinate);797if (dref)798spirv_buffer_emit_word(&b->instructions, dref);799for (int i = 0; i < num_extra_operands; ++i)800spirv_buffer_emit_word(&b->instructions, extra_operands[i]);801return result;802}803804SpvId805spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,806SpvId sampled_image)807{808SpvId result = spirv_builder_new_id(b);809spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);810spirv_buffer_emit_word(&b->instructions, SpvOpImage | (4 << 16));811spirv_buffer_emit_word(&b->instructions, result_type);812spirv_buffer_emit_word(&b->instructions, result);813spirv_buffer_emit_word(&b->instructions, sampled_image);814return result;815}816817SpvId818spirv_builder_emit_image_texel_pointer(struct spirv_builder *b,819SpvId result_type,820SpvId image,821SpvId coordinate,822SpvId sample)823{824SpvId pointer_type = spirv_builder_type_pointer(b,825SpvStorageClassImage,826result_type);827return spirv_builder_emit_triop(b, SpvOpImageTexelPointer, pointer_type, image, coordinate, sample);828}829830SpvId831spirv_builder_emit_image_read(struct spirv_builder *b,832SpvId result_type,833SpvId image,834SpvId coordinate,835SpvId lod,836SpvId sample,837SpvId offset)838{839SpvId result = spirv_builder_new_id(b);840841SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;842SpvId extra_operands[5];843int num_extra_operands = 1;844if (lod) {845extra_operands[num_extra_operands++] = lod;846operand_mask |= SpvImageOperandsLodMask;847}848if (sample) {849extra_operands[num_extra_operands++] = sample;850operand_mask |= SpvImageOperandsSampleMask;851}852if (offset) {853extra_operands[num_extra_operands++] = offset;854operand_mask |= SpvImageOperandsOffsetMask;855}856/* finalize num_extra_operands / extra_operands */857extra_operands[0] = operand_mask;858859spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);860spirv_buffer_emit_word(&b->instructions, SpvOpImageRead |861((5 + num_extra_operands) << 16));862spirv_buffer_emit_word(&b->instructions, result_type);863spirv_buffer_emit_word(&b->instructions, result);864spirv_buffer_emit_word(&b->instructions, image);865spirv_buffer_emit_word(&b->instructions, coordinate);866for (int i = 0; i < num_extra_operands; ++i)867spirv_buffer_emit_word(&b->instructions, extra_operands[i]);868return result;869}870871void872spirv_builder_emit_image_write(struct spirv_builder *b,873SpvId image,874SpvId coordinate,875SpvId texel,876SpvId lod,877SpvId sample,878SpvId offset)879{880SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;881SpvId extra_operands[5];882int num_extra_operands = 1;883if (lod) {884extra_operands[num_extra_operands++] = lod;885operand_mask |= SpvImageOperandsLodMask;886}887if (sample) {888extra_operands[num_extra_operands++] = sample;889operand_mask |= SpvImageOperandsSampleMask;890}891if (offset) {892extra_operands[num_extra_operands++] = offset;893operand_mask |= SpvImageOperandsOffsetMask;894}895/* finalize num_extra_operands / extra_operands */896extra_operands[0] = operand_mask;897898spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4 + num_extra_operands);899spirv_buffer_emit_word(&b->instructions, SpvOpImageWrite |900((4 + num_extra_operands) << 16));901spirv_buffer_emit_word(&b->instructions, image);902spirv_buffer_emit_word(&b->instructions, coordinate);903spirv_buffer_emit_word(&b->instructions, texel);904for (int i = 0; i < num_extra_operands; ++i)905spirv_buffer_emit_word(&b->instructions, extra_operands[i]);906}907908SpvId909spirv_builder_emit_image_gather(struct spirv_builder *b,910SpvId result_type,911SpvId image,912SpvId coordinate,913SpvId component,914SpvId lod,915SpvId sample,916SpvId const_offset,917SpvId offset,918SpvId dref)919{920SpvId result = spirv_builder_new_id(b);921SpvId op = SpvOpImageGather;922923SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;924SpvId extra_operands[4];925int num_extra_operands = 1;926if (lod) {927extra_operands[num_extra_operands++] = lod;928operand_mask |= SpvImageOperandsLodMask;929}930if (sample) {931extra_operands[num_extra_operands++] = sample;932operand_mask |= SpvImageOperandsSampleMask;933}934assert(!(const_offset && offset));935if (const_offset) {936extra_operands[num_extra_operands++] = const_offset;937operand_mask |= SpvImageOperandsConstOffsetMask;938} else if (offset) {939extra_operands[num_extra_operands++] = offset;940operand_mask |= SpvImageOperandsOffsetMask;941}942if (dref)943op = SpvOpImageDrefGather;944/* finalize num_extra_operands / extra_operands */945extra_operands[0] = operand_mask;946947spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6 + num_extra_operands);948spirv_buffer_emit_word(&b->instructions, op |949((6 + num_extra_operands) << 16));950spirv_buffer_emit_word(&b->instructions, result_type);951spirv_buffer_emit_word(&b->instructions, result);952spirv_buffer_emit_word(&b->instructions, image);953spirv_buffer_emit_word(&b->instructions, coordinate);954if (dref)955spirv_buffer_emit_word(&b->instructions, dref);956else957spirv_buffer_emit_word(&b->instructions, component);958for (int i = 0; i < num_extra_operands; ++i)959spirv_buffer_emit_word(&b->instructions, extra_operands[i]);960return result;961}962963SpvId964spirv_builder_emit_image_fetch(struct spirv_builder *b,965SpvId result_type,966SpvId image,967SpvId coordinate,968SpvId lod,969SpvId sample,970SpvId const_offset,971SpvId offset)972{973SpvId result = spirv_builder_new_id(b);974975SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;976SpvId extra_operands[4];977int num_extra_operands = 1;978if (lod) {979extra_operands[num_extra_operands++] = lod;980operand_mask |= SpvImageOperandsLodMask;981}982if (sample) {983extra_operands[num_extra_operands++] = sample;984operand_mask |= SpvImageOperandsSampleMask;985}986assert(!(const_offset && offset));987if (const_offset) {988extra_operands[num_extra_operands++] = const_offset;989operand_mask |= SpvImageOperandsConstOffsetMask;990} else if (offset) {991extra_operands[num_extra_operands++] = offset;992operand_mask |= SpvImageOperandsOffsetMask;993}994995/* finalize num_extra_operands / extra_operands */996extra_operands[0] = operand_mask;997998spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);999spirv_buffer_emit_word(&b->instructions, SpvOpImageFetch |1000((5 + num_extra_operands) << 16));1001spirv_buffer_emit_word(&b->instructions, result_type);1002spirv_buffer_emit_word(&b->instructions, result);1003spirv_buffer_emit_word(&b->instructions, image);1004spirv_buffer_emit_word(&b->instructions, coordinate);1005for (int i = 0; i < num_extra_operands; ++i)1006spirv_buffer_emit_word(&b->instructions, extra_operands[i]);1007return result;1008}10091010SpvId1011spirv_builder_emit_image_query_size(struct spirv_builder *b,1012SpvId result_type,1013SpvId image,1014SpvId lod)1015{1016int opcode = SpvOpImageQuerySize;1017int words = 4;1018if (lod) {1019words++;1020opcode = SpvOpImageQuerySizeLod;1021}10221023SpvId result = spirv_builder_new_id(b);1024spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);1025spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));1026spirv_buffer_emit_word(&b->instructions, result_type);1027spirv_buffer_emit_word(&b->instructions, result);1028spirv_buffer_emit_word(&b->instructions, image);10291030if (lod)1031spirv_buffer_emit_word(&b->instructions, lod);10321033return result;1034}10351036SpvId1037spirv_builder_emit_image_query_levels(struct spirv_builder *b,1038SpvId result_type,1039SpvId image)1040{1041return spirv_builder_emit_unop(b, SpvOpImageQueryLevels, result_type, image);1042}10431044SpvId1045spirv_builder_emit_image_query_lod(struct spirv_builder *b,1046SpvId result_type,1047SpvId image,1048SpvId coords)1049{1050int opcode = SpvOpImageQueryLod;1051int words = 5;10521053SpvId result = spirv_builder_new_id(b);1054spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);1055spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));1056spirv_buffer_emit_word(&b->instructions, result_type);1057spirv_buffer_emit_word(&b->instructions, result);1058spirv_buffer_emit_word(&b->instructions, image);1059spirv_buffer_emit_word(&b->instructions, coords);10601061return result;1062}10631064SpvId1065spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,1066SpvId set, uint32_t instruction,1067const SpvId *args, size_t num_args)1068{1069SpvId result = spirv_builder_new_id(b);10701071int words = 5 + num_args;1072spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);1073spirv_buffer_emit_word(&b->instructions, SpvOpExtInst | (words << 16));1074spirv_buffer_emit_word(&b->instructions, result_type);1075spirv_buffer_emit_word(&b->instructions, result);1076spirv_buffer_emit_word(&b->instructions, set);1077spirv_buffer_emit_word(&b->instructions, instruction);1078for (int i = 0; i < num_args; ++i)1079spirv_buffer_emit_word(&b->instructions, args[i]);1080return result;1081}10821083struct spirv_type {1084SpvOp op;1085uint32_t args[8];1086size_t num_args;10871088SpvId type;1089};10901091static uint32_t1092non_aggregate_type_hash(const void *arg)1093{1094const struct spirv_type *type = arg;10951096uint32_t hash = 0;1097hash = XXH32(&type->op, sizeof(type->op), hash);1098hash = XXH32(type->args, sizeof(uint32_t) * type->num_args, hash);1099return hash;1100}11011102static bool1103non_aggregate_type_equals(const void *a, const void *b)1104{1105const struct spirv_type *ta = a, *tb = b;11061107if (ta->op != tb->op)1108return false;11091110assert(ta->num_args == tb->num_args);1111return memcmp(ta->args, tb->args, sizeof(uint32_t) * ta->num_args) == 0;1112}11131114static SpvId1115get_type_def(struct spirv_builder *b, SpvOp op, const uint32_t args[],1116size_t num_args)1117{1118/* According to the SPIR-V specification:1119*1120* "Two different type <id>s form, by definition, two different types. It1121* is valid to declare multiple aggregate type <id>s having the same1122* opcode and operands. This is to allow multiple instances of aggregate1123* types with the same structure to be decorated differently. (Different1124* decorations are not required; two different aggregate type <id>s are1125* allowed to have identical declarations and decorations, and will still1126* be two different types.) Non-aggregate types are different: It is1127* invalid to declare multiple type <id>s for the same scalar, vector, or1128* matrix type. That is, non-aggregate type declarations must all have1129* different opcodes or operands. (Note that non-aggregate types cannot1130* be decorated in ways that affect their type.)"1131*1132* ..so, we need to prevent the same non-aggregate type to be re-defined1133* with a new <id>. We do this by putting the definitions in a hash-map, so1134* we can easily look up and reuse them.1135*/11361137struct spirv_type key;1138assert(num_args <= ARRAY_SIZE(key.args));1139key.op = op;1140memcpy(&key.args, args, sizeof(uint32_t) * num_args);1141key.num_args = num_args;11421143struct hash_entry *entry;1144if (b->types) {1145entry = _mesa_hash_table_search(b->types, &key);1146if (entry)1147return ((struct spirv_type *)entry->data)->type;1148} else {1149b->types = _mesa_hash_table_create(b->mem_ctx,1150non_aggregate_type_hash,1151non_aggregate_type_equals);1152assert(b->types);1153}11541155struct spirv_type *type = rzalloc(b->mem_ctx, struct spirv_type);1156if (!type)1157return 0;11581159type->op = op;1160memcpy(&type->args, args, sizeof(uint32_t) * num_args);1161type->num_args = num_args;11621163type->type = spirv_builder_new_id(b);1164spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 2 + num_args);1165spirv_buffer_emit_word(&b->types_const_defs, op | ((2 + num_args) << 16));1166spirv_buffer_emit_word(&b->types_const_defs, type->type);1167for (int i = 0; i < num_args; ++i)1168spirv_buffer_emit_word(&b->types_const_defs, args[i]);11691170entry = _mesa_hash_table_insert(b->types, type, type);1171assert(entry);11721173return ((struct spirv_type *)entry->data)->type;1174}11751176SpvId1177spirv_builder_type_void(struct spirv_builder *b)1178{1179return get_type_def(b, SpvOpTypeVoid, NULL, 0);1180}11811182SpvId1183spirv_builder_type_bool(struct spirv_builder *b)1184{1185return get_type_def(b, SpvOpTypeBool, NULL, 0);1186}11871188SpvId1189spirv_builder_type_int(struct spirv_builder *b, unsigned width)1190{1191uint32_t args[] = { width, 1 };1192return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));1193}11941195SpvId1196spirv_builder_type_uint(struct spirv_builder *b, unsigned width)1197{1198uint32_t args[] = { width, 0 };1199return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));1200}12011202SpvId1203spirv_builder_type_float(struct spirv_builder *b, unsigned width)1204{1205uint32_t args[] = { width };1206return get_type_def(b, SpvOpTypeFloat, args, ARRAY_SIZE(args));1207}12081209SpvId1210spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,1211SpvDim dim, bool depth, bool arrayed, bool ms,1212unsigned sampled, SpvImageFormat image_format)1213{1214assert(sampled < 3);1215uint32_t args[] = {1216sampled_type, dim, depth ? 1 : 0, arrayed ? 1 : 0, ms ? 1 : 0, sampled,1217image_format1218};1219return get_type_def(b, SpvOpTypeImage, args, ARRAY_SIZE(args));1220}12211222SpvId1223spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type)1224{1225uint32_t args[] = { image_type };1226return get_type_def(b, SpvOpTypeSampledImage, args, ARRAY_SIZE(args));1227}12281229SpvId1230spirv_builder_type_pointer(struct spirv_builder *b,1231SpvStorageClass storage_class, SpvId type)1232{1233uint32_t args[] = { storage_class, type };1234return get_type_def(b, SpvOpTypePointer, args, ARRAY_SIZE(args));1235}12361237SpvId1238spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,1239unsigned component_count)1240{1241assert(component_count > 1);1242uint32_t args[] = { component_type, component_count };1243return get_type_def(b, SpvOpTypeVector, args, ARRAY_SIZE(args));1244}12451246SpvId1247spirv_builder_type_matrix(struct spirv_builder *b, SpvId component_type,1248unsigned component_count)1249{1250assert(component_count > 1);1251uint32_t args[] = { component_type, component_count };1252return get_type_def(b, SpvOpTypeMatrix, args, ARRAY_SIZE(args));1253}12541255SpvId1256spirv_builder_type_runtime_array(struct spirv_builder *b, SpvId component_type)1257{1258SpvId type = spirv_builder_new_id(b);1259spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3);1260spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeRuntimeArray | (3 << 16));1261spirv_buffer_emit_word(&b->types_const_defs, type);1262spirv_buffer_emit_word(&b->types_const_defs, component_type);1263return type;1264}12651266SpvId1267spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,1268SpvId length)1269{1270SpvId type = spirv_builder_new_id(b);1271spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 4);1272spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeArray | (4 << 16));1273spirv_buffer_emit_word(&b->types_const_defs, type);1274spirv_buffer_emit_word(&b->types_const_defs, component_type);1275spirv_buffer_emit_word(&b->types_const_defs, length);1276return type;1277}12781279SpvId1280spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],1281size_t num_member_types)1282{1283int words = 2 + num_member_types;1284SpvId type = spirv_builder_new_id(b);1285spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);1286spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeStruct | (words << 16));1287spirv_buffer_emit_word(&b->types_const_defs, type);1288for (int i = 0; i < num_member_types; ++i)1289spirv_buffer_emit_word(&b->types_const_defs, member_types[i]);1290return type;1291}12921293SpvId1294spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,1295const SpvId parameter_types[],1296size_t num_parameter_types)1297{1298int words = 3 + num_parameter_types;1299SpvId type = spirv_builder_new_id(b);1300spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);1301spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeFunction | (words << 16));1302spirv_buffer_emit_word(&b->types_const_defs, type);1303spirv_buffer_emit_word(&b->types_const_defs, return_type);1304for (int i = 0; i < num_parameter_types; ++i)1305spirv_buffer_emit_word(&b->types_const_defs, parameter_types[i]);1306return type;1307}13081309struct spirv_const {1310SpvOp op, type;1311uint32_t args[8];1312size_t num_args;13131314SpvId result;1315};13161317static uint32_t1318const_hash(const void *arg)1319{1320const struct spirv_const *key = arg;13211322uint32_t hash = 0;1323hash = XXH32(&key->op, sizeof(key->op), hash);1324hash = XXH32(&key->type, sizeof(key->type), hash);1325hash = XXH32(key->args, sizeof(uint32_t) * key->num_args, hash);1326return hash;1327}13281329static bool1330const_equals(const void *a, const void *b)1331{1332const struct spirv_const *ca = a, *cb = b;13331334if (ca->op != cb->op ||1335ca->type != cb->type)1336return false;13371338assert(ca->num_args == cb->num_args);1339return memcmp(ca->args, cb->args, sizeof(uint32_t) * ca->num_args) == 0;1340}13411342static SpvId1343get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,1344const uint32_t args[], size_t num_args)1345{1346struct spirv_const key;1347assert(num_args <= ARRAY_SIZE(key.args));1348key.op = op;1349key.type = type;1350memcpy(&key.args, args, sizeof(uint32_t) * num_args);1351key.num_args = num_args;13521353struct hash_entry *entry;1354if (b->consts) {1355entry = _mesa_hash_table_search(b->consts, &key);1356if (entry)1357return ((struct spirv_const *)entry->data)->result;1358} else {1359b->consts = _mesa_hash_table_create(b->mem_ctx, const_hash,1360const_equals);1361assert(b->consts);1362}13631364struct spirv_const *cnst = rzalloc(b->mem_ctx, struct spirv_const);1365if (!cnst)1366return 0;13671368cnst->op = op;1369cnst->type = type;1370memcpy(&cnst->args, args, sizeof(uint32_t) * num_args);1371cnst->num_args = num_args;13721373cnst->result = spirv_builder_new_id(b);1374spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3 + num_args);1375spirv_buffer_emit_word(&b->types_const_defs, op | ((3 + num_args) << 16));1376spirv_buffer_emit_word(&b->types_const_defs, type);1377spirv_buffer_emit_word(&b->types_const_defs, cnst->result);1378for (int i = 0; i < num_args; ++i)1379spirv_buffer_emit_word(&b->types_const_defs, args[i]);13801381entry = _mesa_hash_table_insert(b->consts, cnst, cnst);1382assert(entry);13831384return ((struct spirv_const *)entry->data)->result;1385}13861387static SpvId1388emit_constant_32(struct spirv_builder *b, SpvId type, uint32_t val)1389{1390uint32_t args[] = { val };1391return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));1392}13931394static SpvId1395emit_constant_64(struct spirv_builder *b, SpvId type, uint64_t val)1396{1397uint32_t args[] = { val & UINT32_MAX, val >> 32 };1398return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));1399}14001401SpvId1402spirv_builder_const_bool(struct spirv_builder *b, bool val)1403{1404return get_const_def(b, val ? SpvOpConstantTrue : SpvOpConstantFalse,1405spirv_builder_type_bool(b), NULL, 0);1406}14071408SpvId1409spirv_builder_const_int(struct spirv_builder *b, int width, int64_t val)1410{1411assert(width >= 16);1412SpvId type = spirv_builder_type_int(b, width);1413if (width <= 32)1414return emit_constant_32(b, type, val);1415else1416return emit_constant_64(b, type, val);1417}14181419SpvId1420spirv_builder_const_uint(struct spirv_builder *b, int width, uint64_t val)1421{1422assert(width >= 16);1423SpvId type = spirv_builder_type_uint(b, width);1424if (width <= 32)1425return emit_constant_32(b, type, val);1426else1427return emit_constant_64(b, type, val);1428}14291430SpvId1431spirv_builder_spec_const_uint(struct spirv_builder *b, int width)1432{1433assert(width <= 32);1434return spirv_builder_emit_unop(b, SpvOpSpecConstant, spirv_builder_type_uint(b, width), 0);1435}14361437SpvId1438spirv_builder_const_float(struct spirv_builder *b, int width, double val)1439{1440assert(width >= 16);1441SpvId type = spirv_builder_type_float(b, width);1442if (width == 16)1443return emit_constant_32(b, type, _mesa_float_to_half(val));1444else if (width == 32)1445return emit_constant_32(b, type, u_bitcast_f2u(val));1446else if (width == 64)1447return emit_constant_64(b, type, u_bitcast_d2u(val));14481449unreachable("unhandled float-width");1450}14511452SpvId1453spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,1454const SpvId constituents[],1455size_t num_constituents)1456{1457return get_const_def(b, SpvOpConstantComposite, result_type,1458(const uint32_t *)constituents,1459num_constituents);1460}14611462SpvId1463spirv_builder_spec_const_composite(struct spirv_builder *b, SpvId result_type,1464const SpvId constituents[],1465size_t num_constituents)1466{1467SpvId result = spirv_builder_new_id(b);14681469assert(num_constituents > 0);1470int words = 3 + num_constituents;1471spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);1472spirv_buffer_emit_word(&b->instructions,1473SpvOpSpecConstantComposite | (words << 16));1474spirv_buffer_emit_word(&b->instructions, result_type);1475spirv_buffer_emit_word(&b->instructions, result);1476for (int i = 0; i < num_constituents; ++i)1477spirv_buffer_emit_word(&b->instructions, constituents[i]);1478return result;1479}14801481SpvId1482spirv_builder_emit_var(struct spirv_builder *b, SpvId type,1483SpvStorageClass storage_class)1484{1485assert(storage_class != SpvStorageClassGeneric);1486struct spirv_buffer *buf = storage_class != SpvStorageClassFunction ?1487&b->types_const_defs : &b->instructions;14881489SpvId ret = spirv_builder_new_id(b);1490spirv_buffer_prepare(buf, b->mem_ctx, 4);1491spirv_buffer_emit_word(buf, SpvOpVariable | (4 << 16));1492spirv_buffer_emit_word(buf, type);1493spirv_buffer_emit_word(buf, ret);1494spirv_buffer_emit_word(buf, storage_class);1495return ret;1496}14971498void1499spirv_builder_emit_memory_barrier(struct spirv_builder *b, SpvScope scope, SpvMemorySemanticsMask semantics)1500{1501spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);1502spirv_buffer_emit_word(&b->instructions, SpvOpMemoryBarrier | (3 << 16));1503spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));1504spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));1505}15061507void1508spirv_builder_emit_control_barrier(struct spirv_builder *b, SpvScope scope, SpvScope mem_scope, SpvMemorySemanticsMask semantics)1509{1510spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);1511spirv_buffer_emit_word(&b->instructions, SpvOpControlBarrier | (4 << 16));1512spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));1513spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, mem_scope));1514spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));1515}15161517SpvId1518spirv_builder_import(struct spirv_builder *b, const char *name)1519{1520SpvId result = spirv_builder_new_id(b);1521size_t pos = b->imports.num_words;1522spirv_buffer_prepare(&b->imports, b->mem_ctx, 2);1523spirv_buffer_emit_word(&b->imports, SpvOpExtInstImport);1524spirv_buffer_emit_word(&b->imports, result);1525int len = spirv_buffer_emit_string(&b->imports, b->mem_ctx, name);1526b->imports.words[pos] |= (2 + len) << 16;1527return result;1528}15291530size_t1531spirv_builder_get_num_words(struct spirv_builder *b)1532{1533const size_t header_size = 5;1534const size_t caps_size = b->caps ? b->caps->entries * 2 : 0;1535return header_size + caps_size +1536b->extensions.num_words +1537b->imports.num_words +1538b->memory_model.num_words +1539b->entry_points.num_words +1540b->exec_modes.num_words +1541b->debug_names.num_words +1542b->decorations.num_words +1543b->types_const_defs.num_words +1544b->instructions.num_words;1545}15461547size_t1548spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,1549size_t num_words, uint32_t spirv_version)1550{1551assert(num_words >= spirv_builder_get_num_words(b));15521553size_t written = 0;1554words[written++] = SpvMagicNumber;1555words[written++] = spirv_version;1556words[written++] = 0;1557words[written++] = b->prev_id + 1;1558words[written++] = 0;15591560if (b->caps) {1561set_foreach(b->caps, entry) {1562words[written++] = SpvOpCapability | (2 << 16);1563words[written++] = (uintptr_t)entry->key;1564}1565}15661567const struct spirv_buffer *buffers[] = {1568&b->extensions,1569&b->imports,1570&b->memory_model,1571&b->entry_points,1572&b->exec_modes,1573&b->debug_names,1574&b->decorations,1575&b->types_const_defs,1576&b->instructions1577};15781579for (int i = 0; i < ARRAY_SIZE(buffers); ++i) {1580const struct spirv_buffer *buffer = buffers[i];1581for (int j = 0; j < buffer->num_words; ++j)1582words[written++] = buffer->words[j];1583}15841585assert(written == spirv_builder_get_num_words(b));1586return written;1587}158815891590