Home | History | Annotate | Download | only in vc4
      1 /*
      2  * Copyright  2014-2015 Broadcom
      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, sublicense,
      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 next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * 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 NONINFRINGEMENT.  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 DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include "util/u_pack_color.h"
     25 #include "util/format_srgb.h"
     26 
     27 #include "vc4_context.h"
     28 #include "vc4_qir.h"
     29 
     30 static void
     31 write_texture_p0(struct vc4_job *job,
     32                  struct vc4_cl_out **uniforms,
     33                  struct vc4_texture_stateobj *texstate,
     34                  uint32_t unit)
     35 {
     36         struct vc4_sampler_view *sview =
     37                 vc4_sampler_view(texstate->textures[unit]);
     38         struct vc4_resource *rsc = vc4_resource(sview->texture);
     39 
     40         cl_reloc(job, &job->uniforms, uniforms, rsc->bo, sview->texture_p0);
     41 }
     42 
     43 static void
     44 write_texture_p1(struct vc4_job *job,
     45                  struct vc4_cl_out **uniforms,
     46                  struct vc4_texture_stateobj *texstate,
     47                  uint32_t unit)
     48 {
     49         struct vc4_sampler_view *sview =
     50                 vc4_sampler_view(texstate->textures[unit]);
     51         struct vc4_sampler_state *sampler =
     52                 vc4_sampler_state(texstate->samplers[unit]);
     53 
     54         cl_aligned_u32(uniforms, sview->texture_p1 | sampler->texture_p1);
     55 }
     56 
     57 static void
     58 write_texture_p2(struct vc4_job *job,
     59                  struct vc4_cl_out **uniforms,
     60                  struct vc4_texture_stateobj *texstate,
     61                  uint32_t data)
     62 {
     63         uint32_t unit = data & 0xffff;
     64         struct pipe_sampler_view *texture = texstate->textures[unit];
     65         struct vc4_resource *rsc = vc4_resource(texture->texture);
     66 
     67         cl_aligned_u32(uniforms,
     68                VC4_SET_FIELD(VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE,
     69                              VC4_TEX_P2_PTYPE) |
     70                VC4_SET_FIELD(rsc->cube_map_stride >> 12, VC4_TEX_P2_CMST) |
     71                VC4_SET_FIELD((data >> 16) & 1, VC4_TEX_P2_BSLOD));
     72 }
     73 
     74 static void
     75 write_texture_first_level(struct vc4_job *job,
     76                           struct vc4_cl_out **uniforms,
     77                           struct vc4_texture_stateobj *texstate,
     78                           uint32_t data)
     79 {
     80         uint32_t unit = data & 0xffff;
     81         struct pipe_sampler_view *texture = texstate->textures[unit];
     82 
     83         cl_aligned_f(uniforms, texture->u.tex.first_level);
     84 }
     85 
     86 static void
     87 write_texture_msaa_addr(struct vc4_job *job,
     88                  struct vc4_cl_out **uniforms,
     89                         struct vc4_texture_stateobj *texstate,
     90                         uint32_t unit)
     91 {
     92         struct pipe_sampler_view *texture = texstate->textures[unit];
     93         struct vc4_resource *rsc = vc4_resource(texture->texture);
     94 
     95         cl_aligned_reloc(job, &job->uniforms, uniforms, rsc->bo, 0);
     96 }
     97 
     98 
     99 #define SWIZ(x,y,z,w) {          \
    100         PIPE_SWIZZLE_##x, \
    101         PIPE_SWIZZLE_##y, \
    102         PIPE_SWIZZLE_##z, \
    103         PIPE_SWIZZLE_##w  \
    104 }
    105 
    106 static void
    107 write_texture_border_color(struct vc4_job *job,
    108                            struct vc4_cl_out **uniforms,
    109                            struct vc4_texture_stateobj *texstate,
    110                            uint32_t unit)
    111 {
    112         struct pipe_sampler_state *sampler = texstate->samplers[unit];
    113         struct pipe_sampler_view *texture = texstate->textures[unit];
    114         struct vc4_resource *rsc = vc4_resource(texture->texture);
    115         union util_color uc;
    116 
    117         const struct util_format_description *tex_format_desc =
    118                 util_format_description(texture->format);
    119 
    120         float border_color[4];
    121         for (int i = 0; i < 4; i++)
    122                 border_color[i] = sampler->border_color.f[i];
    123         if (util_format_is_srgb(texture->format)) {
    124                 for (int i = 0; i < 3; i++)
    125                         border_color[i] =
    126                                 util_format_linear_to_srgb_float(border_color[i]);
    127         }
    128 
    129         /* Turn the border color into the layout of channels that it would
    130          * have when stored as texture contents.
    131          */
    132         float storage_color[4];
    133         util_format_unswizzle_4f(storage_color,
    134                                  border_color,
    135                                  tex_format_desc->swizzle);
    136 
    137         /* Now, pack so that when the vc4_format-sampled texture contents are
    138          * replaced with our border color, the vc4_get_format_swizzle()
    139          * swizzling will get the right channels.
    140          */
    141         if (util_format_is_depth_or_stencil(texture->format)) {
    142                 uc.ui[0] = util_pack_z(PIPE_FORMAT_Z24X8_UNORM,
    143                                        sampler->border_color.f[0]) << 8;
    144         } else {
    145                 switch (rsc->vc4_format) {
    146                 default:
    147                 case VC4_TEXTURE_TYPE_RGBA8888:
    148                         util_pack_color(storage_color,
    149                                         PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
    150                         break;
    151                 case VC4_TEXTURE_TYPE_RGBA4444:
    152                 case VC4_TEXTURE_TYPE_RGBA5551:
    153                         util_pack_color(storage_color,
    154                                         PIPE_FORMAT_A8B8G8R8_UNORM, &uc);
    155                         break;
    156                 case VC4_TEXTURE_TYPE_RGB565:
    157                         util_pack_color(storage_color,
    158                                         PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
    159                         break;
    160                 case VC4_TEXTURE_TYPE_ALPHA:
    161                         uc.ui[0] = float_to_ubyte(storage_color[0]) << 24;
    162                         break;
    163                 case VC4_TEXTURE_TYPE_LUMALPHA:
    164                         uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) |
    165                                     (float_to_ubyte(storage_color[0]) << 0));
    166                         break;
    167                 }
    168         }
    169 
    170         cl_aligned_u32(uniforms, uc.ui[0]);
    171 }
    172 
    173 static uint32_t
    174 get_texrect_scale(struct vc4_texture_stateobj *texstate,
    175                   enum quniform_contents contents,
    176                   uint32_t data)
    177 {
    178         struct pipe_sampler_view *texture = texstate->textures[data];
    179         uint32_t dim;
    180 
    181         if (contents == QUNIFORM_TEXRECT_SCALE_X)
    182                 dim = texture->texture->width0;
    183         else
    184                 dim = texture->texture->height0;
    185 
    186         return fui(1.0f / dim);
    187 }
    188 
    189 static struct vc4_bo *
    190 vc4_upload_ubo(struct vc4_context *vc4,
    191                struct vc4_compiled_shader *shader,
    192                const uint32_t *gallium_uniforms)
    193 {
    194         if (!shader->ubo_size)
    195                 return NULL;
    196 
    197         struct vc4_bo *ubo = vc4_bo_alloc(vc4->screen, shader->ubo_size, "ubo");
    198         void *data = vc4_bo_map(ubo);
    199         for (uint32_t i = 0; i < shader->num_ubo_ranges; i++) {
    200                 memcpy(data + shader->ubo_ranges[i].dst_offset,
    201                        ((const void *)gallium_uniforms +
    202                         shader->ubo_ranges[i].src_offset),
    203                        shader->ubo_ranges[i].size);
    204         }
    205 
    206         return ubo;
    207 }
    208 
    209 void
    210 vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
    211                    struct vc4_constbuf_stateobj *cb,
    212                    struct vc4_texture_stateobj *texstate)
    213 {
    214         struct vc4_shader_uniform_info *uinfo = &shader->uniforms;
    215         struct vc4_job *job = vc4->job;
    216         const uint32_t *gallium_uniforms = cb->cb[0].user_buffer;
    217         struct vc4_bo *ubo = vc4_upload_ubo(vc4, shader, gallium_uniforms);
    218 
    219         cl_ensure_space(&job->uniforms, (uinfo->count +
    220                                          uinfo->num_texture_samples) * 4);
    221 
    222         struct vc4_cl_out *uniforms =
    223                 cl_start_shader_reloc(&job->uniforms,
    224                                       uinfo->num_texture_samples);
    225 
    226         for (int i = 0; i < uinfo->count; i++) {
    227 
    228                 switch (uinfo->contents[i]) {
    229                 case QUNIFORM_CONSTANT:
    230                         cl_aligned_u32(&uniforms, uinfo->data[i]);
    231                         break;
    232                 case QUNIFORM_UNIFORM:
    233                         cl_aligned_u32(&uniforms,
    234                                        gallium_uniforms[uinfo->data[i]]);
    235                         break;
    236                 case QUNIFORM_VIEWPORT_X_SCALE:
    237                         cl_aligned_f(&uniforms, vc4->viewport.scale[0] * 16.0f);
    238                         break;
    239                 case QUNIFORM_VIEWPORT_Y_SCALE:
    240                         cl_aligned_f(&uniforms, vc4->viewport.scale[1] * 16.0f);
    241                         break;
    242 
    243                 case QUNIFORM_VIEWPORT_Z_OFFSET:
    244                         cl_aligned_f(&uniforms, vc4->viewport.translate[2]);
    245                         break;
    246                 case QUNIFORM_VIEWPORT_Z_SCALE:
    247                         cl_aligned_f(&uniforms, vc4->viewport.scale[2]);
    248                         break;
    249 
    250                 case QUNIFORM_USER_CLIP_PLANE:
    251                         cl_aligned_f(&uniforms,
    252                                      vc4->clip.ucp[uinfo->data[i] / 4][uinfo->data[i] % 4]);
    253                         break;
    254 
    255                 case QUNIFORM_TEXTURE_CONFIG_P0:
    256                         write_texture_p0(job, &uniforms, texstate,
    257                                          uinfo->data[i]);
    258                         break;
    259 
    260                 case QUNIFORM_TEXTURE_CONFIG_P1:
    261                         write_texture_p1(job, &uniforms, texstate,
    262                                          uinfo->data[i]);
    263                         break;
    264 
    265                 case QUNIFORM_TEXTURE_CONFIG_P2:
    266                         write_texture_p2(job, &uniforms, texstate,
    267                                          uinfo->data[i]);
    268                         break;
    269 
    270                 case QUNIFORM_TEXTURE_FIRST_LEVEL:
    271                         write_texture_first_level(job, &uniforms, texstate,
    272                                                   uinfo->data[i]);
    273                         break;
    274 
    275                 case QUNIFORM_UBO_ADDR:
    276                         cl_aligned_reloc(job, &job->uniforms, &uniforms, ubo, 0);
    277                         break;
    278 
    279                 case QUNIFORM_TEXTURE_MSAA_ADDR:
    280                         write_texture_msaa_addr(job, &uniforms,
    281                                                 texstate, uinfo->data[i]);
    282                         break;
    283 
    284                 case QUNIFORM_TEXTURE_BORDER_COLOR:
    285                         write_texture_border_color(job, &uniforms,
    286                                                    texstate, uinfo->data[i]);
    287                         break;
    288 
    289                 case QUNIFORM_TEXRECT_SCALE_X:
    290                 case QUNIFORM_TEXRECT_SCALE_Y:
    291                         cl_aligned_u32(&uniforms,
    292                                        get_texrect_scale(texstate,
    293                                                          uinfo->contents[i],
    294                                                          uinfo->data[i]));
    295                         break;
    296 
    297                 case QUNIFORM_BLEND_CONST_COLOR_X:
    298                 case QUNIFORM_BLEND_CONST_COLOR_Y:
    299                 case QUNIFORM_BLEND_CONST_COLOR_Z:
    300                 case QUNIFORM_BLEND_CONST_COLOR_W:
    301                         cl_aligned_f(&uniforms,
    302                                      CLAMP(vc4->blend_color.f.color[uinfo->contents[i] -
    303                                                                     QUNIFORM_BLEND_CONST_COLOR_X],
    304                                            0, 1));
    305                         break;
    306 
    307                 case QUNIFORM_BLEND_CONST_COLOR_RGBA: {
    308                         const uint8_t *format_swiz =
    309                                 vc4_get_format_swizzle(vc4->framebuffer.cbufs[0]->format);
    310                         uint32_t color = 0;
    311                         for (int i = 0; i < 4; i++) {
    312                                 if (format_swiz[i] >= 4)
    313                                         continue;
    314 
    315                                 color |= (vc4->blend_color.ub[format_swiz[i]] <<
    316                                           (i * 8));
    317                         }
    318                         cl_aligned_u32(&uniforms, color);
    319                         break;
    320                 }
    321 
    322                 case QUNIFORM_BLEND_CONST_COLOR_AAAA: {
    323                         uint8_t a = vc4->blend_color.ub[3];
    324                         cl_aligned_u32(&uniforms, ((a) |
    325                                                    (a << 8) |
    326                                                    (a << 16) |
    327                                                    (a << 24)));
    328                         break;
    329                 }
    330 
    331                 case QUNIFORM_STENCIL:
    332                         cl_aligned_u32(&uniforms,
    333                                        vc4->zsa->stencil_uniforms[uinfo->data[i]] |
    334                                        (uinfo->data[i] <= 1 ?
    335                                         (vc4->stencil_ref.ref_value[uinfo->data[i]] << 8) :
    336                                         0));
    337                         break;
    338 
    339                 case QUNIFORM_ALPHA_REF:
    340                         cl_aligned_f(&uniforms,
    341                                      vc4->zsa->base.alpha.ref_value);
    342                         break;
    343 
    344                 case QUNIFORM_SAMPLE_MASK:
    345                         cl_aligned_u32(&uniforms, vc4->sample_mask);
    346                         break;
    347 
    348                 case QUNIFORM_UNIFORMS_ADDRESS:
    349                         /* This will be filled in by the kernel. */
    350                         cl_aligned_u32(&uniforms, 0xd0d0d0d0);
    351                         break;
    352                 }
    353 #if 0
    354                 uint32_t written_val = *((uint32_t *)uniforms - 1);
    355                 fprintf(stderr, "%p: %d / 0x%08x (%f)\n",
    356                         shader, i, written_val, uif(written_val));
    357 #endif
    358         }
    359 
    360         cl_end(&job->uniforms, uniforms);
    361 
    362         vc4_bo_unreference(&ubo);
    363 }
    364 
    365 void
    366 vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader)
    367 {
    368         uint32_t dirty = 0;
    369 
    370         for (int i = 0; i < shader->uniforms.count; i++) {
    371                 switch (shader->uniforms.contents[i]) {
    372                 case QUNIFORM_CONSTANT:
    373                 case QUNIFORM_UNIFORMS_ADDRESS:
    374                         break;
    375                 case QUNIFORM_UNIFORM:
    376                 case QUNIFORM_UBO_ADDR:
    377                         dirty |= VC4_DIRTY_CONSTBUF;
    378                         break;
    379 
    380                 case QUNIFORM_VIEWPORT_X_SCALE:
    381                 case QUNIFORM_VIEWPORT_Y_SCALE:
    382                 case QUNIFORM_VIEWPORT_Z_OFFSET:
    383                 case QUNIFORM_VIEWPORT_Z_SCALE:
    384                         dirty |= VC4_DIRTY_VIEWPORT;
    385                         break;
    386 
    387                 case QUNIFORM_USER_CLIP_PLANE:
    388                         dirty |= VC4_DIRTY_CLIP;
    389                         break;
    390 
    391                 case QUNIFORM_TEXTURE_CONFIG_P0:
    392                 case QUNIFORM_TEXTURE_CONFIG_P1:
    393                 case QUNIFORM_TEXTURE_CONFIG_P2:
    394                 case QUNIFORM_TEXTURE_BORDER_COLOR:
    395                 case QUNIFORM_TEXTURE_FIRST_LEVEL:
    396                 case QUNIFORM_TEXTURE_MSAA_ADDR:
    397                 case QUNIFORM_TEXRECT_SCALE_X:
    398                 case QUNIFORM_TEXRECT_SCALE_Y:
    399                         /* We could flag this on just the stage we're
    400                          * compiling for, but it's not passed in.
    401                          */
    402                         dirty |= VC4_DIRTY_FRAGTEX | VC4_DIRTY_VERTTEX;
    403                         break;
    404 
    405                 case QUNIFORM_BLEND_CONST_COLOR_X:
    406                 case QUNIFORM_BLEND_CONST_COLOR_Y:
    407                 case QUNIFORM_BLEND_CONST_COLOR_Z:
    408                 case QUNIFORM_BLEND_CONST_COLOR_W:
    409                 case QUNIFORM_BLEND_CONST_COLOR_RGBA:
    410                 case QUNIFORM_BLEND_CONST_COLOR_AAAA:
    411                         dirty |= VC4_DIRTY_BLEND_COLOR;
    412                         break;
    413 
    414                 case QUNIFORM_STENCIL:
    415                 case QUNIFORM_ALPHA_REF:
    416                         dirty |= VC4_DIRTY_ZSA;
    417                         break;
    418 
    419                 case QUNIFORM_SAMPLE_MASK:
    420                         dirty |= VC4_DIRTY_SAMPLE_MASK;
    421                         break;
    422                 }
    423         }
    424 
    425         shader->uniform_dirty_bits = dirty;
    426 }
    427