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>
// 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
strcpy(filename , "builtin");
screen->pLibrary = NULL;
screen->pfnSwrGetInterface = SwrGetInterface;
fprintf(stderr, "(using: builtin).\n");
#else
char filename[256] = { 0 };
sprintf(filename, "%sswr%s%s", UTIL_DL_PREFIX, arch, UTIL_DL_EXT);
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 *
swr_create_screen(struct sw_winsys *winsys)
{
char filename[256] = { 0 };
bool found = false;
bool is_knl = false;
PFNSwrGetInterface pfnSwrGetInterface = nullptr;
struct pipe_screen *p_screen = swr_create_screen_internal(winsys);
if (!p_screen) {
return NULL;
}
struct swr_screen *screen = swr_screen(p_screen);
screen->is_knl = false;
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 ");
#ifndef HAVE_SWR_KNL
fprintf(stderr, "(skipping not built).\n");
fprintf(stderr, "(skipping: not built).\n");
#else
get_swr_arch_filename("KNL", filename);
found = true;
is_knl = true;
if (swr_initialize_screen_interface(screen, "KNL")) {
screen->is_knl = true;
return p_screen;
}
#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 ");
#ifndef HAVE_SWR_SKX
fprintf(stderr, "(skipping not built).\n");
#else
get_swr_arch_filename("SKX", filename);
found = true;
if (swr_initialize_screen_interface(screen, "SKX"))
return p_screen;
#endif
}
if (!found && util_cpu_caps.has_avx2) {
if (util_cpu_caps.has_avx2) {
fprintf(stderr, "SWR detected AVX2 instruction support ");
#ifndef HAVE_SWR_AVX2
fprintf(stderr, "(skipping not built).\n");
#else
get_swr_arch_filename("AVX2", filename);
found = true;
if (swr_initialize_screen_interface(screen, "AVX2"))
return p_screen;
#endif
}
if (!found && util_cpu_caps.has_avx) {
if (util_cpu_caps.has_avx) {
fprintf(stderr, "SWR detected AVX instruction support ");
#ifndef HAVE_SWR_AVX
fprintf(stderr, "(skipping not built).\n");
#else
get_swr_arch_filename("AVX", filename);
found = true;
if (swr_initialize_screen_interface(screen, "AVX"))
return p_screen;
#endif
}
if (!found) {
fprintf(stderr, "SWR could not detect a supported CPU architecture.\n");
exit(-1);
}
fprintf(stderr, "SWR could not initialize a supported CPU architecture.\n");
swr_destroy_screen_internal(&screen);
fprintf(stderr, "(using %s).\n", filename);
#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;
return NULL;
}

View File

@ -25,8 +25,9 @@
#define SWR_PUBLIC_H
struct pipe_screen;
struct sw_winsys;
struct sw_displaytarget;
struct sw_winsys;
struct swr_screen;
#ifdef __cplusplus
extern "C" {
@ -38,6 +39,9 @@ struct pipe_screen *swr_create_screen(struct sw_winsys *winsys);
// arch-specific dll entry point
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
void swr_gdi_swap(struct pipe_screen *screen,
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
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");
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)
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)
{
struct swr_screen *screen = CALLOC_STRUCT(swr_screen);
memset(screen, 0, sizeof(struct swr_screen));
if (!screen)
return NULL;

View File

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