Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_link_uniform_blocks.c
4545 views
/*1* Copyright © 2019 Intel Corporation2*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* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* 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 NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "nir.h"24#include "gl_nir_linker.h"25#include "ir_uniform.h" /* for gl_uniform_storage */26#include "linker_util.h"27#include "main/mtypes.h"2829/**30* This file contains code to do a nir-based linking for uniform blocks. This31* includes ubos and ssbos.32*33* For the case of ARB_gl_spirv there are some differences compared with GLSL:34*35* 1. Linking doesn't use names: GLSL linking use names as core concept. But36* on SPIR-V, uniform block name, fields names, and other names are37* considered optional debug infor so could not be present. So the linking38* should work without it, and it is optional to not handle them at39* all. From ARB_gl_spirv spec.40*41* "19. How should the program interface query operations behave for program42* objects created from SPIR-V shaders?43*44* DISCUSSION: we previously said we didn't need reflection to work for45* SPIR-V shaders (at least for the first version), however we are left46* with specifying how it should "not work". The primary issue is that47* SPIR-V binaries are not required to have names associated with48* variables. They can be associated in debug information, but there is no49* requirement for that to be present, and it should not be relied upon.50*51* Options:52*53* <skip>54*55* C) Allow as much as possible to work "naturally". You can query for the56* number of active resources, and for details about them. Anything that57* doesn't query by name will work as expected. Queries for maximum length58* of names return one. Queries for anything "by name" return INVALID_INDEX59* (or -1). Querying the name property of a resource returns an empty60* string. This may allow many queries to work, but it's not clear how61* useful it would be if you can't actually know which specific variable62* you are retrieving information on. If everything is specified a-priori63* by location/binding/offset/index/component in the shader, this may be64* sufficient.65*66* RESOLVED. Pick (c), but also allow debug names to be returned if an67* implementation wants to."68*69* When linking SPIR-V shaders this implemention doesn't care for the names,70* as the main objective is functional, and not support optional debug71* features.72*73* 2. Terminology: this file handles both UBO and SSBO, including both as74* "uniform blocks" analogously to what is done in the GLSL (IR) path.75*76* From ARB_gl_spirv spec:77* "Mapping of Storage Classes:78* <skip>79* uniform blockN { ... } ...; -> Uniform, with Block decoration80* <skip>81* buffer blockN { ... } ...; -> Uniform, with BufferBlock decoration"82*83* 3. Explicit data: for the SPIR-V path the code assumes that all structure84* members have an Offset decoration, all arrays have an ArrayStride and85* all matrices have a MatrixStride, even for nested structures. That way86* we don’t have to worry about the different layout modes. This is87* explicitly required in the SPIR-V spec:88*89* "Composite objects in the UniformConstant, Uniform, and PushConstant90* Storage Classes must be explicitly laid out. The following apply to all91* the aggregate and matrix types describing such an object, recursively92* through their nested types:93*94* – Each structure-type member must have an Offset Decoration.95* – Each array type must have an ArrayStride Decoration.96* – Each structure-type member that is a matrix or array-of-matrices must97* have be decorated with a MatrixStride Decoration, and one of the98* RowMajor or ColMajor Decorations."99*100* Additionally, the structure members are expected to be presented in101* increasing offset order:102*103* "a structure has lower-numbered members appearing at smaller offsets than104* higher-numbered members"105*/106107enum block_type {108BLOCK_UBO,109BLOCK_SSBO110};111112/*113* It is worth to note that ARB_gl_spirv spec doesn't require us to do this114* validation, but at the same time, it allow us to do it. The following115* validation is easy and a nice-to-have.116*/117static bool118link_blocks_are_compatible(const struct gl_uniform_block *a,119const struct gl_uniform_block *b)120{121/*122* Names on ARB_gl_spirv are optional, so we are ignoring them. So123* meanwhile on the equivalent GLSL method the matching is done using the124* name, here we use the binding, that for SPIR-V binaries is explicit, and125* mandatory, from OpenGL 4.6 spec, section "7.4.2. SPIR-V Shader Interface126* Matching":127* "Uniform and shader storage block variables must also be decorated128* with a Binding"129*/130if (a->Binding != b->Binding)131return false;132133/* We are explicitly ignoring the names, so it would be good to check that134* this is happening.135*/136assert(a->Name == NULL);137assert(b->Name == NULL);138139if (a->NumUniforms != b->NumUniforms)140return false;141142if (a->_Packing != b->_Packing)143return false;144145if (a->_RowMajor != b->_RowMajor)146return false;147148for (unsigned i = 0; i < a->NumUniforms; i++) {149if (a->Uniforms[i].Type != b->Uniforms[i].Type)150return false;151152if (a->Uniforms[i].RowMajor != b->Uniforms[i].RowMajor)153return false;154155if (a->Uniforms[i].Offset != b->Uniforms[i].Offset)156return false;157158/* See comment on previous assert */159assert(a->Uniforms[i].Name == NULL);160assert(b->Uniforms[i].Name == NULL);161}162163return true;164}165166/**167* Merges a buffer block into an array of buffer blocks that may or may not168* already contain a copy of it.169*170* Returns the index of the block in the array (new if it was needed, or the171* index of the copy of it). -1 if there are two incompatible block172* definitions with the same binding.173*174*/175static int176link_cross_validate_uniform_block(void *mem_ctx,177struct gl_uniform_block **linked_blocks,178unsigned int *num_linked_blocks,179struct gl_uniform_block *new_block)180{181/* We first check if new_block was already linked */182for (unsigned int i = 0; i < *num_linked_blocks; i++) {183struct gl_uniform_block *old_block = &(*linked_blocks)[i];184185if (old_block->Binding == new_block->Binding)186return link_blocks_are_compatible(old_block, new_block) ? i : -1;187}188189*linked_blocks = reralloc(mem_ctx, *linked_blocks,190struct gl_uniform_block,191*num_linked_blocks + 1);192int linked_block_index = (*num_linked_blocks)++;193struct gl_uniform_block *linked_block = &(*linked_blocks)[linked_block_index];194195memcpy(linked_block, new_block, sizeof(*new_block));196linked_block->Uniforms = ralloc_array(*linked_blocks,197struct gl_uniform_buffer_variable,198linked_block->NumUniforms);199200memcpy(linked_block->Uniforms,201new_block->Uniforms,202sizeof(*linked_block->Uniforms) * linked_block->NumUniforms);203204return linked_block_index;205}206207208/**209* Accumulates the array of buffer blocks and checks that all definitions of210* blocks agree on their contents.211*/212static bool213nir_interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog,214enum block_type block_type)215{216int *interfaceBlockStageIndex[MESA_SHADER_STAGES];217struct gl_uniform_block *blks = NULL;218unsigned *num_blks = block_type == BLOCK_SSBO ? &prog->data->NumShaderStorageBlocks :219&prog->data->NumUniformBlocks;220221unsigned max_num_buffer_blocks = 0;222for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {223if (prog->_LinkedShaders[i]) {224if (block_type == BLOCK_SSBO) {225max_num_buffer_blocks +=226prog->_LinkedShaders[i]->Program->info.num_ssbos;227} else {228max_num_buffer_blocks +=229prog->_LinkedShaders[i]->Program->info.num_ubos;230}231}232}233234for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {235struct gl_linked_shader *sh = prog->_LinkedShaders[i];236237interfaceBlockStageIndex[i] = malloc(max_num_buffer_blocks * sizeof(int));238for (unsigned int j = 0; j < max_num_buffer_blocks; j++)239interfaceBlockStageIndex[i][j] = -1;240241if (sh == NULL)242continue;243244unsigned sh_num_blocks;245struct gl_uniform_block **sh_blks;246if (block_type == BLOCK_SSBO) {247sh_num_blocks = prog->_LinkedShaders[i]->Program->info.num_ssbos;248sh_blks = sh->Program->sh.ShaderStorageBlocks;249} else {250sh_num_blocks = prog->_LinkedShaders[i]->Program->info.num_ubos;251sh_blks = sh->Program->sh.UniformBlocks;252}253254for (unsigned int j = 0; j < sh_num_blocks; j++) {255int index = link_cross_validate_uniform_block(prog->data, &blks,256num_blks, sh_blks[j]);257258if (index == -1) {259/* We use the binding as we are ignoring the names */260linker_error(prog, "buffer block with binding `%i' has mismatching "261"definitions\n", sh_blks[j]->Binding);262263for (unsigned k = 0; k <= i; k++) {264free(interfaceBlockStageIndex[k]);265}266267/* Reset the block count. This will help avoid various segfaults268* from api calls that assume the array exists due to the count269* being non-zero.270*/271*num_blks = 0;272return false;273}274275interfaceBlockStageIndex[i][index] = j;276}277}278279/* Update per stage block pointers to point to the program list.280*/281for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {282for (unsigned j = 0; j < *num_blks; j++) {283int stage_index = interfaceBlockStageIndex[i][j];284285if (stage_index != -1) {286struct gl_linked_shader *sh = prog->_LinkedShaders[i];287288struct gl_uniform_block **sh_blks = block_type == BLOCK_SSBO ?289sh->Program->sh.ShaderStorageBlocks :290sh->Program->sh.UniformBlocks;291292blks[j].stageref |= sh_blks[stage_index]->stageref;293sh_blks[stage_index] = &blks[j];294}295}296}297298for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {299free(interfaceBlockStageIndex[i]);300}301302if (block_type == BLOCK_SSBO)303prog->data->ShaderStorageBlocks = blks;304else {305prog->data->NumUniformBlocks = *num_blks;306prog->data->UniformBlocks = blks;307}308309return true;310}311312/*313* Iterates @type in order to compute how many individual leaf variables314* contains.315*/316static void317iterate_type_count_variables(const struct glsl_type *type,318unsigned int *num_variables)319{320for (unsigned i = 0; i < glsl_get_length(type); i++) {321const struct glsl_type *field_type;322323if (glsl_type_is_struct_or_ifc(type))324field_type = glsl_get_struct_field(type, i);325else326field_type = glsl_get_array_element(type);327328if (glsl_type_is_leaf(field_type))329(*num_variables)++;330else331iterate_type_count_variables(field_type, num_variables);332}333}334335336static void337fill_individual_variable(const struct glsl_type *type,338struct gl_uniform_buffer_variable *variables,339unsigned int *variable_index,340unsigned int *offset,341struct gl_shader_program *prog,342struct gl_uniform_block *block)343{344/* ARB_gl_spirv: allowed to ignore names. Thus, we don't need to initialize345* the variable's Name or IndexName.346*/347variables[*variable_index].Type = type;348349if (glsl_type_is_matrix(type)) {350variables[*variable_index].RowMajor = glsl_matrix_type_is_row_major(type);351} else {352/* default value, better that potential meaningless garbage */353variables[*variable_index].RowMajor = false;354}355356/**357* Although ARB_gl_spirv points that the offsets need to be included (see358* "Mappings of layouts"), in the end those are only valid for359* root-variables, and we would need to recompute offsets when we iterate360* over non-trivial types, like aoa. So we compute the offset always.361*/362variables[*variable_index].Offset = *offset;363(*offset) += glsl_get_explicit_size(type, true);364365(*variable_index)++;366}367368static void369iterate_type_fill_variables(const struct glsl_type *type,370struct gl_uniform_buffer_variable *variables,371unsigned int *variable_index,372unsigned int *offset,373struct gl_shader_program *prog,374struct gl_uniform_block *block)375{376unsigned int struct_base_offset;377378for (unsigned i = 0; i < glsl_get_length(type); i++) {379const struct glsl_type *field_type;380381if (glsl_type_is_struct_or_ifc(type)) {382field_type = glsl_get_struct_field(type, i);383384if (i == 0) {385struct_base_offset = *offset;386}387388*offset = struct_base_offset + glsl_get_struct_field_offset(type, i);389} else {390field_type = glsl_get_array_element(type);391}392393if (glsl_type_is_leaf(field_type)) {394fill_individual_variable(field_type, variables, variable_index,395offset, prog, block);396} else {397iterate_type_fill_variables(field_type, variables, variable_index,398offset, prog, block);399}400}401}402403/*404* In opposite to the equivalent glsl one, this one only allocates the needed405* space. We do a initial count here, just to avoid re-allocating for each one406* we find.407*/408static void409allocate_uniform_blocks(void *mem_ctx,410struct gl_linked_shader *shader,411struct gl_uniform_block **out_blks, unsigned *num_blocks,412struct gl_uniform_buffer_variable **out_variables,413unsigned *num_variables,414enum block_type block_type)415{416*num_variables = 0;417*num_blocks = 0;418419nir_foreach_variable_in_shader(var, shader->Program->nir) {420if (block_type == BLOCK_UBO && !nir_variable_is_in_ubo(var))421continue;422423if (block_type == BLOCK_SSBO && !nir_variable_is_in_ssbo(var))424continue;425426const struct glsl_type *type = glsl_without_array(var->type);427unsigned aoa_size = glsl_get_aoa_size(var->type);428unsigned buffer_count = aoa_size == 0 ? 1 : aoa_size;429430*num_blocks += buffer_count;431432unsigned int block_variables = 0;433iterate_type_count_variables(type, &block_variables);434435*num_variables += block_variables * buffer_count;436}437438if (*num_blocks == 0) {439assert(*num_variables == 0);440return;441}442443assert(*num_variables != 0);444445struct gl_uniform_block *blocks =446rzalloc_array(mem_ctx, struct gl_uniform_block, *num_blocks);447448struct gl_uniform_buffer_variable *variables =449rzalloc_array(blocks, struct gl_uniform_buffer_variable, *num_variables);450451*out_blks = blocks;452*out_variables = variables;453}454455static void456fill_block(struct gl_uniform_block *block,457nir_variable *var,458struct gl_uniform_buffer_variable *variables,459unsigned *variable_index,460unsigned array_index,461struct gl_shader_program *prog,462const gl_shader_stage stage)463{464const struct glsl_type *type = glsl_without_array(var->type);465466block->Name = NULL; /* ARB_gl_spirv: allowed to ignore names */467/* From ARB_gl_spirv spec:468* "Vulkan uses only one binding point for a resource array,469* while OpenGL still uses multiple binding points, so binding470* numbers are counted differently for SPIR-V used in Vulkan471* and OpenGL472*/473block->Binding = var->data.binding + array_index;474block->Uniforms = &variables[*variable_index];475block->stageref = 1U << stage;476477/* From SPIR-V 1.0 spec, 3.20, Decoration:478* "RowMajor479* Applies only to a member of a structure type.480* Only valid on a matrix or array whose most basic481* element is a matrix. Indicates that components482* within a row are contiguous in memory."483*484* So the SPIR-V binary doesn't report if the block was defined as RowMajor485* or not. In any case, for the components it is mandatory to set it, so it486* is not needed a default RowMajor value to know it.487*488* Setting to the default, but it should be ignored.489*/490block->_RowMajor = false;491492/* From ARB_gl_spirv spec:493* "Mapping of layouts494*495* std140/std430 -> explicit *Offset*, *ArrayStride*, and496* *MatrixStride* Decoration on struct members497* shared/packed -> not allowed"498*499* So we would not have a value for _Packing, and in fact it would be500* useless so far. Using a default value. It should be ignored.501*/502block->_Packing = 0;503block->linearized_array_index = array_index;504505unsigned old_variable_index = *variable_index;506unsigned offset = 0;507iterate_type_fill_variables(type, variables, variable_index, &offset, prog, block);508block->NumUniforms = *variable_index - old_variable_index;509510block->UniformBufferSize = glsl_get_explicit_size(type, false);511512/* From OpenGL 4.6 spec, section 7.6.2.3, "SPIR-V Uniform Offsets and513* strides"514*515* "If the variable is decorated as a BufferBlock , its offsets and516* strides must not contradict std430 alignment and minimum offset517* requirements. Otherwise, its offsets and strides must not contradict518* std140 alignment and minimum offset requirements."519*520* So although we are computing the size based on the offsets and521* array/matrix strides, at the end we need to ensure that the alignment is522* the same that with std140. From ARB_uniform_buffer_object spec:523*524* "For uniform blocks laid out according to [std140] rules, the minimum525* buffer object size returned by the UNIFORM_BLOCK_DATA_SIZE query is526* derived by taking the offset of the last basic machine unit consumed527* by the last uniform of the uniform block (including any end-of-array528* or end-of-structure padding), adding one, and rounding up to the next529* multiple of the base alignment required for a vec4."530*/531block->UniformBufferSize = glsl_align(block->UniformBufferSize, 16);532}533534/*535* Link ubos/ssbos for a given linked_shader/stage.536*/537static void538link_linked_shader_uniform_blocks(void *mem_ctx,539struct gl_context *ctx,540struct gl_shader_program *prog,541struct gl_linked_shader *shader,542struct gl_uniform_block **blocks,543unsigned *num_blocks,544enum block_type block_type)545{546struct gl_uniform_buffer_variable *variables = NULL;547unsigned num_variables = 0;548549allocate_uniform_blocks(mem_ctx, shader,550blocks, num_blocks,551&variables, &num_variables,552block_type);553554/* Fill the content of uniforms and variables */555unsigned block_index = 0;556unsigned variable_index = 0;557struct gl_uniform_block *blks = *blocks;558559nir_foreach_variable_in_shader(var, shader->Program->nir) {560if (block_type == BLOCK_UBO && !nir_variable_is_in_ubo(var))561continue;562563if (block_type == BLOCK_SSBO && !nir_variable_is_in_ssbo(var))564continue;565566unsigned aoa_size = glsl_get_aoa_size(var->type);567unsigned buffer_count = aoa_size == 0 ? 1 : aoa_size;568569for (unsigned array_index = 0; array_index < buffer_count; array_index++) {570fill_block(&blks[block_index], var, variables, &variable_index,571array_index, prog, shader->Stage);572block_index++;573}574}575576assert(block_index == *num_blocks);577assert(variable_index == num_variables);578}579580bool581gl_nir_link_uniform_blocks(struct gl_context *ctx,582struct gl_shader_program *prog)583{584void *mem_ctx = ralloc_context(NULL);585bool ret = false;586for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) {587struct gl_linked_shader *const linked = prog->_LinkedShaders[stage];588struct gl_uniform_block *ubo_blocks = NULL;589unsigned num_ubo_blocks = 0;590struct gl_uniform_block *ssbo_blocks = NULL;591unsigned num_ssbo_blocks = 0;592593if (!linked)594continue;595596link_linked_shader_uniform_blocks(mem_ctx, ctx, prog, linked,597&ubo_blocks, &num_ubo_blocks,598BLOCK_UBO);599600link_linked_shader_uniform_blocks(mem_ctx, ctx, prog, linked,601&ssbo_blocks, &num_ssbo_blocks,602BLOCK_SSBO);603604if (!prog->data->LinkStatus) {605goto out;606}607608prog->data->linked_stages |= 1 << stage;609610/* Copy ubo blocks to linked shader list */611linked->Program->sh.UniformBlocks =612ralloc_array(linked, struct gl_uniform_block *, num_ubo_blocks);613ralloc_steal(linked, ubo_blocks);614linked->Program->sh.NumUniformBlocks = num_ubo_blocks;615for (unsigned i = 0; i < num_ubo_blocks; i++) {616linked->Program->sh.UniformBlocks[i] = &ubo_blocks[i];617}618619/* We need to set it twice to avoid the value being overwritten by the620* one from nir in brw_shader_gather_info. TODO: get a way to set the621* info once, and being able to gather properly the info.622*/623linked->Program->nir->info.num_ubos = num_ubo_blocks;624linked->Program->info.num_ubos = num_ubo_blocks;625626/* Copy ssbo blocks to linked shader list */627linked->Program->sh.ShaderStorageBlocks =628ralloc_array(linked, struct gl_uniform_block *, num_ssbo_blocks);629ralloc_steal(linked, ssbo_blocks);630for (unsigned i = 0; i < num_ssbo_blocks; i++) {631linked->Program->sh.ShaderStorageBlocks[i] = &ssbo_blocks[i];632}633634/* See previous comment on num_ubo_blocks */635linked->Program->nir->info.num_ssbos = num_ssbo_blocks;636linked->Program->info.num_ssbos = num_ssbo_blocks;637}638639if (!nir_interstage_cross_validate_uniform_blocks(prog, BLOCK_UBO))640goto out;641642if (!nir_interstage_cross_validate_uniform_blocks(prog, BLOCK_SSBO))643goto out;644645ret = true;646out:647ralloc_free(mem_ctx);648return ret;649}650651652