radeonsi: implement 32-bit SNORM/UNORM/SSCALED/USCALED vertex formats
authorMarek Olšák <marek.olsak@amd.com>
Thu, 5 Jan 2017 23:30:12 +0000 (00:30 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 16 Jan 2017 17:07:08 +0000 (18:07 +0100)
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state.c

index ddb6ca1ae1752b643396401fca519cadc73a2799..840b3790f045843fdad9afb1bf7f0fda93d5b2b4 100644 (file)
@@ -434,7 +434,11 @@ static void declare_input_vs(
        }
 
        fix_fetch = (ctx->shader->key.mono.vs.fix_fetch >> (4 * input_index)) & 0xf;
-       if (fix_fetch) {
+
+       switch (fix_fetch) {
+       case SI_FIX_FETCH_A2_SNORM:
+       case SI_FIX_FETCH_A2_SSCALED:
+       case SI_FIX_FETCH_A2_SINT: {
                /* The hardware returns an unsigned value; convert it to a
                 * signed one.
                 */
@@ -470,6 +474,52 @@ static void declare_input_vs(
                }
 
                out[3] = tmp;
+               break;
+       }
+       case SI_FIX_FETCH_RGBA_32_UNORM:
+       case SI_FIX_FETCH_RGBX_32_UNORM:
+               for (chan = 0; chan < 4; chan++) {
+                       out[chan] = LLVMBuildBitCast(gallivm->builder, out[chan],
+                                                    ctx->i32, "");
+                       out[chan] = LLVMBuildUIToFP(gallivm->builder,
+                                                   out[chan], ctx->f32, "");
+                       out[chan] = LLVMBuildFMul(gallivm->builder, out[chan],
+                                                 LLVMConstReal(ctx->f32, 1.0 / UINT_MAX), "");
+               }
+               /* RGBX UINT returns 1 in alpha, which would be rounded to 0 by normalizing. */
+               if (fix_fetch == SI_FIX_FETCH_RGBX_32_UNORM)
+                       out[3] = LLVMConstReal(ctx->f32, 1);
+               break;
+       case SI_FIX_FETCH_RGBA_32_SNORM:
+       case SI_FIX_FETCH_RGBX_32_SNORM:
+               for (chan = 0; chan < 4; chan++) {
+                       out[chan] = LLVMBuildBitCast(gallivm->builder, out[chan],
+                                                    ctx->i32, "");
+                       out[chan] = LLVMBuildSIToFP(gallivm->builder,
+                                                   out[chan], ctx->f32, "");
+                       out[chan] = LLVMBuildFMul(gallivm->builder, out[chan],
+                                                 LLVMConstReal(ctx->f32, 1.0 / INT_MAX), "");
+               }
+               /* RGBX SINT returns 1 in alpha, which would be rounded to 0 by normalizing. */
+               if (fix_fetch == SI_FIX_FETCH_RGBX_32_SNORM)
+                       out[3] = LLVMConstReal(ctx->f32, 1);
+               break;
+       case SI_FIX_FETCH_RGBA_32_USCALED:
+               for (chan = 0; chan < 4; chan++) {
+                       out[chan] = LLVMBuildBitCast(gallivm->builder, out[chan],
+                                                    ctx->i32, "");
+                       out[chan] = LLVMBuildUIToFP(gallivm->builder,
+                                                   out[chan], ctx->f32, "");
+               }
+               break;
+       case SI_FIX_FETCH_RGBA_32_SSCALED:
+               for (chan = 0; chan < 4; chan++) {
+                       out[chan] = LLVMBuildBitCast(gallivm->builder, out[chan],
+                                                    ctx->i32, "");
+                       out[chan] = LLVMBuildSIToFP(gallivm->builder,
+                                                   out[chan], ctx->f32, "");
+               }
+               break;
        }
 }
 
index 89f9628a1f6ba27f37df069675d23fc801f66cca..5e554d9afe3c6aa2fb27b476b7aaf0f77a1d16ae 100644 (file)
@@ -236,9 +236,15 @@ enum {
 /* For VS shader key fix_fetch. */
 enum {
        SI_FIX_FETCH_NONE = 0,
-       SI_FIX_FETCH_A2_SNORM = 1,
-       SI_FIX_FETCH_A2_SSCALED = 2,
-       SI_FIX_FETCH_A2_SINT = 3,
+       SI_FIX_FETCH_A2_SNORM,
+       SI_FIX_FETCH_A2_SSCALED,
+       SI_FIX_FETCH_A2_SINT,
+       SI_FIX_FETCH_RGBA_32_UNORM,
+       SI_FIX_FETCH_RGBX_32_UNORM,
+       SI_FIX_FETCH_RGBA_32_SNORM,
+       SI_FIX_FETCH_RGBX_32_SNORM,
+       SI_FIX_FETCH_RGBA_32_USCALED,
+       SI_FIX_FETCH_RGBA_32_SSCALED,
 };
 
 struct si_shader;
index fa78a56f73ee1573dcba3f2317179f8a6ab49e91..c8d1099421cfa0350d629ad2a17c733857c2ff2c 100644 (file)
@@ -1746,14 +1746,6 @@ static uint32_t si_translate_buffer_dataformat(struct pipe_screen *screen,
                }
                break;
        case 32:
-               /* From the Southern Islands ISA documentation about MTBUF:
-                * 'Memory reads of data in memory that is 32 or 64 bits do not
-                * undergo any format conversion.'
-                */
-               if (type != UTIL_FORMAT_TYPE_FLOAT &&
-                   !desc->channel[first_non_void].pure_integer)
-                       return V_008F0C_BUF_DATA_FORMAT_INVALID;
-
                switch (desc->nr_channels) {
                case 1:
                        return V_008F0C_BUF_DATA_FORMAT_32;
@@ -1781,18 +1773,20 @@ static uint32_t si_translate_buffer_numformat(struct pipe_screen *screen,
 
        switch (desc->channel[first_non_void].type) {
        case UTIL_FORMAT_TYPE_SIGNED:
-               if (desc->channel[first_non_void].normalized)
-                       return V_008F0C_BUF_NUM_FORMAT_SNORM;
-               else if (desc->channel[first_non_void].pure_integer)
+               if (desc->channel[first_non_void].size >= 32 ||
+                   desc->channel[first_non_void].pure_integer)
                        return V_008F0C_BUF_NUM_FORMAT_SINT;
+               else if (desc->channel[first_non_void].normalized)
+                       return V_008F0C_BUF_NUM_FORMAT_SNORM;
                else
                        return V_008F0C_BUF_NUM_FORMAT_SSCALED;
                break;
        case UTIL_FORMAT_TYPE_UNSIGNED:
-               if (desc->channel[first_non_void].normalized)
-                       return V_008F0C_BUF_NUM_FORMAT_UNORM;
-               else if (desc->channel[first_non_void].pure_integer)
+               if (desc->channel[first_non_void].size >= 32 ||
+                   desc->channel[first_non_void].pure_integer)
                        return V_008F0C_BUF_NUM_FORMAT_UINT;
+               else if (desc->channel[first_non_void].normalized)
+                       return V_008F0C_BUF_NUM_FORMAT_UNORM;
                else
                        return V_008F0C_BUF_NUM_FORMAT_USCALED;
                break;
@@ -3342,6 +3336,7 @@ static void *si_create_vertex_elements(struct pipe_context *ctx,
        v->count = count;
        for (i = 0; i < count; ++i) {
                const struct util_format_description *desc;
+               const struct util_format_channel_description *channel;
                unsigned data_format, num_format;
                int first_non_void;
 
@@ -3349,6 +3344,7 @@ static void *si_create_vertex_elements(struct pipe_context *ctx,
                first_non_void = util_format_get_first_non_void_channel(elements[i].src_format);
                data_format = si_translate_buffer_dataformat(ctx->screen, desc, first_non_void);
                num_format = si_translate_buffer_numformat(ctx->screen, desc, first_non_void);
+               channel = &desc->channel[first_non_void];
 
                v->rsrc_word3[i] = S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
                                   S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) |
@@ -3370,6 +3366,26 @@ static void *si_create_vertex_elements(struct pipe_context *ctx,
                                /* This isn't actually used in OpenGL. */
                                v->fix_fetch |= (uint64_t)SI_FIX_FETCH_A2_SINT << (4 * i);
                        }
+               } else if (channel->size == 32 && !channel->pure_integer) {
+                       if (channel->type == UTIL_FORMAT_TYPE_SIGNED) {
+                               if (channel->normalized) {
+                                       if (desc->swizzle[3] == PIPE_SWIZZLE_1)
+                                               v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBX_32_SNORM << (4 * i);
+                                       else
+                                               v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBA_32_SNORM << (4 * i);
+                               } else {
+                                       v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBA_32_SSCALED << (4 * i);
+                               }
+                       } else if (channel->type == UTIL_FORMAT_TYPE_UNSIGNED) {
+                               if (channel->normalized) {
+                                       if (desc->swizzle[3] == PIPE_SWIZZLE_1)
+                                               v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBX_32_UNORM << (4 * i);
+                                       else
+                                               v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBA_32_UNORM << (4 * i);
+                               } else {
+                                       v->fix_fetch |= (uint64_t)SI_FIX_FETCH_RGBA_32_USCALED << (4 * i);
+                               }
+                       }
                }
 
                /* We work around the fact that 8_8_8 and 16_16_16 data formats