xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/etnaviv/etnaviv_uniforms.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2016 Etnaviv Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sub license,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Christian Gmeiner <[email protected]>
25  */
26 
27 #include "etnaviv_uniforms.h"
28 
29 #include "etnaviv_compiler.h"
30 #include "etnaviv_context.h"
31 #include "etnaviv_util.h"
32 #include "etnaviv_emit.h"
33 #include "pipe/p_defines.h"
34 #include "util/u_math.h"
35 
36 static unsigned
get_const_idx(const struct etna_context * ctx,bool frag,unsigned samp_id)37 get_const_idx(const struct etna_context *ctx, bool frag, unsigned samp_id)
38 {
39    struct etna_screen *screen = ctx->screen;
40 
41    if (frag)
42       return samp_id;
43 
44    return samp_id + screen->specs.vertex_sampler_offset;
45 }
46 
47 static uint32_t
get_texrect_scale(const struct etna_context * ctx,bool frag,enum etna_uniform_contents contents,uint32_t data)48 get_texrect_scale(const struct etna_context *ctx, bool frag,
49                   enum etna_uniform_contents contents, uint32_t data)
50 {
51    unsigned index = get_const_idx(ctx, frag, data);
52    struct pipe_sampler_view *texture = ctx->sampler_view[index];
53    uint32_t dim;
54 
55    if (contents == ETNA_UNIFORM_TEXRECT_SCALE_X)
56       dim = texture->texture->width0;
57    else
58       dim = texture->texture->height0;
59 
60    return fui(1.0f / dim);
61 }
62 
63 static inline bool
is_array_texture(enum pipe_texture_target target)64 is_array_texture(enum pipe_texture_target target)
65 {
66    switch (target) {
67    case PIPE_TEXTURE_1D_ARRAY:
68    case PIPE_TEXTURE_2D_ARRAY:
69    case PIPE_TEXTURE_CUBE_ARRAY:
70       return true;
71    default:
72       return false;
73    }
74 }
75 
76 static uint32_t
get_texture_size(const struct etna_context * ctx,bool frag,enum etna_uniform_contents contents,uint32_t data)77 get_texture_size(const struct etna_context *ctx, bool frag,
78                   enum etna_uniform_contents contents, uint32_t data)
79 {
80    unsigned index = get_const_idx(ctx, frag, data);
81    struct pipe_sampler_view *texture = ctx->sampler_view[index];
82 
83    switch (contents) {
84    case ETNA_UNIFORM_TEXTURE_WIDTH:
85       if (texture->target == PIPE_BUFFER) {
86          return texture->u.buf.size / util_format_get_blocksize(texture->format);
87       } else {
88          return u_minify(texture->texture->width0, texture->u.tex.first_level);
89       }
90    case ETNA_UNIFORM_TEXTURE_HEIGHT:
91       return u_minify(texture->texture->height0, texture->u.tex.first_level);
92    case ETNA_UNIFORM_TEXTURE_DEPTH:
93       assert(texture->target != PIPE_BUFFER);
94 
95       if (is_array_texture(texture->target)) {
96          if (texture->target != PIPE_TEXTURE_CUBE_ARRAY) {
97             return texture->texture->array_size;
98          } else {
99             assert(texture->texture->array_size % 6 == 0);
100             return texture->texture->array_size / 6;
101          }
102       }
103 
104       return u_minify(texture->texture->depth0, texture->u.tex.first_level);
105    default:
106       unreachable("Bad texture size field");
107    }
108 }
109 
110 void
etna_uniforms_write(const struct etna_context * ctx,const struct etna_shader_variant * sobj,struct pipe_constant_buffer * cb)111 etna_uniforms_write(const struct etna_context *ctx,
112                     const struct etna_shader_variant *sobj,
113                     struct pipe_constant_buffer *cb)
114 {
115    struct etna_screen *screen = ctx->screen;
116    struct etna_cmd_stream *stream = ctx->stream;
117    const struct etna_shader_uniform_info *uinfo = &sobj->uniforms;
118    bool frag = (sobj == ctx->shader.fs);
119    uint32_t base = frag ? screen->specs.ps_uniforms_offset : screen->specs.vs_uniforms_offset;
120 
121    if (!uinfo->count)
122       return;
123 
124    etna_cmd_stream_reserve(stream, align(uinfo->count + 1, 2));
125    etna_emit_load_state(stream, base >> 2, uinfo->count, 0);
126 
127    for (uint32_t i = 0; i < uinfo->count; i++) {
128       uint32_t val = uinfo->data[i];
129 
130       switch (uinfo->contents[i]) {
131       case ETNA_UNIFORM_CONSTANT:
132          etna_cmd_stream_emit(stream, val);
133          break;
134 
135       case ETNA_UNIFORM_UNIFORM:
136          assert(cb->user_buffer && val * 4 < cb->buffer_size);
137          etna_cmd_stream_emit(stream, ((uint32_t*) cb->user_buffer)[val]);
138          break;
139 
140       case ETNA_UNIFORM_TEXRECT_SCALE_X:
141       case ETNA_UNIFORM_TEXRECT_SCALE_Y:
142          etna_cmd_stream_emit(stream,
143             get_texrect_scale(ctx, frag, uinfo->contents[i], val));
144          break;
145 
146       case ETNA_UNIFORM_TEXTURE_WIDTH:
147       case ETNA_UNIFORM_TEXTURE_HEIGHT:
148       case ETNA_UNIFORM_TEXTURE_DEPTH:
149          etna_cmd_stream_emit(stream,
150             get_texture_size(ctx, frag, uinfo->contents[i], val));
151          break;
152 
153       case ETNA_UNIFORM_UBO_ADDR:
154          etna_cmd_stream_reloc(stream, &(struct etna_reloc) {
155             .bo = etna_resource(cb[val].buffer)->bo,
156             .flags = ETNA_RELOC_READ,
157             .offset = cb[val].buffer_offset,
158          });
159          break;
160 
161       case ETNA_UNIFORM_UNUSED:
162          etna_cmd_stream_emit(stream, 0);
163          break;
164       }
165    }
166 
167    if ((uinfo->count % 2) == 0)
168       etna_cmd_stream_emit(stream, 0);
169 }
170 
171 void
etna_set_shader_uniforms_dirty_flags(struct etna_shader_variant * sobj)172 etna_set_shader_uniforms_dirty_flags(struct etna_shader_variant *sobj)
173 {
174    uint32_t dirty = 0;
175 
176    for (uint32_t i = 0; i < sobj->uniforms.count; i++) {
177       switch (sobj->uniforms.contents[i]) {
178       default:
179          break;
180 
181       case ETNA_UNIFORM_TEXRECT_SCALE_X:
182       case ETNA_UNIFORM_TEXRECT_SCALE_Y:
183          dirty |= ETNA_DIRTY_SAMPLER_VIEWS;
184          break;
185       }
186    }
187 
188    sobj->uniforms_dirty_bits = dirty;
189 }
190