Mesa (master): r300g: FS constants emission rework

Marek Olšák mareko at kemper.freedesktop.org
Mon Apr 12 02:16:42 UTC 2010


Module: Mesa
Branch: master
Commit: 953a309de9204490edcd011e700c06c7c25c0b9e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=953a309de9204490edcd011e700c06c7c25c0b9e

Author: Marek Olšák <maraeo at gmail.com>
Date:   Sun Apr 11 23:00:16 2010 +0200

r300g: FS constants emission rework

* The constant buffer emission is separated from RC state variables emission.
* The immediates are emitted with FS code.

---

 src/gallium/drivers/r300/r300_emit.c       |  145 ++++++++++++++++++++++++----
 src/gallium/drivers/r300/r300_emit.h       |    6 +
 src/gallium/drivers/r300/r300_fs.c         |   20 ++++
 src/gallium/drivers/r300/r300_fs.h         |    5 +
 src/gallium/drivers/r300/r300_tgsi_to_rc.c |    1 -
 5 files changed, 156 insertions(+), 21 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 63cd41a..20d1c24 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -237,12 +237,17 @@ void r300_emit_fragment_program_code(struct r300_context* r300,
                                      struct rX00_fragment_program_code* generic_code)
 {
     struct r300_fragment_program_code * code = &generic_code->code.r300;
-    int i;
+    unsigned i;
+    unsigned imm_count = r300->fs->shader->immediates_count;
+    unsigned imm_first = r300->fs->shader->externals_count;
+    unsigned imm_end = generic_code->constants.Count;
+    struct rc_constant *constants = generic_code->constants.Constants;
     CS_LOCALS(r300);
 
     BEGIN_CS(15 +
              code->alu.length * 4 +
-             (code->tex.length ? (1 + code->tex.length) : 0));
+             (code->tex.length ? (1 + code->tex.length) : 0) +
+             (imm_count ? imm_count * 5 : 0));
 
     OUT_CS_REG(R300_US_CONFIG, code->config);
     OUT_CS_REG(R300_US_PIXSIZE, code->pixsize);
@@ -274,24 +279,38 @@ void r300_emit_fragment_program_code(struct r300_context* r300,
             OUT_CS(code->tex.inst[i]);
     }
 
