> Agreed, using ENABLE_SHADER_CACHE to guard some OS specifics is dirty, it > should be only guarding shader cache itself.
I found this online, but I'm not sure if it can be used as part of mesa license etc. It looks quite reasonable (except for the include of sys/file.h) which isnt needed AFAICT --- /* Emulate flock on platforms that lack it, primarily Windows and MinGW. This is derived from sqlite3 sources. http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c http://www.sqlite.org/copyright.html Written by Richard W.M. Jones <rjones.at.redhat.com> Copyright (C) 2008-2012 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <sys/file.h> #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* LockFileEx */ # define WIN32_LEAN_AND_MEAN # include <windows.h> # include <errno.h> /* _get_osfhandle */ # include "msvc-nothrow.h" /* Determine the current size of a file. Because the other braindead * APIs we'll call need lower/upper 32 bit pairs, keep the file size * like that too. */ static BOOL file_size (HANDLE h, DWORD * lower, DWORD * upper) { *lower = GetFileSize (h, upper); return 1; } /* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */ # ifndef LOCKFILE_FAIL_IMMEDIATELY # define LOCKFILE_FAIL_IMMEDIATELY 1 # endif /* Acquire a lock. */ static BOOL do_lock (HANDLE h, int non_blocking, int exclusive) { BOOL res; DWORD size_lower, size_upper; OVERLAPPED ovlp; int flags = 0; /* We're going to lock the whole file, so get the file size. */ res = file_size (h, &size_lower, &size_upper); if (!res) return 0; /* Start offset is 0, and also zero the remaining members of this struct. */ memset (&ovlp, 0, sizeof ovlp); if (non_blocking) flags |= LOCKFILE_FAIL_IMMEDIATELY; if (exclusive) flags |= LOCKFILE_EXCLUSIVE_LOCK; return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp); } /* Unlock reader or exclusive lock. */ static BOOL do_unlock (HANDLE h) { int res; DWORD size_lower, size_upper; res = file_size (h, &size_lower, &size_upper); if (!res) return 0; return UnlockFile (h, 0, 0, size_lower, size_upper); } /* Now our BSD-like flock operation. */ int flock (int fd, int operation) { HANDLE h = (HANDLE) _get_osfhandle (fd); DWORD res; int non_blocking; if (h == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } non_blocking = operation & LOCK_NB; operation &= ~LOCK_NB; switch (operation) { case LOCK_SH: res = do_lock (h, non_blocking, 0); break; case LOCK_EX: res = do_lock (h, non_blocking, 1); break; case LOCK_UN: res = do_unlock (h); break; default: errno = EINVAL; return -1; } /* Map Windows errors into Unix errnos. As usual MSDN fails to * document the permissible error codes. */ if (!res) { DWORD err = GetLastError (); switch (err) { /* This means someone else is holding a lock. */ case ERROR_LOCK_VIOLATION: errno = EAGAIN; break; /* Out of memory. */ case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_BAD_COMMAND: errno = EINVAL; break; /* Unlikely to be other errors, but at least don't lose the * error code. */ default: errno = err; } return -1; } return 0; } #else /* !Windows */ # ifdef HAVE_STRUCT_FLOCK_L_TYPE /* We know how to implement flock in terms of fcntl. */ # include <fcntl.h> # ifdef HAVE_UNISTD_H # include <unistd.h> # endif # include <errno.h> # include <string.h> int flock (int fd, int operation) { int cmd, r; struct flock fl; if (operation & LOCK_NB) cmd = F_SETLK; else cmd = F_SETLKW; operation &= ~LOCK_NB; memset (&fl, 0, sizeof fl); fl.l_whence = SEEK_SET; /* l_start & l_len are 0, which as a special case means "whole file". */ switch (operation) { case LOCK_SH: fl.l_type = F_RDLCK; break; case LOCK_EX: fl.l_type = F_WRLCK; break; case LOCK_UN: fl.l_type = F_UNLCK; break; default: errno = EINVAL; return -1; } r = fcntl (fd, cmd, &fl); if (r == -1 && errno == EACCES) errno = EAGAIN; return r; } # else /* !HAVE_STRUCT_FLOCK_L_TYPE */ # error "This platform lacks flock function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib." # endif /* !HAVE_STRUCT_FLOCK_L_TYPE */ #endif /* !Windows */ Am 18.05.2018 um 07:34 schrieb Tapani Pälli: > > > On 05/17/2018 02:00 PM, Benedikt Schemmer wrote: >> Ok I found the commit. >> But it says: "Until we have a proper fix." >> So this would be a good time I guess ;) > > >> >> --- >> >> author Emil Velikov <emil.veli...@collabora.com> 2017-01-18 19:40:31 >> +0000 >> committer Emil Velikov <emil.l.veli...@gmail.com> 2017-01-18 20:09:01 >> +0000 >> commit 9f8dc3bf03ec825bae7041858dda6ca2e9a34363 (patch) >> tree ff9672995474d3c31f027fea8356cb5733e45388 >> parent d1efa09d342bff3e5def2978a0bef748d74f9c82 (diff) >> utils: build sha1/disk cache only with Android/Autoconf >> Earlier commit imported a SHA1 implementation and relaxed the SHA1 and >> disk cache handling, broking the Windows builds. >> >> Restrict things for now until we get to a proper fix. >> >> Fixes: d1efa09d342 "util: import sha1 implementation from OpenBSD" >> Signed-off-by: Emil Velikov <emil.veli...@collabora.com> >> >> >> Am 17.05.2018 um 12:28 schrieb Tapani Pälli: >>> >>> >>> On 05/17/2018 11:38 AM, Benedikt Schemmer wrote: >>>> Thanks for reviewing! >>>> >>>> Am 17.05.2018 um 08:42 schrieb Tapani Pälli: >>>>> >>>>> >>>>> On 05/10/2018 12:05 PM, Benedikt Schemmer wrote: >>>>>> Move shader-cache code from back to front and make generate_sha1() usable >>>>>> unconditionally to avoid code duplication in the following patch >>>>>> >>>>>> --- >>>>>> src/mesa/main/shaderapi.c | 228 >>>>>> +++++++++++++++++++++++----------------------- >>>>>> 1 file changed, 116 insertions(+), 112 deletions(-) >>>>>> >>>>>> diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c >>>>>> index 44b18af492..e8acca4490 100644 >>>>>> --- a/src/mesa/main/shaderapi.c >>>>>> +++ b/src/mesa/main/shaderapi.c >>>>>> @@ -64,6 +64,122 @@ >>>>>> #include "util/mesa-sha1.h" >>>>>> #include "util/crc32.h" >>>>>> >>>>>> + >>>>>> +/** >>>>>> + * Generate a SHA-1 hash value string for given source string. >>>>>> + */ >>>>>> +static void >>>>>> +generate_sha1(const char *source, char sha_str[64]) >>>>>> +{ >>>>>> + unsigned char sha[20]; >>>>>> + _mesa_sha1_compute(source, strlen(source), sha); >>>>>> + _mesa_sha1_format(sha_str, sha); >>>>>> +} >>>>> >>>>> There is one potential problem here. The 'ENABLE_SHADER_CACHE' guard for >>>>> generate_sha1 and others was placed there because the imported sha1 code >>>>> broke windows build, I'm wondering if this is still >>>>> the case? If so, then generate_sha1 should be inside ENABLE_SHADER_CACHE >>>>> guard. >>>>> >>>> >>>> I did a quick >>>> gedit $(grep -Rlsi "_mesa_sha1_compute" | grep -E "\.c|\.h") >>>> >>>> and it seems radv and anv use _mesa_sha1_compute (and _mesa_sha1_format) >>>> without a guard >>>> best example from Intel seems to be brw_disk_cache.c which uses it alot >>>> outside of the ENABLE_SHADER_CACHE guard >>>> >>>> so probably safe? >>> >>> AFAIK none of those things are compiled on windows. IIUC windows builds are >>> about Mesa core and gallium side. >>> >>>>>> + >>>>>> + >>>>>> +#ifdef ENABLE_SHADER_CACHE >>>>>> +/** >>>>>> + * Construct a full path for shader replacement functionality using >>>>>> + * following format: >>>>>> + * >>>>>> + * <path>/<stage prefix>_<CHECKSUM>.glsl >>>>>> + */ >>>>>> +static char * >>>>>> +construct_name(const gl_shader_stage stage, const char *source, >>>>>> + const char *path) >>>>>> +{ >>>>>> + char sha[64]; >>>>>> + static const char *types[] = { >>>>>> + "VS", "TC", "TE", "GS", "FS", "CS", >>>>>> + }; >>>>>> + >>>>>> + generate_sha1(source, sha); >>>>>> + return ralloc_asprintf(NULL, "%s/%s_%s.glsl", path, types[stage], >>>>>> sha); >>>>>> +} >>>>>> + >>>>>> +/** >>>>>> + * Write given shader source to a file in MESA_SHADER_DUMP_PATH. >>>>>> + */ >>>>>> +static void >>>>>> +dump_shader(const gl_shader_stage stage, const char *source) >>>>>> +{ >>>>>> + static bool path_exists = true; >>>>>> + char *dump_path; >>>>>> + FILE *f; >>>>>> + >>>>>> + if (!path_exists) >>>>>> + return; >>>>>> + >>>>>> + dump_path = getenv("MESA_SHADER_DUMP_PATH"); >>>>>> + if (!dump_path) { >>>>>> + path_exists = false; >>>>>> + return; >>>>>> + } >>>>>> + >>>>>> + char *name = construct_name(stage, source, dump_path); >>>>>> + >>>>>> + f = fopen(name, "w"); >>>>>> + if (f) { >>>>>> + fputs(source, f); >>>>>> + fclose(f); >>>>>> + } else { >>>>>> + GET_CURRENT_CONTEXT(ctx); >>>>>> + _mesa_warning(ctx, "could not open %s for dumping shader (%s)", >>>>>> name, >>>>>> + strerror(errno)); >>>>>> + } >>>>>> + ralloc_free(name); >>>>>> +} >>>>>> + >>>>>> +/** >>>>>> + * Read shader source code from a file. >>>>>> + * Useful for debugging to override an app's shader. >>>>>> + */ >>>>>> +static GLcharARB * >>>>>> +read_shader(const gl_shader_stage stage, const char *source) >>>>>> +{ >>>>>> + char *read_path; >>>>>> + static bool path_exists = true; >>>>>> + int len, shader_size = 0; >>>>>> + GLcharARB *buffer; >>>>>> + FILE *f; >>>>>> + >>>>>> + if (!path_exists) >>>>>> + return NULL; >>>>>> + >>>>>> + read_path = getenv("MESA_SHADER_READ_PATH"); >>>>>> + if (!read_path) { >>>>>> + path_exists = false; >>>>>> + return NULL; >>>>>> + } >>>>>> + >>>>>> + char *name = construct_name(stage, source, read_path); >>>>>> + f = fopen(name, "r"); >>>>>> + ralloc_free(name); >>>>>> + if (!f) >>>>>> + return NULL; >>>>>> + >>>>>> + /* allocate enough room for the entire shader */ >>>>>> + fseek(f, 0, SEEK_END); >>>>>> + shader_size = ftell(f); >>>>>> + rewind(f); >>>>>> + assert(shader_size); >>>>>> + >>>>>> + /* add one for terminating zero */ >>>>>> + shader_size++; >>>>>> + >>>>>> + buffer = malloc(shader_size); >>>>>> + assert(buffer); >>>>>> + >>>>>> + len = fread(buffer, 1, shader_size, f); >>>>>> + buffer[len] = 0; >>>>>> + >>>>>> + fclose(f); >>>>>> + >>>>>> + return buffer; >>>>>> +} >>>>>> + >>>>>> +#endif /* ENABLE_SHADER_CACHE */ >>>>>> + >>>>>> /** >>>>>> * Return mask of GLSL_x flags by examining the MESA_GLSL env var. >>>>>> */ >>>>>> @@ -1775,119 +1891,7 @@ _mesa_LinkProgram(GLuint programObj) >>>>>> link_program_error(ctx, shProg); >>>>>> } >>>>>> >>>>>> -#ifdef ENABLE_SHADER_CACHE >>>>>> -/** >>>>>> - * Generate a SHA-1 hash value string for given source string. >>>>>> - */ >>>>>> -static void >>>>>> -generate_sha1(const char *source, char sha_str[64]) >>>>>> -{ >>>>>> - unsigned char sha[20]; >>>>>> - _mesa_sha1_compute(source, strlen(source), sha); >>>>>> - _mesa_sha1_format(sha_str, sha); >>>>>> -} >>>>>> - >>>>>> -/** >>>>>> - * Construct a full path for shader replacement functionality using >>>>>> - * following format: >>>>>> - * >>>>>> - * <path>/<stage prefix>_<CHECKSUM>.glsl >>>>>> - */ >>>>>> -static char * >>>>>> -construct_name(const gl_shader_stage stage, const char *source, >>>>>> - const char *path) >>>>>> -{ >>>>>> - char sha[64]; >>>>>> - static const char *types[] = { >>>>>> - "VS", "TC", "TE", "GS", "FS", "CS", >>>>>> - }; >>>>>> - >>>>>> - generate_sha1(source, sha); >>>>>> - return ralloc_asprintf(NULL, "%s/%s_%s.glsl", path, types[stage], >>>>>> sha); >>>>>> -} >>>>>> - >>>>>> -/** >>>>>> - * Write given shader source to a file in MESA_SHADER_DUMP_PATH. >>>>>> - */ >>>>>> -static void >>>>>> -dump_shader(const gl_shader_stage stage, const char *source) >>>>>> -{ >>>>>> - static bool path_exists = true; >>>>>> - char *dump_path; >>>>>> - FILE *f; >>>>>> - >>>>>> - if (!path_exists) >>>>>> - return; >>>>>> - >>>>>> - dump_path = getenv("MESA_SHADER_DUMP_PATH"); >>>>>> - if (!dump_path) { >>>>>> - path_exists = false; >>>>>> - return; >>>>>> - } >>>>>> - >>>>>> - char *name = construct_name(stage, source, dump_path); >>>>>> - >>>>>> - f = fopen(name, "w"); >>>>>> - if (f) { >>>>>> - fputs(source, f); >>>>>> - fclose(f); >>>>>> - } else { >>>>>> - GET_CURRENT_CONTEXT(ctx); >>>>>> - _mesa_warning(ctx, "could not open %s for dumping shader (%s)", >>>>>> name, >>>>>> - strerror(errno)); >>>>>> - } >>>>>> - ralloc_free(name); >>>>>> -} >>>>>> - >>>>>> -/** >>>>>> - * Read shader source code from a file. >>>>>> - * Useful for debugging to override an app's shader. >>>>>> - */ >>>>>> -static GLcharARB * >>>>>> -read_shader(const gl_shader_stage stage, const char *source) >>>>>> -{ >>>>>> - char *read_path; >>>>>> - static bool path_exists = true; >>>>>> - int len, shader_size = 0; >>>>>> - GLcharARB *buffer; >>>>>> - FILE *f; >>>>>> - >>>>>> - if (!path_exists) >>>>>> - return NULL; >>>>>> >>>>>> - read_path = getenv("MESA_SHADER_READ_PATH"); >>>>>> - if (!read_path) { >>>>>> - path_exists = false; >>>>>> - return NULL; >>>>>> - } >>>>>> - >>>>>> - char *name = construct_name(stage, source, read_path); >>>>>> - f = fopen(name, "r"); >>>>>> - ralloc_free(name); >>>>>> - if (!f) >>>>>> - return NULL; >>>>>> - >>>>>> - /* allocate enough room for the entire shader */ >>>>>> - fseek(f, 0, SEEK_END); >>>>>> - shader_size = ftell(f); >>>>>> - rewind(f); >>>>>> - assert(shader_size); >>>>>> - >>>>>> - /* add one for terminating zero */ >>>>>> - shader_size++; >>>>>> - >>>>>> - buffer = malloc(shader_size); >>>>>> - assert(buffer); >>>>>> - >>>>>> - len = fread(buffer, 1, shader_size, f); >>>>>> - buffer[len] = 0; >>>>>> - >>>>>> - fclose(f); >>>>>> - >>>>>> - return buffer; >>>>>> -} >>>>>> - >>>>>> -#endif /* ENABLE_SHADER_CACHE */ >>>>>> >>>>>> /** >>>>>> * Called via glShaderSource() and glShaderSourceARB() API functions. >>>>>> _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev