Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_link_uniform_initializers.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 "gl_nir_linker.h"25#include "compiler/glsl/ir_uniform.h" /* for gl_uniform_storage */26#include "main/context.h"27#include "main/mtypes.h"2829struct set_opaque_binding_closure {30struct gl_shader_program *shader_prog;31struct gl_program *prog;32const nir_variable *var;33int binding;34int location;35};3637static void38set_opaque_binding(struct set_opaque_binding_closure *data,39const struct glsl_type *type)40{41if (glsl_type_is_array(type) &&42glsl_type_is_array(glsl_get_array_element(type))) {43const struct glsl_type *element_type = glsl_get_array_element(type);4445for (unsigned int i = 0; i < glsl_get_length(type); i++)46set_opaque_binding(data, element_type);4748return;49}5051if (data->location < 0 ||52data->location >= data->prog->sh.data->NumUniformStorage)53return;5455struct gl_uniform_storage *storage =56data->prog->sh.data->UniformStorage + data->location++;5758const unsigned elements = MAX2(storage->array_elements, 1);5960for (unsigned int i = 0; i < elements; i++)61storage->storage[i].i = data->binding++;6263for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {64struct gl_linked_shader *shader = data->shader_prog->_LinkedShaders[sh];6566if (!shader)67continue;68if (!storage->opaque[sh].active)69continue;7071if (glsl_type_is_sampler(storage->type)) {72for (unsigned i = 0; i < elements; i++) {73const unsigned index = storage->opaque[sh].index + i;7475if (storage->is_bindless) {76if (index >= shader->Program->sh.NumBindlessSamplers)77break;78shader->Program->sh.BindlessSamplers[index].unit =79storage->storage[i].i;80shader->Program->sh.BindlessSamplers[index].bound = true;81shader->Program->sh.HasBoundBindlessSampler = true;82} else {83if (index >= ARRAY_SIZE(shader->Program->SamplerUnits))84break;85shader->Program->SamplerUnits[index] =86storage->storage[i].i;87}88}89} else if (glsl_type_is_image(storage->type)) {90for (unsigned i = 0; i < elements; i++) {91const unsigned index = storage->opaque[sh].index + i;9293if (storage->is_bindless) {94if (index >= shader->Program->sh.NumBindlessImages)95break;96shader->Program->sh.BindlessImages[index].unit =97storage->storage[i].i;98shader->Program->sh.BindlessImages[index].bound = true;99shader->Program->sh.HasBoundBindlessImage = true;100} else {101if (index >= ARRAY_SIZE(shader->Program->sh.ImageUnits))102break;103shader->Program->sh.ImageUnits[index] =104storage->storage[i].i;105}106}107}108}109}110111static void112copy_constant_to_storage(union gl_constant_value *storage,113const nir_constant *val,114const struct glsl_type *type,115unsigned int boolean_true)116{117const enum glsl_base_type base_type = glsl_get_base_type(type);118const unsigned n_columns = glsl_get_matrix_columns(type);119const unsigned n_rows = glsl_get_vector_elements(type);120unsigned dmul = glsl_base_type_is_64bit(base_type) ? 2 : 1;121int i = 0;122123if (n_columns > 1) {124const struct glsl_type *column_type = glsl_get_column_type(type);125for (unsigned int column = 0; column < n_columns; column++) {126copy_constant_to_storage(&storage[i], val->elements[column],127column_type, boolean_true);128i += n_rows * dmul;129}130} else {131for (unsigned int row = 0; row < n_rows; row++) {132switch (base_type) {133case GLSL_TYPE_UINT:134storage[i].u = val->values[row].u32;135break;136case GLSL_TYPE_INT:137case GLSL_TYPE_SAMPLER:138storage[i].i = val->values[row].i32;139break;140case GLSL_TYPE_FLOAT:141storage[i].f = val->values[row].f32;142break;143case GLSL_TYPE_DOUBLE:144case GLSL_TYPE_UINT64:145case GLSL_TYPE_INT64:146/* XXX need to check on big-endian */147memcpy(&storage[i].u, &val->values[row].f64, sizeof(double));148break;149case GLSL_TYPE_BOOL:150storage[i].b = val->values[row].u32 ? boolean_true : 0;151break;152case GLSL_TYPE_ARRAY:153case GLSL_TYPE_STRUCT:154case GLSL_TYPE_IMAGE:155case GLSL_TYPE_ATOMIC_UINT:156case GLSL_TYPE_INTERFACE:157case GLSL_TYPE_VOID:158case GLSL_TYPE_SUBROUTINE:159case GLSL_TYPE_FUNCTION:160case GLSL_TYPE_ERROR:161case GLSL_TYPE_UINT16:162case GLSL_TYPE_INT16:163case GLSL_TYPE_UINT8:164case GLSL_TYPE_INT8:165case GLSL_TYPE_FLOAT16:166/* All other types should have already been filtered by other167* paths in the caller.168*/169assert(!"Should not get here.");170break;171}172i += dmul;173}174}175}176177struct set_uniform_initializer_closure {178struct gl_shader_program *shader_prog;179struct gl_program *prog;180const nir_variable *var;181int location;182unsigned int boolean_true;183};184185static void186set_uniform_initializer(struct set_uniform_initializer_closure *data,187const struct glsl_type *type,188const nir_constant *val)189{190const struct glsl_type *t_without_array = glsl_without_array(type);191192if (glsl_type_is_struct_or_ifc(type)) {193for (unsigned int i = 0; i < glsl_get_length(type); i++) {194const struct glsl_type *field_type = glsl_get_struct_field(type, i);195set_uniform_initializer(data, field_type, val->elements[i]);196}197return;198}199200if (glsl_type_is_struct_or_ifc(t_without_array) ||201(glsl_type_is_array(type) &&202glsl_type_is_array(glsl_get_array_element(type)))) {203const struct glsl_type *element_type = glsl_get_array_element(type);204205for (unsigned int i = 0; i < glsl_get_length(type); i++)206set_uniform_initializer(data, element_type, val->elements[i]);207208return;209}210211if (data->location < 0 ||212data->location >= data->prog->sh.data->NumUniformStorage)213return;214215struct gl_uniform_storage *storage =216data->prog->sh.data->UniformStorage + data->location++;217218if (glsl_type_is_array(type)) {219const struct glsl_type *element_type = glsl_get_array_element(type);220const enum glsl_base_type base_type = glsl_get_base_type(element_type);221const unsigned int elements = glsl_get_components(element_type);222unsigned int idx = 0;223unsigned dmul = glsl_base_type_is_64bit(base_type) ? 2 : 1;224225assert(glsl_get_length(type) >= storage->array_elements);226for (unsigned int i = 0; i < storage->array_elements; i++) {227copy_constant_to_storage(&storage->storage[idx],228val->elements[i],229element_type,230data->boolean_true);231232idx += elements * dmul;233}234} else {235copy_constant_to_storage(storage->storage,236val,237type,238data->boolean_true);239240if (glsl_type_is_sampler(storage->type)) {241for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {242struct gl_linked_shader *shader =243data->shader_prog->_LinkedShaders[sh];244245if (shader && storage->opaque[sh].active) {246unsigned index = storage->opaque[sh].index;247248shader->Program->SamplerUnits[index] = storage->storage[0].i;249}250}251}252}253}254255void256gl_nir_set_uniform_initializers(struct gl_context *ctx,257struct gl_shader_program *prog)258{259for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {260struct gl_linked_shader *sh = prog->_LinkedShaders[i];261if (!sh)262continue;263264nir_shader *nir = sh->Program->nir;265assert(nir);266267nir_foreach_gl_uniform_variable(var, nir) {268if (var->constant_initializer) {269struct set_uniform_initializer_closure data = {270.shader_prog = prog,271.prog = sh->Program,272.var = var,273.location = var->data.location,274.boolean_true = ctx->Const.UniformBooleanTrue275};276set_uniform_initializer(&data,277var->type,278var->constant_initializer);279} else if (var->data.explicit_binding) {280281if (nir_variable_is_in_block(var)) {282/* This case is handled by link_uniform_blocks */283continue;284}285286const struct glsl_type *without_array =287glsl_without_array(var->type);288289if (glsl_type_is_sampler(without_array) ||290glsl_type_is_image(without_array)) {291struct set_opaque_binding_closure data = {292.shader_prog = prog,293.prog = sh->Program,294.var = var,295.binding = var->data.binding,296.location = var->data.location297};298set_opaque_binding(&data, var->type);299}300}301}302}303memcpy(prog->data->UniformDataDefaults, prog->data->UniformDataSlots,304sizeof(union gl_constant_value) * prog->data->NumUniformDataSlots);305306}307308309