swr: refactor swr_create_screen to allow for proper cleanup on error

This makes the following changes to address cleanup issues:
- Error conditions now return NULL instead of calling exit()
- swr_creen is now freed upon error, rather than leak.
- Library handle from dlopen is now closed upon swr_screen destruction

v2: Added additional context in commit msg and remove unnecessary "PUBLIC"
v3: Fix typo in commit message.

Signed-off-by: Chuck Atkins <chuck.atkins@kitware.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Cc: Bruce Cherniak <bruce.cherniak@intel.com>
Cc: Tim Rowley <timothy.o.rowley@intel.com>
cc: mesa-stable@lists.freedesktop.org
This commit is contained in:
Chuck Atkins
2018-01-22 12:09:28 -05:00
committed by George Kyriazis
parent 56b9060381
commit a29d63ecf7
4 changed files with 79 additions and 56 deletions

View File

@@ -29,96 +29,98 @@
#include <stdio.h> #include <stdio.h>
// Helper function to resolve the backend filename based on architecture // Helper function to resolve the backend filename based on architecture
inline void get_swr_arch_filename(const char arch[], char filename[]) static bool
swr_initialize_screen_interface(struct swr_screen *screen, const char arch[])
{ {
#ifdef HAVE_SWR_BUILTIN #ifdef HAVE_SWR_BUILTIN
strcpy(filename , "builtin"); screen->pLibrary = NULL;
screen->pfnSwrGetInterface = SwrGetInterface;
fprintf(stderr, "(using: builtin).\n");
#else #else
char filename[256] = { 0 };
sprintf(filename, "%sswr%s%s", UTIL_DL_PREFIX, arch, UTIL_DL_EXT); sprintf(filename, "%sswr%s%s", UTIL_DL_PREFIX, arch, UTIL_DL_EXT);
#endif
screen->pLibrary = util_dl_open(filename);
if (!screen->pLibrary) {
fprintf(stderr, "(skipping: %s).\n", util_dl_error());
return false;
} }
util_dl_proc pApiProc = util_dl_get_proc_address(screen->pLibrary,
"SwrGetInterface");
if (!pApiProc) {
fprintf(stderr, "(skipping: %s).\n", util_dl_error());
util_dl_close(screen->pLibrary);
screen->pLibrary = NULL;
return false;
}
screen->pfnSwrGetInterface = (PFNSwrGetInterface)pApiProc;
fprintf(stderr, "(using: %s).\n", filename);
#endif
return true;
}
struct pipe_screen * struct pipe_screen *
swr_create_screen(struct sw_winsys *winsys) swr_create_screen(struct sw_winsys *winsys)
{ {
char filename[256] = { 0 }; struct pipe_screen *p_screen = swr_create_screen_internal(winsys);
bool found = false; if (!p_screen) {
bool is_knl = false; return NULL;
PFNSwrGetInterface pfnSwrGetInterface = nullptr; }
struct swr_screen *screen = swr_screen(p_screen);
screen->is_knl = false;
util_cpu_detect(); util_cpu_detect();
if (!found && util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512er) { if (util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512er) {
fprintf(stderr, "SWR detected KNL instruction support "); fprintf(stderr, "SWR detected KNL instruction support ");
#ifndef HAVE_SWR_KNL #ifndef HAVE_SWR_KNL
fprintf(stderr, "(skipping not built).\n"); fprintf(stderr, "(skipping: not built).\n");
#else #else
get_swr_arch_filename("KNL", filename); if (swr_initialize_screen_interface(screen, "KNL")) {
found = true; screen->is_knl = true;
is_knl = true; return p_screen;
}
#endif #endif
} }
if (!found && util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512bw) { if (util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512bw) {
fprintf(stderr, "SWR detected SKX instruction support "); fprintf(stderr, "SWR detected SKX instruction support ");
#ifndef HAVE_SWR_SKX #ifndef HAVE_SWR_SKX
fprintf(stderr, "(skipping not built).\n"); fprintf(stderr, "(skipping not built).\n");
#else #else
get_swr_arch_filename("SKX", filename); if (swr_initialize_screen_interface(screen, "SKX"))
found = true; return p_screen;
#endif #endif
} }
if (!found && util_cpu_caps.has_avx2) { if (util_cpu_caps.has_avx2) {
fprintf(stderr, "SWR detected AVX2 instruction support "); fprintf(stderr, "SWR detected AVX2 instruction support ");
#ifndef HAVE_SWR_AVX2 #ifndef HAVE_SWR_AVX2
fprintf(stderr, "(skipping not built).\n"); fprintf(stderr, "(skipping not built).\n");
#else #else
get_swr_arch_filename("AVX2", filename); if (swr_initialize_screen_interface(screen, "AVX2"))
found = true; return p_screen;
#endif #endif
} }
if (!found && util_cpu_caps.has_avx) { if (util_cpu_caps.has_avx) {
fprintf(stderr, "SWR detected AVX instruction support "); fprintf(stderr, "SWR detected AVX instruction support ");
#ifndef HAVE_SWR_AVX #ifndef HAVE_SWR_AVX
fprintf(stderr, "(skipping not built).\n"); fprintf(stderr, "(skipping not built).\n");
#else #else
get_swr_arch_filename("AVX", filename); if (swr_initialize_screen_interface(screen, "AVX"))
found = true; return p_screen;
#endif #endif
} }
if (!found) { fprintf(stderr, "SWR could not initialize a supported CPU architecture.\n");
fprintf(stderr, "SWR could not detect a supported CPU architecture.\n"); swr_destroy_screen_internal(&screen);
exit(-1);
}
fprintf(stderr, "(using %s).\n", filename); return NULL;
#ifdef HAVE_SWR_BUILTIN
pfnSwrGetInterface = SwrGetInterface;
#else
util_dl_library *pLibrary = util_dl_open(filename);
if (!pLibrary) {
fprintf(stderr, "SWR library load failure: %s\n", util_dl_error());
exit(-1);
}
util_dl_proc pApiProc = util_dl_get_proc_address(pLibrary, "SwrGetInterface");
if (!pApiProc) {
fprintf(stderr, "SWR library search failure: %s\n", util_dl_error());
exit(-1);
}
pfnSwrGetInterface = (PFNSwrGetInterface)pApiProc;
#endif
struct pipe_screen *screen = swr_create_screen_internal(winsys);
swr_screen(screen)->is_knl = is_knl;
swr_screen(screen)->pfnSwrGetInterface = pfnSwrGetInterface;
return screen;
} }

View File

@@ -25,8 +25,9 @@
#define SWR_PUBLIC_H #define SWR_PUBLIC_H
struct pipe_screen; struct pipe_screen;
struct sw_winsys;
struct sw_displaytarget; struct sw_displaytarget;
struct sw_winsys;
struct swr_screen;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -38,6 +39,9 @@ struct pipe_screen *swr_create_screen(struct sw_winsys *winsys);
// arch-specific dll entry point // arch-specific dll entry point
PUBLIC struct pipe_screen *swr_create_screen_internal(struct sw_winsys *winsys); PUBLIC struct pipe_screen *swr_create_screen_internal(struct sw_winsys *winsys);
// cleanup for failed screen creation
void swr_destroy_screen_internal(struct swr_screen **screen);
#ifdef _WIN32 #ifdef _WIN32
void swr_gdi_swap(struct pipe_screen *screen, void swr_gdi_swap(struct pipe_screen *screen,
struct pipe_resource *res, struct pipe_resource *res,

View File

@@ -1052,6 +1052,24 @@ swr_flush_frontbuffer(struct pipe_screen *p_screen,
} }
void
swr_destroy_screen_internal(struct swr_screen **screen)
{
struct pipe_screen *p_screen = &(*screen)->base;
swr_fence_finish(p_screen, NULL, (*screen)->flush_fence, 0);
swr_fence_reference(p_screen, &(*screen)->flush_fence, NULL);
JitDestroyContext((*screen)->hJitMgr);
if ((*screen)->pLibrary)
util_dl_close((*screen)->pLibrary);
FREE(*screen);
*screen = NULL;
}
static void static void
swr_destroy_screen(struct pipe_screen *p_screen) swr_destroy_screen(struct pipe_screen *p_screen)
{ {
@@ -1060,15 +1078,10 @@ swr_destroy_screen(struct pipe_screen *p_screen)
fprintf(stderr, "SWR destroy screen!\n"); fprintf(stderr, "SWR destroy screen!\n");
swr_fence_finish(p_screen, NULL, screen->flush_fence, 0);
swr_fence_reference(p_screen, &screen->flush_fence, NULL);
JitDestroyContext(screen->hJitMgr);
if (winsys->destroy) if (winsys->destroy)
winsys->destroy(winsys); winsys->destroy(winsys);
FREE(screen); swr_destroy_screen_internal(&screen);
} }
@@ -1119,6 +1132,7 @@ struct pipe_screen *
swr_create_screen_internal(struct sw_winsys *winsys) swr_create_screen_internal(struct sw_winsys *winsys)
{ {
struct swr_screen *screen = CALLOC_STRUCT(swr_screen); struct swr_screen *screen = CALLOC_STRUCT(swr_screen);
memset(screen, 0, sizeof(struct swr_screen));
if (!screen) if (!screen)
return NULL; return NULL;

View File

@@ -28,6 +28,7 @@
#include "pipe/p_screen.h" #include "pipe/p_screen.h"
#include "pipe/p_defines.h" #include "pipe/p_defines.h"
#include "util/u_dl.h"
#include "util/u_format.h" #include "util/u_format.h"
#include "api.h" #include "api.h"
@@ -50,6 +51,8 @@ struct swr_screen {
HANDLE hJitMgr; HANDLE hJitMgr;
/* Dynamic backend implementations */
util_dl_library *pLibrary;
PFNSwrGetInterface pfnSwrGetInterface; PFNSwrGetInterface pfnSwrGetInterface;
/* Do we run on Xeon Phi? */ /* Do we run on Xeon Phi? */