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->base.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                         util_pack_color(storage_color,
    153                                         PIPE_FORMAT_A8B8G8R8_UNORM, &uc);
    154                         break;
    155                 case VC4_TEXTURE_TYPE_RGB565:
    156                         util_pack_color(storage_color,
    157                                         PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
    158                         break;
    159                 case VC4_TEXTURE_TYPE_ALPHA:
    160                         uc.ui[0] = float_to_ubyte(storage_color[0]) << 24;
    161                         break;
    162                 case VC4_TEXTURE_TYPE_LUMALPHA:
    163                         uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) |
    164                                     (float_to_ubyte(storage_color[0]) << 0));
    165                         break;
    166                 }
    167         }
    168 
    169         cl_aligned_u32(uniforms, uc.ui[0]);
    170 }
    171 
    172 static uint32_t
    173 get_texrect_scale(struct vc4_texture_stateobj *texstate,
    174                   enum quniform_contents contents,
    175                   uint32_t data)
    176 {
    177         struct pipe_sampler_view *texture = texstate->textures[data];
    178         uint32_t dim;
    179 
    180         if (contents == QUNIFORM_TEXRECT_SCALE_X)
    181                 dim = texture->texture->width0;
    182         else
    183                 dim = texture->texture->height0;
    184 
    185         return fui(1.0f / dim);
    186 }
    187 
    188 static struct vc4_bo *
    189 vc4_upload_ubo(struct vc4_context *vc4,
    190                struct vc4_compiled_shader *shader,
    191                const uint32_t *gallium_uniforms)
    192 {
    193         if (!shader->ubo_size)
    194                 return NULL;
    195 
    196         struct vc4_bo *ubo = vc4_bo_alloc(vc4->screen, shader->ubo_size, "ubo");
    197         void *data = vc4_bo_map(ubo);
    198         for (uint32_t i = 0; i < shader->num_ubo_ranges; i++) {
    199                 memcpy(data + shader->ubo_ranges[i].dst_offset,
    200                        ((const void *)gallium_uniforms +
    201                         shader->ubo_ranges[i].src_offset),
    202                        shader->ubo_ranges[i].size);
    203         }
    204 
    205         return ubo;
    206 }
    207 
    208 void
    209 vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
    210                    struct vc4_constbuf_stateobj *cb,
    211                    struct vc4_texture_stateobj *texstate)
    212 {
    213         struct vc4_shader_uniform_info *uinfo = &shader->uniforms;
    214         struct vc4_job *job = vc4->job;
    215         const uint32_t *gallium_uniforms = cb->cb[0].user_buffer;
    216         struct vc4_bo *ubo = vc4_upload_ubo(vc4, shader, gallium_uniforms);
    217 
    218         cl_ensure_space(&job->uniforms, (uinfo->count +
    219                                          uinfo->num_texture_samples) * 4);
    220 
    221         struct vc4_cl_out *uniforms =
    222                 cl_start_shader_reloc(&job->uniforms,
    223                                       uinfo->num_texture_samples);
    224 
    225         for (int i = 0; i < uinfo->count; i++) {
    226 
    227                 switch (uinfo->contents[i]) {
    228                 case QUNIFORM_CONSTANT:
    229                         cl_aligned_u32(&uniforms, uinfo->data[i]);
    230                         break;
    231                 case QUNIFORM_UNIFORM:
    232                         cl_aligned_u32(&uniforms,
    233                                        gallium_uniforms[uinfo->data[i]]);
    234                         break;
    235                 case QUNIFORM_VIEWPORT_X_SCALE:
    236                         cl_aligned_f(&uniforms, vc4->viewport.scale[0] * 16.0f);
    237                         break;
    238                 case QUNIFORM_VIEWPORT_Y_SCALE:
    239                         cl_aligned_f(&uniforms, vc4->viewport.scale[1] * 16.0f);
    240                         break;
    241 
    242                 case QUNIFORM_VIEWPORT_Z_OFFSET:
    243                         cl_aligned_f(&uniforms, vc4->viewport.translate[2]);
    244                         break;
    245                 case QUNIFORM_VIEWPORT_Z_SCALE:
    246                         cl_aligned_f(&uniforms, vc4->viewport.scale[2]);
    247                         break;
    248 
    249                 case QUNIFORM_USER_CLIP_PLANE:
    250                         cl_aligned_f(&uniforms,
    251                                      vc4->clip.ucp[uinfo->data[i] / 4][uinfo->data[i] % 4]);
    252                         break;
    253 
    254                 case QUNIFORM_TEXTURE_CONFIG_P0:
    255                         write_texture_p0(job, &uniforms, texstate,
    256                                          uinfo->data[i]);
    257                         break;
    258 
    259                 case QUNIFORM_TEXTURE_CONFIG_P1:
    260                         write_texture_p1(job, &uniforms, texstate,
    261                                          uinfo->data[i]);
    262                         break;
    263 
    264                 case QUNIFORM_TEXTURE_CONFIG_P2:
    265                         write_texture_p2(job, &uniforms, texstate,
    266                                          uinfo->data[i]);
    267                         break;
    268 
    269                 case QUNIFORM_TEXTURE_FIRST_LEVEL:
    270                         write_texture_first_level(job, &uniforms, texstate,
    271                                                   uinfo->data[i]);
    272                         break;
    273 
    274                 case QUNIFORM_UBO_ADDR:
    275                         cl_aligned_reloc(job, &job->uniforms, &uniforms, ubo, 0);
    276                         break;
    277 
    278                 case QUNIFORM_TEXTURE_MSAA_ADDR:
    279                         write_texture_msaa_addr(job, &uniforms,
    280                                                 texstate, uinfo->data[i]);
    281                         break;
    282 
    283                 case QUNIFORM_TEXTURE_BORDER_COLOR:
    284                         write_texture_border_color(job, &uniforms,
    285                                                    texstate, uinfo->data[i]);
    286                         break;
    287 
    288                 case QUNIFORM_TEXRECT_SCALE_X:
    289                 case QUNIFORM_TEXRECT_SCALE_Y:
    290                         cl_aligned_u32(&uniforms,
    291                                        get_texrect_scale(texstate,
    292                                                          uinfo->contents[i],
    293                                                          uinfo->data[i]));
    294                         break;
    295 
    296                 case QUNIFORM_BLEND_CONST_COLOR_X:
    297                 case QUNIFORM_BLEND_CONST_COLOR_Y:
    298                 case QUNIFORM_BLEND_CONST_COLOR_Z:
    299                 case QUNIFORM_BLEND_CONST_COLOR_W:
    300                         cl_aligned_f(&uniforms,
    301                                      CLAMP(vc4->blend_color.f.color[uinfo->contents[i] -
    302                                                                     QUNIFORM_BLEND_CONST_COLOR_X],
    303                                            0, 1));
    304                         break;
    305 
    306                 case QUNIFORM_BLEND_CONST_COLOR_RGBA: {
    307                         const uint8_t *format_swiz =
    308                                 vc4_get_format_swizzle(vc4->framebuffer.cbufs[0]->format);
    309                         uint32_t color = 0;
    310                         for (int i = 0; i < 4; i++) {
    311                                 if (format_swiz[i] >= 4)
    312                                         continue;
    313 
    314                                 color |= (vc4->blend_color.ub[format_swiz[i]] <<
    315                                           (i * 8));
    316                         }
    317                         cl_aligned_u32(&uniforms, color);
    318                         break;
    319                 }
    320 
    321                 case QUNIFORM_BLEND_CONST_COLOR_AAAA: {
    322                         uint8_t a = vc4->blend_color.ub[3];
    323                         cl_aligned_u32(&uniforms, ((a) |
    324                                                    (a << 8) |
    325                                                    (a << 16) |
    326                                                    (a << 24)));
    327                         break;
    328                 }
    329 
    330                 case QUNIFORM_STENCIL:
    331                         cl_aligned_u32(&uniforms,
    332                                        vc4->zsa->stencil_uniforms[uinfo->data[i]] |
    333                                        (uinfo->data[i] <= 1 ?
    334                                         (vc4->stencil_ref.ref_value[uinfo->data[i]] << 8) :
    335                                         0));
    336                         break;
    337 
    338                 case QUNIFORM_ALPHA_REF:
    339                         cl_aligned_f(&uniforms,
    340                                      vc4->zsa->base.alpha.ref_value);
    341                         break;
    342 
    343                 case QUNIFORM_SAMPLE_MASK:
    344                         cl_aligned_u32(&uniforms, vc4->sample_mask);
    345                         break;
    346 
    347                 case QUNIFORM_UNIFORMS_ADDRESS:
    348                         /* This will be filled in by the kernel. */
    349                         cl_aligned_u32(&uniforms, 0xd0d0d0d0);
    350                         break;
    351                 }
    352 #if 0
    353                 uint32_t written_val = *((uint32_t *)uniforms - 1);
    354                 fprintf(stderr, "%p: %d / 0x%08x (%f)\n",
    355                         shader, i, written_val, uif(written_val));
    356 #endif
    357         }
    358 
    359         cl_end(&job->uniforms, uniforms);
    360 
    361         vc4_bo_unreference(&ubo);
    362 }
    363 
    364 void
    365 vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader)
    366 {
    367         uint32_t dirty = 0;
    368 
    369         for (int i = 0; i < shader->uniforms.count; i++) {
    370                 switch (shader->uniforms.contents[i]) {
    371                 case QUNIFORM_CONSTANT:
    372                 case QUNIFORM_UNIFORMS_ADDRESS:
    373                         break;
    374                 case QUNIFORM_UNIFORM:
    375                 case QUNIFORM_UBO_ADDR:
    376                         dirty |= VC4_DIRTY_CONSTBUF;
    377                         break;
    378 
    379                 case QUNIFORM_VIEWPORT_X_SCALE:
    380                 case QUNIFORM_VIEWPORT_Y_SCALE:
    381                 case QUNIFORM_VIEWPORT_Z_OFFSET:
    382                 case QUNIFORM_VIEWPORT_Z_SCALE:
    383                         dirty |= VC4_DIRTY_VIEWPORT;
    384                         break;
    385 
    386                 case QUNIFORM_USER_CLIP_PLANE:
    387                         dirty |= VC4_DIRTY_CLIP;
    388                         break;
    389 
    390                 case QUNIFORM_TEXTURE_CONFIG_P0:
    391                 case QUNIFORM_TEXTURE_CONFIG_P1:
    392                 case QUNIFORM_TEXTURE_CONFIG_P2:
    393                 case QUNIFORM_TEXTURE_BORDER_COLOR:
    394                 case QUNIFORM_TEXTURE_FIRST_LEVEL:
    395                 case QUNIFORM_TEXTURE_MSAA_ADDR:
    396                 case QUNIFORM_TEXRECT_SCALE_X:
    397                 case QUNIFORM_TEXRECT_SCALE_Y:
    398                         /* We could flag this on just the stage we're
    399                          * compiling for, but it's not passed in.
    400                          */
    401                         dirty |= VC4_DIRTY_FRAGTEX | VC4_DIRTY_VERTTEX;
    402                         break;
    403 
    404                 case QUNIFORM_BLEND_CONST_COLOR_X:
    405                 case QUNIFORM_BLEND_CONST_COLOR_Y:
    406                 case QUNIFORM_BLEND_CONST_COLOR_Z:
    407                 case QUNIFORM_BLEND_CONST_COLOR_W:
    408                 case QUNIFORM_BLEND_CONST_COLOR_RGBA:
    409                 case QUNIFORM_BLEND_CONST_COLOR_AAAA:
    410                         dirty |= VC4_DIRTY_BLEND_COLOR;
    411                         break;
    412 
    413                 case QUNIFORM_STENCIL:
    414                 case QUNIFORM_ALPHA_REF:
    415                         dirty |= VC4_DIRTY_ZSA;
    416                         break;
    417 
    418                 case QUNIFORM_SAMPLE_MASK:
    419                         dirty |= VC4_DIRTY_SAMPLE_MASK;
    420                         break;
    421                 }
    422         }
    423 
    424         shader->uniform_dirty_bits = dirty;
    425 }
    426