Home | History | Annotate | Download | only in svga
      1 /**********************************************************
      2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 #include "util/u_inlines.h"
     27 #include "pipe/p_defines.h"
     28 
     29 #include "svga_screen.h"
     30 #include "svga_context.h"
     31 #include "svga_state.h"
     32 #include "svga_cmd.h"
     33 #include "svga_tgsi.h"
     34 #include "svga_debug.h"
     35 
     36 #include "svga_hw_reg.h"
     37 
     38 
     39 /*
     40  * Don't try to send more than 4kb of successive constants.
     41  */
     42 #define MAX_CONST_REG_COUNT 256  /**< number of float[4] constants */
     43 
     44 
     45 
     46 /**
     47  * Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_*
     48  */
     49 static int
     50 svga_shader_type(unsigned shader)
     51 {
     52    assert(PIPE_SHADER_VERTEX + 1 == SVGA3D_SHADERTYPE_VS);
     53    assert(PIPE_SHADER_FRAGMENT + 1 == SVGA3D_SHADERTYPE_PS);
     54    assert(shader <= PIPE_SHADER_FRAGMENT);
     55    return shader + 1;
     56 }
     57 
     58 
     59 /**
     60  * Check and emit one shader constant register.
     61  * \param shader  PIPE_SHADER_FRAGMENT or PIPE_SHADER_VERTEX
     62  * \param i  which float[4] constant to change
     63  * \param value  the new float[4] value
     64  */
     65 static enum pipe_error
     66 emit_const(struct svga_context *svga, unsigned shader, unsigned i,
     67            const float *value)
     68 {
     69    enum pipe_error ret = PIPE_OK;
     70 
     71    assert(shader < PIPE_SHADER_TYPES);
     72    assert(i < SVGA3D_CONSTREG_MAX);
     73 
     74    if (memcmp(svga->state.hw_draw.cb[shader][i], value,
     75               4 * sizeof(float)) != 0) {
     76       if (SVGA_DEBUG & DEBUG_CONSTS)
     77          debug_printf("%s %s %u: %f %f %f %f\n",
     78                       __FUNCTION__,
     79                       shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
     80                       i,
     81                       value[0],
     82                       value[1],
     83                       value[2],
     84                       value[3]);
     85 
     86       ret = SVGA3D_SetShaderConst( svga->swc,
     87                                    i,
     88                                    svga_shader_type(shader),
     89                                    SVGA3D_CONST_TYPE_FLOAT,
     90                                    value );
     91       if (ret != PIPE_OK)
     92          return ret;
     93 
     94       memcpy(svga->state.hw_draw.cb[shader][i], value, 4 * sizeof(float));
     95    }
     96 
     97    return ret;
     98 }
     99 
    100 
    101 /*
    102  * Check and emit a range of shader constant registers, trying to coalesce
    103  * successive shader constant updates in a single command in order to save
    104  * space on the command buffer.  This is a HWv8 feature.
    105  */
    106 static enum pipe_error
    107 emit_const_range(struct svga_context *svga,
    108                  unsigned shader,
    109                  unsigned offset,
    110                  unsigned count,
    111                  const float (*values)[4])
    112 {
    113    unsigned i, j;
    114    enum pipe_error ret;
    115 
    116 #ifdef DEBUG
    117    if (offset + count > SVGA3D_CONSTREG_MAX) {
    118       debug_printf("svga: too many constants (offset + count = %u)\n",
    119                    offset + count);
    120    }
    121 #endif
    122 
    123    if (offset > SVGA3D_CONSTREG_MAX) {
    124       /* This isn't OK, but if we propagate an error all the way up we'll
    125        * just get into more trouble.
    126        * XXX note that offset is always zero at this time so this is moot.
    127        */
    128       return PIPE_OK;
    129    }
    130 
    131    if (offset + count > SVGA3D_CONSTREG_MAX) {
    132       /* Just drop the extra constants for now.
    133        * Ideally we should not have allowed the app to create a shader
    134        * that exceeds our constant buffer size but there's no way to
    135        * express that in gallium at this time.
    136        */
    137       count = SVGA3D_CONSTREG_MAX - offset;
    138    }
    139 
    140    i = 0;
    141    while (i < count) {
    142       if (memcmp(svga->state.hw_draw.cb[shader][offset + i],
    143                  values[i],
    144                  4 * sizeof(float)) != 0) {
    145          /* Found one dirty constant
    146           */
    147          if (SVGA_DEBUG & DEBUG_CONSTS)
    148             debug_printf("%s %s %d: %f %f %f %f\n",
    149                          __FUNCTION__,
    150                          shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
    151                          offset + i,
    152                          values[i][0],
    153                          values[i][1],
    154                          values[i][2],
    155                          values[i][3]);
    156 
    157          /* Look for more consecutive dirty constants.
    158           */
    159          j = i + 1;
    160          while (j < count &&
    161                 j < i + MAX_CONST_REG_COUNT &&
    162                 memcmp(svga->state.hw_draw.cb[shader][offset + j],
    163                        values[j],
    164                        4 * sizeof(float)) != 0) {
    165 
    166             if (SVGA_DEBUG & DEBUG_CONSTS)
    167                debug_printf("%s %s %d: %f %f %f %f\n",
    168                             __FUNCTION__,
    169                             shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
    170                             offset + j,
    171                             values[j][0],
    172                             values[j][1],
    173                             values[j][2],
    174                             values[j][3]);
    175 
    176             ++j;
    177          }
    178 
    179          assert(j >= i + 1);
    180 
    181          /* Send them all together.
    182           */
    183          ret = SVGA3D_SetShaderConsts(svga->swc,
    184                                       offset + i, j - i,
    185                                       svga_shader_type(shader),
    186                                       SVGA3D_CONST_TYPE_FLOAT,
    187                                       values + i);
    188          if (ret != PIPE_OK) {
    189             return ret;
    190          }
    191 
    192          /*
    193           * Local copy of the hardware state.
    194           */
    195          memcpy(svga->state.hw_draw.cb[shader][offset + i],
    196                 values[i],
    197                 (j - i) * 4 * sizeof(float));
    198 
    199          i = j + 1;
    200       } else {
    201          ++i;
    202       }
    203    }
    204 
    205    return PIPE_OK;
    206 }
    207 
    208 
    209 /**
    210  * Emit all the constants in a constant buffer for a shader stage.
    211  */
    212 static enum pipe_error
    213 emit_consts(struct svga_context *svga, unsigned shader)
    214 {
    215    struct svga_screen *ss = svga_screen(svga->pipe.screen);
    216    struct pipe_transfer *transfer = NULL;
    217    unsigned count;
    218    const float (*data)[4] = NULL;
    219    unsigned i;
    220    enum pipe_error ret = PIPE_OK;
    221    const unsigned offset = 0;
    222 
    223    assert(shader < PIPE_SHADER_TYPES);
    224 
    225    if (svga->curr.cb[shader] == NULL)
    226       goto done;
    227 
    228    count = svga->curr.cb[shader]->width0 / (4 * sizeof(float));
    229 
    230    data = (const float (*)[4])pipe_buffer_map(&svga->pipe,
    231                                               svga->curr.cb[shader],
    232                                               PIPE_TRANSFER_READ,
    233 					      &transfer);
    234    if (data == NULL) {
    235       ret = PIPE_ERROR_OUT_OF_MEMORY;
    236       goto done;
    237    }
    238 
    239    if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
    240       ret = emit_const_range( svga, shader, offset, count, data );
    241       if (ret != PIPE_OK) {
    242          goto done;
    243       }
    244    } else {
    245       for (i = 0; i < count; i++) {
    246          ret = emit_const( svga, shader, offset + i, data[i] );
    247          if (ret != PIPE_OK) {
    248             goto done;
    249          }
    250       }
    251    }
    252 
    253 done:
    254    if (data)
    255       pipe_buffer_unmap(&svga->pipe, transfer);
    256 
    257    return ret;
    258 }
    259 
    260 
    261 static enum pipe_error
    262 emit_fs_consts(struct svga_context *svga, unsigned dirty)
    263 {
    264    const struct svga_shader_result *result = svga->state.hw_draw.fs;
    265    enum pipe_error ret = PIPE_OK;
    266 
    267    ret = emit_consts( svga, PIPE_SHADER_FRAGMENT );
    268    if (ret != PIPE_OK)
    269       return ret;
    270 
    271    /* The internally generated fragment shader for xor blending
    272     * doesn't have a 'result' struct.  It should be fixed to avoid
    273     * this special case, but work around it with a NULL check:
    274     */
    275    if (result) {
    276       const struct svga_fs_compile_key *key = &result->key.fkey;
    277       if (key->num_unnormalized_coords) {
    278          const unsigned offset =
    279             result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
    280          unsigned i;
    281 
    282          for (i = 0; i < key->num_textures; i++) {
    283             if (key->tex[i].unnormalized) {
    284                struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
    285                float data[4];
    286 
    287                data[0] = 1.0f / (float) tex->width0;
    288                data[1] = 1.0f / (float) tex->height0;
    289                data[2] = 1.0f;
    290                data[3] = 1.0f;
    291 
    292                ret = emit_const(svga,
    293                                 PIPE_SHADER_FRAGMENT,
    294                                 key->tex[i].width_height_idx + offset,
    295                                 data);
    296                if (ret != PIPE_OK) {
    297                   return ret;
    298                }
    299             }
    300          }
    301       }
    302    }
    303 
    304    return PIPE_OK;
    305 }
    306 
    307 
    308 struct svga_tracked_state svga_hw_fs_constants =
    309 {
    310    "hw fs params",
    311    (SVGA_NEW_FS_CONST_BUFFER |
    312     SVGA_NEW_FS_RESULT |
    313     SVGA_NEW_TEXTURE_BINDING),
    314    emit_fs_consts
    315 };
    316 
    317 
    318 
    319 static enum pipe_error
    320 emit_vs_consts(struct svga_context *svga, unsigned dirty)
    321 {
    322    const struct svga_shader_result *result = svga->state.hw_draw.vs;
    323    const struct svga_vs_compile_key *key;
    324    enum pipe_error ret = PIPE_OK;
    325    unsigned offset;
    326 
    327    /* SVGA_NEW_VS_RESULT
    328     */
    329    if (result == NULL)
    330       return PIPE_OK;
    331 
    332    key = &result->key.vkey;
    333 
    334    /* SVGA_NEW_VS_CONST_BUFFER
    335     */
    336    ret = emit_consts( svga, PIPE_SHADER_VERTEX );
    337    if (ret != PIPE_OK)
    338       return ret;
    339 
    340    /* offset = number of constants in the VS const buffer */
    341    offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
    342 
    343    /* SVGA_NEW_VS_PRESCALE
    344     * Put the viewport pre-scale/translate values into the const buffer.
    345     */
    346    if (key->need_prescale) {
    347       ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
    348                         svga->state.hw_clear.prescale.scale );
    349       if (ret != PIPE_OK)
    350          return ret;
    351 
    352       ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
    353                         svga->state.hw_clear.prescale.translate );
    354       if (ret != PIPE_OK)
    355          return ret;
    356    }
    357 
    358    return PIPE_OK;
    359 }
    360 
    361 
    362 struct svga_tracked_state svga_hw_vs_constants =
    363 {
    364    "hw vs params",
    365    (SVGA_NEW_PRESCALE |
    366     SVGA_NEW_VS_CONST_BUFFER |
    367     SVGA_NEW_VS_RESULT),
    368    emit_vs_consts
    369 };
    370