diff --git a/dive_core/CMakeLists.txt b/dive_core/CMakeLists.txt index 085140833..12f22f4b9 100644 --- a/dive_core/CMakeLists.txt +++ b/dive_core/CMakeLists.txt @@ -140,10 +140,7 @@ add_dependencies(${PROJECT_NAME} freedreno_devices_header) -if (MSVC) - # freedreno_ir3 build is currently disabled on MSVC -else() - add_custom_command( +add_custom_command( OUTPUT ${FREEDRENO_IR3_ISA_SRC_FILE} ${FREEDRENO_IR3_ISA_HDR_FILE} COMMAND ${Python3_EXECUTABLE} ${THIRDPARTY_DIRECTORY}/mesa/src/compiler/isaspec/decode.py "--xml" @@ -153,9 +150,9 @@ else() DEPENDS "${THIRDPARTY_DIRECTORY}/mesa/src/compiler/isaspec/decode.py" "${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/isa/ir3.xml" VERBATIM - ) +) - add_library(freedreno_ir3 STATIC +add_library(freedreno_ir3 STATIC ${FREEDRENO_IR3_ISA_SRC_FILE} "${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/ir3/disasm-a3xx.c" "${THIRDPARTY_DIRECTORY}/mesa/src/util/half_float.c" @@ -170,9 +167,9 @@ else() "${THIRDPARTY_DIRECTORY}/mesa/src/util/u_debug.c" "${THIRDPARTY_DIRECTORY}/mesa/src/util/u_printf.c" "${THIRDPARTY_DIRECTORY}/mesa/src/util/u_process.c" - ) +) - target_include_directories(freedreno_ir3 PRIVATE +target_include_directories(freedreno_ir3 PRIVATE "${THIRDPARTY_DIRECTORY}/mesa/include" "${THIRDPARTY_DIRECTORY}/mesa/src" "${THIRDPARTY_DIRECTORY}/mesa/src/compiler" @@ -181,18 +178,25 @@ else() "${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/common" "${THIRDPARTY_DIRECTORY}/mesa/src/freedreno/isa" "${THIRDPARTY_DIRECTORY}/mesa/src/util/ralloc.c" - ) - target_compile_definitions(freedreno_ir3 PRIVATE +) + +if(MSVC) +target_compile_definitions(freedreno_ir3 PRIVATE + -DHAVE_STRUCT_TIMESPEC +) +else() +target_compile_definitions(freedreno_ir3 PRIVATE -DHAVE_ENDIAN_H -DHAVE_FUNC_ATTRIBUTE_PACKED -DHAVE_STRUCT_TIMESPEC -DHAVE_PTHREAD - ) - target_compile_options(freedreno_ir3 PRIVATE -fPIC) - add_dependencies(${PROJECT_NAME} freedreno_ir3) - target_link_libraries(${PROJECT_NAME} PRIVATE freedreno_ir3) +) endif() +target_compile_options(freedreno_ir3 PRIVATE -fPIC) +add_dependencies(${PROJECT_NAME} freedreno_ir3) +target_link_libraries(${PROJECT_NAME} PRIVATE freedreno_ir3) + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") target_link_libraries(${PROJECT_NAME} PRIVATE dl) diff --git a/dive_core/shader_disassembly.cpp b/dive_core/shader_disassembly.cpp index 01a12c55d..118eed0fb 100644 --- a/dive_core/shader_disassembly.cpp +++ b/dive_core/shader_disassembly.cpp @@ -19,12 +19,14 @@ #include "dive_core/common/common.h" #include "pm4_info.h" -#ifndef _MSC_VER +#ifdef _MSC_VER +# include +# include +#endif extern "C" { -# include "third_party/mesa/src/freedreno/common/disasm.h" +#include "third_party/mesa/src/freedreno/common/disasm.h" } -#endif namespace Dive { @@ -40,38 +42,55 @@ bool Disassemble(const uint8_t* shader_memory, return false; } -// TODO(b/309801805): Shader disassembly is disabled on windows due to compiler errors. -#ifndef _MSC_VER std::string DisassembleA3XX(const uint8_t* data, size_t max_size, struct shader_stats* stats, enum debug_t debug) { disasm_a3xx_set_debug(debug); - +#ifdef _MSC_VER + FILE* disasm_file; + errno_t err = tmpfile_s(&disasm_file); + DIVE_ASSERT(disasm_file == NULL); + DIVE_ASSERT(err != 0); +#else char* disasm_buf = nullptr; size_t disasm_buf_size = 0; FILE* disasm_file = open_memstream(&disasm_buf, &disasm_buf_size); +#endif + + size_t code_size = max_size / sizeof(uint32_t); int res = disasm_a3xx_stat(reinterpret_cast(const_cast(data)), - max_size / sizeof(uint32_t), + static_cast(code_size), 0, disasm_file, GetGPUID(), stats); ((void)(res)); // avoid unused variable DIVE_ASSERT(res != -1); +#ifdef _MSC_VER + rewind(disasm_file); + std::string disasm_output; + char buffer[1024]; + size_t bytes_read; + while ((bytes_read = fread(buffer, 1, sizeof(buffer), disasm_file)) > 0) + { + disasm_output.append(buffer, bytes_read); + } + fclose(disasm_file); + return disasm_output; +#else fflush(disasm_file); disasm_buf[disasm_buf_size] = '\0'; std::string disasm(disasm_buf); fclose(disasm_file); free(disasm_buf); return disasm; -} #endif +} void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, ILog* log_ptr) { -#ifndef _MSC_VER struct shader_stats stats; std::string disasm = DisassembleA3XX(data, max_size, &stats, PRINT_RAW); std::istringstream disasm_istr(disasm); @@ -82,6 +101,16 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I int prefix_len = 0; for (std::string line; std::getline(disasm_istr, line);) { +#ifdef _MSC_VER + sscanf_s(line.c_str(), + " :%d:%04d:%04d[%08xx_%08xx] %n", + &opc_cat, + &n, + &cycles, + &dword1, + &dword0, + &prefix_len); +#else sscanf(line.c_str(), " :%d:%04d:%04d[%08xx_%08xx] %n", &opc_cat, @@ -90,6 +119,7 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I &dword1, &dword0, &prefix_len); +#endif std::string instr(&line[prefix_len]); if (n >= m_instructions_text.size()) { @@ -106,7 +136,6 @@ void Disassembly::Init(const uint8_t* data, uint64_t address, size_t max_size, I } m_gpr_count = (stats.fullreg + 3) / 4; m_listing = DisassembleA3XX(data, max_size, &stats, PRINT_STATS); -#endif } } // namespace Dive diff --git a/third_party/mesa/src/c11/threads.h b/third_party/mesa/src/c11/threads.h index dbcb3459a..1cfe8737c 100644 --- a/third_party/mesa/src/c11/threads.h +++ b/third_party/mesa/src/c11/threads.h @@ -168,11 +168,12 @@ thrd_t thrd_current(void); int thrd_detach(thrd_t); int thrd_equal(thrd_t, thrd_t); #if defined(__cplusplus) -[[ noreturn ]] +[[ noreturn ]] void thrd_exit(int); +# elif defined(_MSC_VER) +__declspec(noreturn) void thrd_exit(int); #else -_Noreturn +_Noreturn void thrd_exit(int); #endif -void thrd_exit(int); int thrd_join(thrd_t, int *); int thrd_sleep(const struct timespec *, struct timespec *); void thrd_yield(void); diff --git a/third_party/mesa/src/compiler/isaspec/decode.py b/third_party/mesa/src/compiler/isaspec/decode.py index 7b348bf80..bcef59c05 100755 --- a/third_party/mesa/src/compiler/isaspec/decode.py +++ b/third_party/mesa/src/compiler/isaspec/decode.py @@ -143,12 +143,14 @@ def resolve_simple_field(self, bitset, name): static void decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_${df.get_c_name()}(void *out, struct decode_scope *scope, uint64_t val); % endfor static const struct isa_field_decode decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_fields[] = { -% for df in s.decode_fields(bitset): - { +% if len(list(s.decode_fields(bitset))) > 0: +% for df in s.decode_fields(bitset): .name = "${df.name}", .decode = decode_${bitset.get_c_name()}_gen_${bitset.gen_min}_${df.get_c_name()}, - }, -% endfor +% endfor +% else: + { 0 }, // Dummy initializer for empty case +% endif }; static void decode_${bitset.get_c_name()}_gen_${bitset.gen_min}(void *out, struct decode_scope *scope); %endfor @@ -194,35 +196,41 @@ def resolve_simple_field(self, bitset, name): % if case.display is not None: .display = "${case.display}", % endif - .num_fields = ${len(case.fields)}, - .fields = { -% for field_name, field in case.fields.items(): - { .name = "${field_name}", .low = ${field.low}, .high = ${field.high}, -% if field.expr is not None: +.num_fields = ${len(case.fields)}, +.fields = +% if len(case.fields) > 0: + { + % for field_name, field in case.fields.items(): + { .name = "${field_name}", .low = ${field.low}, .high = ${field.high}, + % if field.expr is not None: .expr = &${isa.expressions[field.expr].get_c_name()}, -% endif -% if field.display is not None: + % endif + % if field.display is not None: .display = "${field.display}", -% endif + % endif .type = ${field.get_c_typename()}, -% if field.get_c_typename() == 'TYPE_BITSET': + % if field.get_c_typename() == 'TYPE_BITSET': .bitsets = ${isa.roots[field.type].get_c_name()}, -% if len(field.params) > 0: - .params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()}, -% endif -% endif -% if field.get_c_typename() == 'TYPE_ENUM': + % if len(field.params) > 0: + .params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()}, + + % endif + % endif + % if field.get_c_typename() == 'TYPE_ENUM': .enums = &${isa.enums[field.type].get_c_name()}, -% endif -% if field.get_c_typename() == 'TYPE_ASSERT': + % endif + % if field.get_c_typename() == 'TYPE_ASSERT': .val.bitset = { ${', '.join(isa.split_bits(field.val, 32))} }, -% endif -% if field.get_c_typename() == 'TYPE_BRANCH' or field.get_c_typename() == 'TYPE_ABSBRANCH': + % endif + % if field.get_c_typename() == 'TYPE_BRANCH' or field.get_c_typename() == 'TYPE_ABSBRANCH': .call = ${str(field.call).lower()}, -% endif - }, -% endfor - }, + % endif + }, + % endfor + } +% else: + { 0 }, +% endif }; % endfor static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min} = { diff --git a/third_party/mesa/src/compiler/isaspec/isaspec_decode_impl.c b/third_party/mesa/src/compiler/isaspec/isaspec_decode_impl.c index ce4af3db2..5ccbe58f8 100644 --- a/third_party/mesa/src/compiler/isaspec/isaspec_decode_impl.c +++ b/third_party/mesa/src/compiler/isaspec/isaspec_decode_impl.c @@ -184,7 +184,16 @@ isa_print(struct isa_print_state *state, const char *fmt, ...) int ret; va_start(args, fmt); - ret = vasprintf(&buffer, fmt, args); +#ifdef _MSC_VER + va_list args_copy; + va_copy(args_copy, args); + int len = _vscprintf(fmt, args_copy); + va_end(args_copy); + buffer = (char *)malloc(len + 1); + ret = _vsprintf_p(&buffer, len + 1, fmt, args); +#else + ret = vasprintf(&buffer, fmt, args); +#endif va_end(args); if (ret != -1) { @@ -224,7 +233,27 @@ decode_error(struct decode_state *state, const char *fmt, ...) va_list ap; va_start(ap, fmt); - vasprintf(&state->errors[state->num_errors++], fmt, ap); +#ifdef _MSC_VER + va_list ap_copy; + va_copy(ap_copy, ap); + int len = _vscprintf(fmt, ap_copy); + va_end(ap_copy); + + if (len == -1) { + va_end(ap); + return; + } + + state->errors[state->num_errors] = (char *)malloc(len + 1); + if (!state->errors[state->num_errors]) { + va_end(ap); + return; + } + + _vsprintf_p(state->errors[state->num_errors++], len + 1, fmt, ap); +#else + vasprintf(&state->errors[state->num_errors++], fmt, ap); +#endif va_end(ap); } @@ -733,9 +762,17 @@ display(struct decode_scope *scope) e++; } - char *field_name = strndup(p, e-p); - display_field(scope, field_name); - free(field_name); +#ifdef _MSC_VER + char *field_name = (char *)malloc(e - p + 1); + strncpy(field_name, p, e - p); + field_name[e - p] = '\0'; + display_field(scope, field_name); + free(field_name); +#else + char *field_name = strndup(p, e - p); + display_field(scope, field_name); + free(field_name); +#endif p = e; } else { @@ -913,9 +950,17 @@ decode_bitset(void *out, struct decode_scope *scope) e++; } - char *field_name = strndup(p, e-p); - decode_field(out, scope, field_name); - free(field_name); +#ifdef _MSC_VER + char *field_name = (char *)malloc(e - p + 1); + strncpy(field_name, p, e - p); + field_name[e - p] = '\0'; + decode_field(out, scope, field_name); + free(field_name); +#else + char *field_name = strndup(p, e - p); + decode_field(out, scope, field_name); + free(field_name); +#endif p = e; } diff --git a/third_party/mesa/src/freedreno/ir3/instr-a3xx.h b/third_party/mesa/src/freedreno/ir3/instr-a3xx.h index e9eaebc93..ab740cc0c 100644 --- a/third_party/mesa/src/freedreno/ir3/instr-a3xx.h +++ b/third_party/mesa/src/freedreno/ir3/instr-a3xx.h @@ -24,7 +24,15 @@ #ifndef INSTR_A3XX_H_ #define INSTR_A3XX_H_ +#if defined(__GNUC__) #define PACKED __attribute__((__packed__)) +#elif defined(_MSC_VER) +#define PACKED +#pragma pack(push, 1) +#pragma pack(pop) +#else +#error "Unsupported compiler" +#endif #include #include @@ -32,8 +40,15 @@ #include /* clang-format off */ +#if defined(__GNUC__) void ir3_assert_handler(const char *expr, const char *file, int line, - const char *func) __attribute__((weak)) __attribute__((__noreturn__)); + const char *func) __attribute__((weak)) __attribute__((__noreturn__)); +#elif defined(_MSC_VER) +__declspec(noreturn) void __cdecl ir3_assert_handler(const char *expr, const char *file, int line, + const char *func); +#else +#error "Unsupported compiler" +#endif /* clang-format on */ /* A wrapper for assert() that allows overriding handling of a failed diff --git a/third_party/mesa/src/util/ralloc.c b/third_party/mesa/src/util/ralloc.c index b74bae25b..03d27a3a9 100644 --- a/third_party/mesa/src/util/ralloc.c +++ b/third_party/mesa/src/util/ralloc.c @@ -50,7 +50,13 @@ */ struct ralloc_header { - alignas(HEADER_ALIGN) +#if defined(__GNUC__) + alignas(HEADER_ALIGN) +#elif defined(_MSC_VER) + __declspec(align(HEADER_ALIGN)) +#else +#error "Unsupported compiler" +#endif #ifndef NDEBUG /* A canary value used to determine whether a pointer is ralloc'd. */ @@ -578,7 +584,13 @@ typedef struct * allocated using a freelist backed by a simple linear allocator. */ typedef struct gc_slab { - alignas(HEADER_ALIGN) +#if defined(__GNUC__) + alignas(HEADER_ALIGN) +#elif defined(_MSC_VER) + __declspec(align(HEADER_ALIGN)) +#else +#error "Unsupported compiler" +#endif gc_ctx *ctx; @@ -961,7 +973,13 @@ gc_sweep_end(gc_ctx *ctx) struct linear_ctx { - alignas(HEADER_ALIGN) +#if defined(__GNUC__) + alignas(HEADER_ALIGN) +#elif defined(_MSC_VER) + __declspec(align(HEADER_ALIGN)) +#else +#error "Unsupported compiler" +#endif #ifndef NDEBUG unsigned magic; /* for debugging */ @@ -975,7 +993,13 @@ typedef struct linear_ctx linear_ctx; #ifndef NDEBUG struct linear_node_canary { - alignas(HEADER_ALIGN) +#if defined(__GNUC__) + alignas(HEADER_ALIGN) +#elif defined(_MSC_VER) + __declspec(align(HEADER_ALIGN)) +#else +#error "Unsupported compiler" +#endif unsigned magic; unsigned offset; /* points to the first unused byte in *this* buffer */ }; diff --git a/third_party/mesa/src/util/simple_mtx.h b/third_party/mesa/src/util/simple_mtx.h index cddf86e83..e272fb053 100644 --- a/third_party/mesa/src/util/simple_mtx.h +++ b/third_party/mesa/src/util/simple_mtx.h @@ -28,6 +28,9 @@ #include "util/macros.h" #include "util/u_call_once.h" #include "u_atomic.h" +#ifdef _WIN32 +#include +#endif #if UTIL_FUTEX_SUPPORTED #if defined(HAVE_VALGRIND) && !defined(NDEBUG) @@ -110,10 +113,17 @@ simple_mtx_lock(simple_mtx_t *mtx) if (__builtin_expect(c != 0, 0)) { if (c != 2) c = p_atomic_xchg(&mtx->val, 2); - while (c != 0) { - futex_wait(&mtx->val, 2, NULL); - c = p_atomic_xchg(&mtx->val, 2); - } +#ifdef _WIN32 + while (c != 0) { + WaitForSingleObject(mtx->val, 2); + c = p_atomic_xchg(&mtx->val, 2); + } +#else + while (c != 0) { + futex_wait(&mtx->val, 2, NULL); + c = p_atomic_xchg(&mtx->val, 2); + } +#endif } HG(ANNOTATE_RWLOCK_ACQUIRED(mtx, 1)); @@ -132,7 +142,11 @@ simple_mtx_unlock(simple_mtx_t *mtx) if (__builtin_expect(c != 1, 0)) { mtx->val = 0; - futex_wake(&mtx->val, 1); +#ifdef _WIN32 + SetEvent(mtx->val); +#else + futex_wake(&mtx->val, 1); +#endif } } diff --git a/third_party/mesa/src/util/u_call_once.c b/third_party/mesa/src/util/u_call_once.c index e16a3cfea..be9694b1a 100644 --- a/third_party/mesa/src/util/u_call_once.c +++ b/third_party/mesa/src/util/u_call_once.c @@ -11,7 +11,13 @@ struct util_call_once_context_t util_call_once_data_func func; }; +#if defined(__GNUC__) static thread_local struct util_call_once_context_t call_once_context; +#elif defined(_MSC_VER) +static __declspec(thread) struct util_call_once_context_t call_once_context; +#else +#error "Unsupported compiler" +#endif static void util_call_once_data_slow_once(void) diff --git a/third_party/mesa/src/util/u_math.h b/third_party/mesa/src/util/u_math.h index 5be5cdaec..c7a52dbe5 100644 --- a/third_party/mesa/src/util/u_math.h +++ b/third_party/mesa/src/util/u_math.h @@ -601,7 +601,7 @@ util_sign_extend(uint64_t val, unsigned width) } static inline void* -util_memcpy_cpu_to_le32(void * restrict dest, const void * restrict src, size_t n) +util_memcpy_cpu_to_le32(void * dest, const void * src, size_t n) { #if UTIL_ARCH_BIG_ENDIAN size_t i, e;