[Mesa-dev] [PATCH 3/3] radeonsi: Read rodata from ELF and append it to the end of shaders

Tom Stellard thomas.stellard at amd.com
Fri Jul 18 12:10:53 PDT 2014


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 |  5 +++++
 src/gallium/drivers/radeon/radeon_elf_util.c  |  5 +++++
 src/gallium/drivers/radeonsi/si_shader.c      | 16 +++++++++++++---
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index d82adf5..8f1a0a5 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -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;
diff --git a/src/gallium/drivers/radeon/radeon_elf_util.c b/src/gallium/drivers/radeon/radeon_elf_util.c
index 7d92962..7c5f93e 100644
--- a/src/gallium/drivers/radeon/radeon_elf_util.c
+++ b/src/gallium/drivers/radeon/radeon_elf_util.c
@@ -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);
 		}
 	}
 
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 8593bca..641e563 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2499,11 +2499,12 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader,
 {
 	unsigned r; /* llvm_compile result */
 	unsigned i;
-	uint32_t *ptr;
+	unsigned char *ptr;
 	struct radeon_shader_binary binary;
 	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));
@@ -2551,19 +2552,28 @@ 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;
 	}
 
-	ptr = (uint32_t*)sctx->b.ws->buffer_map(shader->bo->cs_buf, sctx->b.rings.gfx.cs, PIPE_TRANSFER_WRITE);
+	ptr = sctx->b.ws->buffer_map(shader->bo->cs_buf, sctx->b.rings.gfx.cs,
+					PIPE_TRANSFER_WRITE);
 	util_memcpy_cpu_to_le32(ptr, binary.code, binary.code_size);
+	/* Copy read only data if any. */
+	if (binary.rodata_size > 0) {
+		ptr += binary.code_size;
+		util_memcpy_cpu_to_le32(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;
 }
-- 
1.8.1.5



More information about the mesa-dev mailing list