• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <christian.gmeiner@gmail.com>
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 void
etna_uniforms_write(const struct etna_context * ctx,const struct etna_shader_variant * sobj,struct pipe_constant_buffer * cb)64 etna_uniforms_write(const struct etna_context *ctx,
65                     const struct etna_shader_variant *sobj,
66                     struct pipe_constant_buffer *cb)
67 {
68    struct etna_screen *screen = ctx->screen;
69    struct etna_cmd_stream *stream = ctx->stream;
70    const struct etna_shader_uniform_info *uinfo = &sobj->uniforms;
71    bool frag = (sobj == ctx->shader.fs);
72    uint32_t base = frag ? screen->specs.ps_uniforms_offset : screen->specs.vs_uniforms_offset;
73    unsigned idx;
74 
75    if (!uinfo->count)
76       return;
77 
78    etna_cmd_stream_reserve(stream, align(uinfo->count + 1, 2));
79    etna_emit_load_state(stream, base >> 2, uinfo->count, 0);
80 
81    for (uint32_t i = 0; i < uinfo->count; i++) {
82       uint32_t val = uinfo->data[i];
83 
84       switch (uinfo->contents[i]) {
85       case ETNA_UNIFORM_CONSTANT:
86          etna_cmd_stream_emit(stream, val);
87          break;
88 
89       case ETNA_UNIFORM_UNIFORM:
90          assert(cb->user_buffer && val * 4 < cb->buffer_size);
91          etna_cmd_stream_emit(stream, ((uint32_t*) cb->user_buffer)[val]);
92          break;
93 
94       case ETNA_UNIFORM_TEXRECT_SCALE_X:
95       case ETNA_UNIFORM_TEXRECT_SCALE_Y:
96          etna_cmd_stream_emit(stream,
97             get_texrect_scale(ctx, frag, uinfo->contents[i], val));
98          break;
99 
100       case ETNA_UNIFORM_UBO0_ADDR ... ETNA_UNIFORM_UBOMAX_ADDR:
101          idx = uinfo->contents[i] - ETNA_UNIFORM_UBO0_ADDR;
102          etna_cmd_stream_reloc(stream, &(struct etna_reloc) {
103             .bo = etna_resource(cb[idx].buffer)->bo,
104             .flags = ETNA_RELOC_READ,
105             .offset = cb[idx].buffer_offset + val,
106          });
107          break;
108 
109       case ETNA_UNIFORM_UNUSED:
110          etna_cmd_stream_emit(stream, 0);
111          break;
112       }
113    }
114 
115    if ((uinfo->count % 2) == 0)
116       etna_cmd_stream_emit(stream, 0);
117 }
118 
119 void
etna_set_shader_uniforms_dirty_flags(struct etna_shader_variant * sobj)120 etna_set_shader_uniforms_dirty_flags(struct etna_shader_variant *sobj)
121 {
122    uint32_t dirty = 0;
123 
124    for (uint32_t i = 0; i < sobj->uniforms.count; i++) {
125       switch (sobj->uniforms.contents[i]) {
126       default:
127          break;
128 
129       case ETNA_UNIFORM_TEXRECT_SCALE_X:
130       case ETNA_UNIFORM_TEXRECT_SCALE_Y:
131          dirty |= ETNA_DIRTY_SAMPLER_VIEWS;
132          break;
133       }
134    }
135 
136    sobj->uniforms_dirty_bits = dirty;
137 }
138