> 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

Reply via email to