Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_link_xfb.c
4545 views
/*1* Copyright © 2018 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 "nir_xfb_info.h"25#include "gl_nir_linker.h"26#include "linker_util.h"27#include "main/context.h"28#include "util/u_math.h"2930/**31* This file does the linking of GLSL transform feedback using NIR.32*/3334void35gl_nir_link_assign_xfb_resources(struct gl_context *ctx,36struct gl_shader_program *prog)37{38/*39* From ARB_gl_spirv spec:40*41* "- If the *Xfb* Execution Mode is set, any output variable that is at42* least partially captured:43* * must be decorated with an *XfbBuffer*, declaring the capturing buffer44* * must have at least one captured output variable in the capturing45* buffer decorated with an *XfbStride* (and all such *XfbStride* values46* for the capturing buffer must be equal)47* - If the *Xfb* Execution Mode is set, any captured output:48* * must be a non-structure decorated with *Offset* or a member of a49* structure whose type member is decorated with *Offset*"50*51* Note the "must be", meaning that explicit buffer, offset and stride are52* mandatory. So as this is intended to work with SPIR-V shaders we don't53* need to calculate the offset or the stride.54*/5556struct gl_program *xfb_prog = prog->last_vert_prog;5758if (xfb_prog == NULL)59return;6061/* free existing varyings, if any */62for (unsigned i = 0; i < prog->TransformFeedback.NumVarying; i++)63free(prog->TransformFeedback.VaryingNames[i]);64free(prog->TransformFeedback.VaryingNames);6566nir_xfb_info *xfb_info = NULL;67nir_xfb_varyings_info *varyings_info = NULL;6869/* Find last stage before fragment shader */70for (int stage = MESA_SHADER_FRAGMENT - 1; stage >= 0; stage--) {71struct gl_linked_shader *sh = prog->_LinkedShaders[stage];7273if (sh && stage != MESA_SHADER_TESS_CTRL) {74xfb_info = nir_gather_xfb_info_with_varyings(sh->Program->nir, NULL, &varyings_info);75break;76}77}7879struct gl_transform_feedback_info *linked_xfb =80rzalloc(xfb_prog, struct gl_transform_feedback_info);81xfb_prog->sh.LinkedTransformFeedback = linked_xfb;8283if (!xfb_info) {84prog->TransformFeedback.NumVarying = 0;85linked_xfb->NumOutputs = 0;86linked_xfb->NumVarying = 0;87linked_xfb->ActiveBuffers = 0;88return;89}9091for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++)92prog->TransformFeedback.BufferStride[buf] = xfb_info->buffers[buf].stride;9394prog->TransformFeedback.NumVarying = varyings_info->varying_count;95prog->TransformFeedback.VaryingNames =96malloc(sizeof(GLchar *) * varyings_info->varying_count);9798linked_xfb->Outputs =99rzalloc_array(xfb_prog,100struct gl_transform_feedback_output,101xfb_info->output_count);102linked_xfb->NumOutputs = xfb_info->output_count;103104linked_xfb->Varyings =105rzalloc_array(xfb_prog,106struct gl_transform_feedback_varying_info,107varyings_info->varying_count);108linked_xfb->NumVarying = varyings_info->varying_count;109110int buffer_index = 0; /* Corresponds to GL_TRANSFORM_FEEDBACK_BUFFER_INDEX */111int xfb_buffer =112(varyings_info->varying_count > 0) ?113xfb_info->outputs[0].buffer : 0;114115for (unsigned i = 0; i < varyings_info->varying_count; i++) {116nir_xfb_varying_info *xfb_varying = &varyings_info->varyings[i];117118/* From ARB_gl_spirv spec:119*120* "19. How should the program interface query operations behave for121* program objects created from SPIR-V shaders?122*123* DISCUSSION: we previously said we didn't need reflection to work124* for SPIR-V shaders (at least for the first version), however we125* are left with specifying how it should "not work". The primary126* issue is that SPIR-V binaries are not required to have names127* associated with variables. They can be associated in debug128* information, but there is no requirement for that to be present,129* and it should not be relied upon."130*131* Options:"132*133* <skip>134*135* "RESOLVED. Pick (c), but also allow debug names to be returned136* if an implementation wants to."137*138* So names are considered optional debug info, so the linker needs to139* work without them, and returning them is optional. For simplicity at140* this point we are ignoring names141*/142prog->TransformFeedback.VaryingNames[i] = NULL;143144if (xfb_buffer != xfb_varying->buffer) {145buffer_index++;146xfb_buffer = xfb_varying->buffer;147}148149struct gl_transform_feedback_varying_info *varying =150linked_xfb->Varyings + i;151152/* ARB_gl_spirv: see above. */153varying->Name = NULL;154varying->Type = glsl_get_gl_type(xfb_varying->type);155varying->BufferIndex = buffer_index;156varying->Size = glsl_type_is_array(xfb_varying->type) ?157glsl_get_length(xfb_varying->type) : 1;158varying->Offset = xfb_varying->offset;159}160161for (unsigned i = 0; i < xfb_info->output_count; i++) {162nir_xfb_output_info *xfb_output = &xfb_info->outputs[i];163164struct gl_transform_feedback_output *output =165linked_xfb->Outputs + i;166167output->OutputRegister = xfb_output->location;168output->OutputBuffer = xfb_output->buffer;169output->NumComponents = util_bitcount(xfb_output->component_mask);170output->StreamId = xfb_info->buffer_to_stream[xfb_output->buffer];171output->DstOffset = xfb_output->offset / 4;172output->ComponentOffset = xfb_output->component_offset;173}174175/* Make sure MaxTransformFeedbackBuffers is <= 32 so the bitmask for176* tracking the number of buffers doesn't overflow.177*/178unsigned buffers = 0;179assert(ctx->Const.MaxTransformFeedbackBuffers <= sizeof(buffers) * 8);180181for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++) {182if (xfb_info->buffers[buf].stride > 0) {183linked_xfb->Buffers[buf].Stride = xfb_info->buffers[buf].stride / 4;184linked_xfb->Buffers[buf].NumVaryings = xfb_info->buffers[buf].varying_count;185buffers |= 1 << buf;186}187}188189linked_xfb->ActiveBuffers = buffers;190191ralloc_free(xfb_info);192}193194195