radeonsi: Read rodata from ELF and append it to the end of shaders
authorTom Stellard <thomas.stellard@amd.com>
Mon, 14 Jul 2014 20:49:08 +0000 (16:49 -0400)
committerTom Stellard <thomas.stellard@amd.com>
Mon, 21 Jul 2014 14:00:09 +0000 (10:00 -0400)
The is used for programs that have arrays of constants that
are accessed using dynamic indices.  The shader will compute
the base address of the constants and then access them using
SMRD instructions.

src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/radeon_elf_util.c
src/gallium/drivers/radeonsi/si_shader.c

index d82adf5d387cb7e0160213d9dec5f92744f2742c..8f1a0a5944c53ae72bc77de0b0954db06db9a954 100644 (file)
@@ -108,6 +108,11 @@ struct radeon_shader_binary {
        unsigned char *config;
        unsigned config_size;
 
+       /** Constant data accessed by the shader.  This will be uploaded
+        * into a constant buffer. */
+       unsigned char *rodata;
+       unsigned rodata_size;
+
        /** Set to 1 if the disassembly for this binary has been dumped to
         *  stderr. */
        int disassembled;
index 7d9296239374e2af61897011319574fab0a122b9..7c5f93ef67a439546d78fd3cd08fee4179844ed9 100644 (file)
@@ -80,6 +80,11 @@ void radeon_elf_read(const char *elf_data, unsigned elf_size,
                        fprintf(stderr, "\nShader Disassembly:\n\n");
                        fprintf(stderr, "%.*s\n", (int)section_data->d_size,
                                                  (char *)section_data->d_buf);
+               } else if (!strncmp(name, ".rodata", 7)) {
+                       section_data = elf_getdata(section, section_data);
+                       binary->rodata_size = section_data->d_size;
+                       binary->rodata = MALLOC(binary->rodata_size * sizeof(unsigned char));
+                       memcpy(binary->rodata, section_data->d_buf, binary->rodata_size);
                }
        }
 
index 4c3e83f9605d6d36fd1bcbf9a6f724fa593e7fa0..be18dfc88c7d990f42b5d9f25f84bd433ff9d3ee 100644 (file)
@@ -2558,6 +2558,7 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader,
        bool dump = r600_can_dump_shader(&sctx->screen->b,
                        shader->selector ? shader->selector->tokens : NULL);
        const char * gpu_family = r600_get_llvm_processor_name(sctx->screen->b.family);
+       unsigned code_size;
 
        /* Use LLVM to compile shader */
        memset(&binary, 0, sizeof(binary));
@@ -2605,9 +2606,10 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader,
        }
 
        /* copy new shader */
+       code_size = binary.code_size + binary.rodata_size;
        r600_resource_reference(&shader->bo, NULL);
        shader->bo = si_resource_create_custom(sctx->b.b.screen, PIPE_USAGE_IMMUTABLE,
-                                              binary.code_size);
+                                              code_size);
        if (shader->bo == NULL) {
                return -ENOMEM;
        }
@@ -2617,13 +2619,22 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader,
                for (i = 0; i < binary.code_size / 4; ++i) {
                        ptr[i] = util_cpu_to_le32((*(uint32_t*)(binary.code + i*4)));
                }
+               ptr += (binary.code_size / 4);
+               for (i = 0; i < binary.rodata_size / 4; ++i) {
+                       ptr[i] = util_cpu_to_le32((*(uint32_t*)(binary.rodata + i * 4)));
+               }
        } else {
                memcpy(ptr, binary.code, binary.code_size);
+               if (binary.rodata_size > 0) {
+                       ptr += (binary.code_size / 4);
+                       memcpy(ptr, binary.rodata, binary.rodata_size);
+               }
        }
        sctx->b.ws->buffer_unmap(shader->bo->cs_buf);
 
        free(binary.code);
        free(binary.config);
+       free(binary.rodata);
 
        return r;
 }