+    /* Emit immediates. */
+    if (imm_count) {
+        for(i = imm_first; i < imm_end; ++i) {
+            if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+                const float *data = constants[i].u.Immediate;
+
+                OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
+                OUT_CS(pack_float24(data[0]));
+                OUT_CS(pack_float24(data[1]));
+                OUT_CS(pack_float24(data[2]));
+                OUT_CS(pack_float24(data[3]));
+            }
+        }
+    }
     END_CS;
 }
 
 void r300_emit_fs_constant_buffer(struct r300_context* r300,
                                   struct rc_constant_list* constants)
 {
-    int i;
+    unsigned i, count = r300->fs->shader->externals_count;
     CS_LOCALS(r300);
 
-    if (constants->Count == 0)
+    if (count == 0)
         return;
 
-    BEGIN_CS(constants->Count * 4 + 1);
-    OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, constants->Count * 4);
-    for(i = 0; i < constants->Count; ++i) {
-        const float * data = get_shader_constant(r300,
-                                                 &constants->Constants[i],
-                                                 &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+    BEGIN_CS(count * 4 + 1);
+    OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4);
+    for(i = 0; i < count; ++i) {
+        assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
+        const float *data =
+            r300->shader_constants[PIPE_SHADER_FRAGMENT].constants[i];
         OUT_CS(pack_float24(data[0]));
         OUT_CS(pack_float24(data[1]));
         OUT_CS(pack_float24(data[2]));
@@ -300,6 +319,34 @@ void r300_emit_fs_constant_buffer(struct r300_context* r300,
     END_CS;
 }
 
+void r300_emit_fs_constant_rc_state(struct r300_context* r300,
+                                    struct rc_constant_list* constants)
+{
+    unsigned i;
+    unsigned count = r300->fs->shader->rc_state_count;
+    unsigned first = r300->fs->shader->externals_count;
+    unsigned end = constants->Count;
+    CS_LOCALS(r300);
+
+    if (count == 0)
+        return;
+
+    BEGIN_CS(count * 5);
+    for(i = first; i < end; ++i) {
+        if (constants->Constants[i].Type == RC_CONSTANT_STATE) {
+            const float *data = get_shader_constant(r300,
+                                                    &constants->Constants[i], 0);
+
+            OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
+            OUT_CS(pack_float24(data[0]));
+            OUT_CS(pack_float24(data[1]));
+            OUT_CS(pack_float24(data[2]));
+            OUT_CS(pack_float24(data[3]));
+        }
+    }
+    END_CS;
+}
+
 static void r300_emit_fragment_depth_config(struct r300_context* r300,
                                             struct r300_fragment_shader* fs)
 {
@@ -320,11 +367,16 @@ void r500_emit_fragment_program_code(struct r300_context* r300,
                                      struct rX00_fragment_program_code* generic_code)
 {
     struct r500_fragment_program_code * code = &generic_code->code.r500;
-    int i;
+    unsigned i;
+    unsigned imm_count = r300->fs->shader->immediates_count;
+    unsigned imm_first = r300->fs->shader->externals_count;
+    unsigned imm_end = generic_code->constants.Count;
+    struct rc_constant *constants = generic_code->constants.Constants;
     CS_LOCALS(r300);
 
     BEGIN_CS(13 +
-             ((code->inst_end + 1) * 6));
+             ((code->inst_end + 1) * 6) +
+             (imm_count ? imm_count * 7 : 0));
     OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
     OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx);
     OUT_CS_REG(R500_US_CODE_RANGE,
@@ -344,25 +396,43 @@ void r500_emit_fragment_program_code(struct r300_context* r300,
         OUT_CS(code->inst[i].inst5);
     }
 
+    /* Emit immediates. */
+    if (imm_count) {
+        for(i = imm_first; i < imm_end; ++i) {
+            if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+                const float *data = constants[i].u.Immediate;
+
+                OUT_CS_REG(R500_GA_US_VECTOR_INDEX,
+                           R500_GA_US_VECTOR_INDEX_TYPE_CONST |
+                           (i & R500_GA_US_VECTOR_INDEX_MASK));
+                OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
+                OUT_CS_32F(data[0]);
+                OUT_CS_32F(data[1]);
+                OUT_CS_32F(data[2]);
+                OUT_CS_32F(data[3]);
+            }
+        }
+    }
     END_CS;
 }
 
 void r500_emit_fs_constant_buffer(struct r300_context* r300,
                                   struct rc_constant_list* constants)
 {
-    int i;
+    unsigned i, count = r300->fs->shader->externals_count;
     CS_LOCALS(r300);
 
-    if (constants->Count == 0)
+    if (count == 0)
         return;
 
-    BEGIN_CS(constants->Count * 4 + 3);
+    BEGIN_CS(count * 4 + 3);
     OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST);
-    OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4);
-    for (i = 0; i < constants->Count; i++) {
-        const float * data = get_shader_constant(r300,
-                                                 &constants->Constants[i],
-                                                 &r300->shader_constants[PIPE_SHADER_FRAGMENT]);
+    OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4);
+    for(i = 0; i < count; ++i) {
+        assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
+        const float *data =
+            r300->shader_constants[PIPE_SHADER_FRAGMENT].constants[i];
+
         OUT_CS_32F(data[0]);
         OUT_CS_32F(data[1]);
         OUT_CS_32F(data[2]);
@@ -371,6 +441,37 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300,
     END_CS;
 }
 
