Module: Mesa Branch: master Commit: af8d488ea5e13219c67c132a3edfa2e7a698746d URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=af8d488ea5e13219c67c132a3edfa2e7a698746d
Author: James Park <jpar...@lagfreegames.com> Date: Tue Aug 4 10:58:11 2020 -0700 util,ac,aco,radv: Cross-platform memstream API POSIX memstream is not available on Windows. Reviewed-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7143> --- src/amd/common/ac_debug.c | 7 ++- src/amd/compiler/aco_assembler.cpp | 7 ++- src/amd/compiler/aco_instruction_selection.cpp | 7 ++- src/amd/compiler/aco_interface.cpp | 12 ++-- src/amd/compiler/aco_optimizer.cpp | 7 ++- src/amd/compiler/aco_validate.cpp | 14 +++-- src/amd/vulkan/radv_shader.c | 16 +++-- src/util/memstream.c | 81 ++++++++++++++++++++++++++ src/util/memstream.h | 67 +++++++++++++++++++++ src/util/meson.build | 2 + 10 files changed, 197 insertions(+), 23 deletions(-) diff --git a/src/amd/common/ac_debug.c b/src/amd/common/ac_debug.c index 246a89ee86a..5acf4928d0b 100644 --- a/src/amd/common/ac_debug.c +++ b/src/amd/common/ac_debug.c @@ -33,6 +33,7 @@ #include "sid.h" #include "sid_tables.h" +#include "util/memstream.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_string.h" @@ -584,10 +585,12 @@ void ac_parse_ib_chunk(FILE *f, uint32_t *ib_ptr, int num_dw, const int *trace_i char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); ib.f = memf; ac_do_parse_ib(memf, &ib); - fclose(memf); + u_memstream_close(&mem); if (out) { format_ib_output(f, out); diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp index ac9339c99eb..755bed09e1a 100644 --- a/src/amd/compiler/aco_assembler.cpp +++ b/src/amd/compiler/aco_assembler.cpp @@ -5,6 +5,7 @@ #include "aco_builder.h" #include "common/sid.h" #include "ac_shader_util.h" +#include "util/memstream.h" #include "util/u_math.h" namespace aco { @@ -83,11 +84,13 @@ void emit_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* if (opcode == (uint32_t)-1) { char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); fprintf(memf, "Unsupported opcode: "); aco_print_instr(instr, memf); - fclose(memf); + u_memstream_close(&mem); aco_err(ctx.program, out); free(out); diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 1da9ea41d98..c57b6709ac6 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -34,6 +34,7 @@ #include "aco_interface.h" #include "aco_instruction_selection.h" #include "util/fast_idiv_by_const.h" +#include "util/memstream.h" #include "ac_exp_param.h" #include "sid.h" @@ -50,11 +51,13 @@ static void _isel_err(isel_context *ctx, const char *file, unsigned line, { char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); fprintf(memf, "%s: ", msg); nir_print_instr(instr, memf); - fclose(memf); + u_memstream_close(&mem); _aco_err(ctx->program, file, line, out); free(out); diff --git a/src/amd/compiler/aco_interface.cpp b/src/amd/compiler/aco_interface.cpp index 9b3f88e8a26..55ddd19b638 100644 --- a/src/amd/compiler/aco_interface.cpp +++ b/src/amd/compiler/aco_interface.cpp @@ -23,6 +23,7 @@ #include "aco_interface.h" #include "aco_ir.h" +#include "util/memstream.h" #include "vulkan/radv_shader.h" #include "vulkan/radv_shader_args.h" @@ -110,11 +111,12 @@ void aco_compile_shader(unsigned shader_count, if (args->options->record_ir) { char *data = NULL; size_t size = 0; - FILE *f = open_memstream(&data, &size); - if (f) { - aco_print_program(program.get(), f); - fputc(0, f); - fclose(f); + u_memstream mem; + if (u_memstream_open(&mem, &data, &size)) { + FILE *const memf = u_memstream_get(&mem); + aco_print_program(program.get(), memf); + fputc(0, memf); + u_memstream_close(&mem); } llvm_ir = std::string(data, data + size); diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index a21fb21d1fa..22497a10452 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -30,6 +30,7 @@ #include "aco_ir.h" #include "util/half_float.h" +#include "util/memstream.h" #include "util/u_math.h" namespace aco { @@ -40,11 +41,13 @@ void perfwarn(Program *program, bool cond, const char *msg, Instruction *instr) if (cond) { char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); fprintf(memf, "%s: ", msg); aco_print_instr(instr, memf); - fclose(memf); + u_memstream_close(&mem); aco_perfwarn(program, out); free(out); diff --git a/src/amd/compiler/aco_validate.cpp b/src/amd/compiler/aco_validate.cpp index d8886cd31b7..ef3b4c78cba 100644 --- a/src/amd/compiler/aco_validate.cpp +++ b/src/amd/compiler/aco_validate.cpp @@ -27,6 +27,8 @@ #include <array> #include <map> +#include "util/memstream.h" + namespace aco { static void aco_log(Program *program, enum radv_compiler_debug_level level, @@ -78,11 +80,13 @@ bool validate_ir(Program* program) if (!check) { char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); fprintf(memf, "%s: ", msg); aco_print_instr(instr, memf); - fclose(memf); + u_memstream_close(&mem); aco_err(program, out); free(out); @@ -520,7 +524,9 @@ bool ra_fail(Program *program, Location loc, Location loc2, const char *fmt, ... char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); fprintf(memf, "RA error found at instruction in BB%d:\n", loc.block->index); if (loc.instr) { @@ -534,7 +540,7 @@ bool ra_fail(Program *program, Location loc, Location loc2, const char *fmt, ... aco_print_instr(loc2.instr, memf); } fprintf(memf, "\n\n"); - fclose(memf); + u_memstream_close(&mem); aco_err(program, out); free(out); diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 9d25b4f0b89..118c0bbeb08 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -25,6 +25,7 @@ * IN THE SOFTWARE. */ +#include "util/memstream.h" #include "util/mesa-sha1.h" #include "util/u_atomic.h" #include "radv_debug.h" @@ -1224,11 +1225,12 @@ radv_dump_nir_shaders(struct nir_shader * const *shaders, char *data = NULL; char *ret = NULL; size_t size = 0; - FILE *f = open_memstream(&data, &size); - if (f) { + struct u_memstream mem; + if (u_memstream_open(&mem, &data, &size)) { + FILE *const memf = u_memstream_get(&mem); for (int i = 0; i < shader_count; ++i) - nir_print_shader(shaders[i], f); - fclose(f); + nir_print_shader(shaders[i], memf); + u_memstream_close(&mem); } ret = malloc(size + 1); @@ -1601,13 +1603,15 @@ radv_GetShaderInfoAMD(VkDevice _device, case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: { char *out; size_t outsize; - FILE *memf = open_memstream(&out, &outsize); + struct u_memstream mem; + u_memstream_open(&mem, &out, &outsize); + FILE *const memf = u_memstream_get(&mem); 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); radv_dump_shader_stats(device, pipeline, stage, memf); - fclose(memf); + u_memstream_close(&mem); /* Need to include the null terminator. */ size_t length = outsize + 1; diff --git a/src/util/memstream.c b/src/util/memstream.c new file mode 100644 index 00000000000..f133a527341 --- /dev/null +++ b/src/util/memstream.c @@ -0,0 +1,81 @@ +/* + * Copyright 2020 Lag Free Games, LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "memstream.h" + +#include <stdlib.h> + +bool +u_memstream_open(struct u_memstream *mem, char **bufp, size_t *sizep) +{ +#ifdef _WIN32 + bool success = false; + + char path[MAX_PATH]; + DWORD dwResult = GetTempPath(MAX_PATH, path); + if ((dwResult > 0) && (dwResult < MAX_PATH)) { + char *temp = mem->temp; + UINT uResult = GetTempFileName(path, "MEMSTREAM", 0, temp); + if (uResult != 0) { + FILE *f = fopen(temp, "w+b"); + success = f != NULL; + if (success) + { + mem->f = f; + mem->bufp = bufp; + mem->sizep = sizep; + } + } + } + + return success; +#else + FILE *const f = open_memstream(bufp, sizep); + mem->f = f; + return f != NULL; +#endif +} + +void +u_memstream_close(struct u_memstream *mem) +{ + FILE *const f = mem->f; + +#ifdef _WIN32 + long size = ftell(f); + if (size > 0) { + char *buf = malloc(size); + fseek(f, 0, SEEK_SET); + fread(buf, 1, size, f); + + *mem->bufp = buf; + *mem->sizep = size; + } + + remove(mem->temp); +#endif + + fclose(f); +} diff --git a/src/util/memstream.h b/src/util/memstream.h new file mode 100644 index 00000000000..2d4be8257c1 --- /dev/null +++ b/src/util/memstream.h @@ -0,0 +1,67 @@ +/************************************************************************** + * + * Copyright 2020 Lag Free Games, LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef MEMSTREAM_H +#define MEMSTREAM_H + +#include <stdbool.h> +#include <stdio.h> +#ifdef _WIN32 +#include <windows.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct u_memstream +{ + FILE *f; +#ifdef _WIN32 + char **bufp; + size_t *sizep; + char temp[MAX_PATH]; +#endif +}; + +extern bool +u_memstream_open(struct u_memstream *mem, char **bufp, size_t *sizep); + +extern void +u_memstream_close(struct u_memstream *mem); + +static inline FILE * +u_memstream_get(const struct u_memstream *mem) +{ + return mem->f; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/util/meson.build b/src/util/meson.build index 7c0e37cf1ed..f38b725f251 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -61,6 +61,8 @@ files_mesa_util = files( 'list.h', 'log.c', 'macros.h', + 'memstream.c', + 'memstream.h', 'mesa-sha1.c', 'mesa-sha1.h', 'os_time.c', _______________________________________________ mesa-commit mailing list mesa-commit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-commit