radv: Disable shader disassembly when no disassembler is available

ACO relies on LLVM to disassemble AMD shaders for ISAs newer than GFX7,
so disassembly needs to be skipped when LLVM is not enabled.

For vkGetPipelineExecutableInternalRepresentationsKHR and vkGetShaderInfoAMD,
the disassembly will not be reported anymore if it can't be generated.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11319>
This commit is contained in:
Tony Wasserka 2021-06-11 12:37:50 +02:00
parent d5ac15c0e4
commit 3c1802accd
5 changed files with 55 additions and 14 deletions

View File

@ -198,19 +198,27 @@ aco_compile_shader(unsigned shader_count, struct nir_shader* const* shaders,
std::string disasm;
if (get_disasm) {
char* data = NULL;
size_t disasm_size = 0;
struct u_memstream mem;
if (u_memstream_open(&mem, &data, &disasm_size)) {
FILE* const memf = u_memstream_get(&mem);
aco::print_asm(program.get(), code, exec_size / 4u, memf);
fputc(0, memf);
u_memstream_close(&mem);
}
if (check_print_asm_support(program.get())) {
char* data = NULL;
size_t disasm_size = 0;
struct u_memstream mem;
if (u_memstream_open(&mem, &data, &disasm_size)) {
FILE* const memf = u_memstream_get(&mem);
aco::print_asm(program.get(), code, exec_size / 4u, memf);
fputc(0, memf);
u_memstream_close(&mem);
}
disasm = std::string(data, data + disasm_size);
size += disasm_size;
free(data);
disasm = std::string(data, data + disasm_size);
size += disasm_size;
free(data);
} else {
fprintf(stderr, "Shader disassembly is not supported in the current configuration"
#ifndef LLVM_AVAILABLE
" (LLVM not available)"
#endif
".\n");
}
}
size_t stats_size = 0;

View File

@ -2168,6 +2168,11 @@ void insert_wait_states(Program* program);
void insert_NOPs(Program* program);
void form_hard_clauses(Program* program);
unsigned emit_program(Program* program, std::vector<uint32_t>& code);
/**
* Returns true if print_asm can disassemble the given program for the current build/runtime
* configuration
*/
bool check_print_asm_support(Program* program);
bool print_asm(Program* program, std::vector<uint32_t>& binary, unsigned exec_size, FILE* output);
bool validate_ir(Program* program);
bool validate_ra(Program* program);

View File

@ -24,11 +24,13 @@
#include "aco_ir.h"
#ifdef LLVM_AVAILABLE
#include "llvm/ac_llvm_util.h"
#include "llvm-c/Disassembler.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#endif
#include <array>
#include <iomanip>
@ -142,6 +144,7 @@ fail:
#endif
}
#ifdef LLVM_AVAILABLE
std::pair<bool, size_t>
disasm_instr(chip_class chip, LLVMDisasmContextRef disasm, uint32_t* binary, unsigned exec_size,
size_t pos, char* outline, unsigned outline_size)
@ -284,15 +287,38 @@ print_asm_llvm(Program* program, std::vector<uint32_t>& binary, unsigned exec_si
return invalid;
}
#endif /* LLVM_AVAILABLE */
} /* end namespace */
bool
check_print_asm_support(Program* program)
{
#ifdef LLVM_AVAILABLE
if (program->chip_class >= GFX8) {
/* LLVM disassembler only supports GFX8+ */
return true;
}
#endif
#ifndef _WIN32
/* Check if CLRX disassembler binary is available and can disassemble the program */
return to_clrx_device_name(program->chip_class, program->family) &&
system("clrxdisasm --version") == 0;
#else
return false;
#endif
}
/* Returns true on failure */
bool
print_asm(Program* program, std::vector<uint32_t>& binary, unsigned exec_size, FILE* output)
{
#ifdef LLVM_AVAILABLE
if (program->chip_class >= GFX8) {
return print_asm_llvm(program, binary, exec_size, output);
}
#endif
return print_asm_clrx(program, binary, output);
}

View File

@ -6095,7 +6095,7 @@ radv_GetPipelineExecutableInternalRepresentationsKHR(
++p;
/* Disassembler */
if (p < end) {
if (p < end && shader->disasm_string) {
p->isText = true;
desc_copy(p->name, "Assembly");
desc_copy(p->description, "Final Assembly");

View File

@ -1876,7 +1876,9 @@ radv_GetShaderInfoAMD(VkDevice _device, VkPipeline _pipeline, VkShaderStageFlagB
fprintf(memf, "%s:\n", radv_get_shader_name(&variant->info, stage));
fprintf(memf, "%s\n\n", variant->ir_string);
fprintf(memf, "%s\n\n", variant->disasm_string);
if (variant->disasm_string) {
fprintf(memf, "%s\n\n", variant->disasm_string);
}
radv_dump_shader_stats(device, pipeline, stage, memf);
u_memstream_close(&mem);