+void r500_emit_fs_constant_rc_state(struct r300_context* r300,
+                                    struct rc_constant_list* constants)
+{
+    unsigned i;
+    unsigned count = r300->fs->shader->rc_state_count;
+    unsigned first = r300->fs->shader->externals_count;
+    unsigned end = constants->Count;
+    CS_LOCALS(r300);
+
+    if (count == 0)
+        return;
+
+    BEGIN_CS(count * 7);
+    for(i = first; i < end; ++i) {
+        if (constants->Constants[i].Type == RC_CONSTANT_STATE) {
+            const float *data = get_shader_constant(r300,
+                                                    &constants->Constants[i], 0);
+
+            OUT_CS_REG(R500_GA_US_VECTOR_INDEX,
+                       R500_GA_US_VECTOR_INDEX_TYPE_CONST |
+                       (i & R500_GA_US_VECTOR_INDEX_MASK));
+            OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
+            OUT_CS_32F(data[0]);
+            OUT_CS_32F(data[1]);
+            OUT_CS_32F(data[2]);
+            OUT_CS_32F(data[3]);
+        }
+    }
+    END_CS;
+}
+
 void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
 {
     struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
@@ -1099,9 +1200,13 @@ void r300_emit_dirty_state(struct r300_context* r300)
         if (r300screen->caps.is_r500) {
             r500_emit_fs_constant_buffer(r300,
                                          &r300->fs->shader->code.constants);
+            r500_emit_fs_constant_rc_state(r300,
+                                           &r300->fs->shader->code.constants);
         } else {
             r300_emit_fs_constant_buffer(r300,
                                          &r300->fs->shader->code.constants);
+            r300_emit_fs_constant_rc_state(r300,
+                                           &r300->fs->shader->code.constants);
         }
         r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS;
     }
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 27251a6..19ab430 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -49,12 +49,18 @@ void r300_emit_fragment_program_code(struct r300_context* r300,
 void r300_emit_fs_constant_buffer(struct r300_context* r300,
                                   struct rc_constant_list* constants);
 
+void r300_emit_fs_constant_rc_state(struct r300_context* r300,
+                                    struct rc_constant_list* constants);
+
 void r500_emit_fragment_program_code(struct r300_context* r300,
                                      struct rX00_fragment_program_code* generic_code);
 
 void r500_emit_fs_constant_buffer(struct r300_context* r300,
                                   struct rc_constant_list* constants);
 
+void r500_emit_fs_constant_rc_state(struct r300_context* r300,
+                                    struct rc_constant_list* constants);
+
 void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state);
 
 void r300_emit_query_start(struct r300_context* r300);
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index c3f51ec..4969c14 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -192,6 +192,7 @@ static void r300_translate_fragment_shader(
     struct r300_fragment_program_compiler compiler;
     struct tgsi_to_rc ttr;
     int wpos;
+    unsigned i;
 
     tgsi_scan_shader(tokens, &shader->info);
     r300_shader_read_fs_inputs(&shader->info, &shader->inputs);
@@ -240,6 +241,7 @@ static void r300_translate_fragment_shader(
 
     /* Invoke the compiler */
     r3xx_compile_fragment_program(&compiler);
+
     if (compiler.Base.Error) {
         fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
                 " instead.\n", compiler.Base.ErrorMsg);
@@ -252,6 +254,24 @@ static void r300_translate_fragment_shader(
         r300_dummy_fragment_shader(r300, shader);
     }
 
+    /* Initialize numbers of constants for each type. */
+    shader->externals_count = ttr.immediate_offset;
+    shader->immediates_count = 0;
+    shader->rc_state_count = 0;
+
+    for (i = shader->externals_count; i < shader->code.constants.Count; i++) {
+        switch (shader->code.constants.Constants[i].Type) {
+            case RC_CONSTANT_IMMEDIATE:
+                ++shader->immediates_count;
+                break;
+            case RC_CONSTANT_STATE:
+                ++shader->rc_state_count;
+                break;
+            default:
+                assert(0);
+        }
+    }
+
     /* And, finally... */
     rc_destroy(&compiler.Base);
 }
diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h
index 0feba15..18da5f7 100644
--- a/src/gallium/drivers/r300/r300_fs.h
+++ b/src/gallium/drivers/r300/r300_fs.h
@@ -41,6 +41,11 @@ struct r300_fragment_shader_code {
     /* Bits 0-15: TRUE if it's a shadow sampler, FALSE otherwise. */
     unsigned shadow_samplers;
 
+    /* Numbers of constants for each type. */
+    unsigned externals_count;
+    unsigned immediates_count;
+    unsigned rc_state_count;
+
     struct r300_fragment_program_external_state compare_state;
     struct rX00_fragment_program_code code;
 
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index 3b3802e..21a1c45 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -383,4 +383,3 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
 
     rc_calculate_inputs_outputs(ttr->compiler);
 }
-




More information about the mesa-commit mailing list