mesa/src/mesa/state_tracker/st_context.c

1022 lines
35 KiB
C
Raw Permalink Normal View History

/**************************************************************************
*
* Copyright 2007 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/accum.h"
#include "main/context.h"
#include "main/debug_output.h"
#include "main/framebuffer.h"
#include "main/glthread.h"
#include "main/shaderobj.h"
#include "main/state.h"
#include "main/version.h"
#include "main/hash.h"
#include "program/prog_cache.h"
2007-08-17 15:27:18 +01:00
#include "vbo/vbo.h"
2008-06-17 21:27:36 +01:00
#include "glapi/glapi.h"
#include "st_manager.h"
#include "st_context.h"
#include "st_debug.h"
#include "st_cb_bitmap.h"
2007-08-02 17:29:50 +01:00
#include "st_cb_clear.h"
2007-08-02 21:21:16 +01:00
#include "st_cb_drawpixels.h"
2008-08-13 01:02:44 +01:00
#include "st_cb_drawtex.h"
#include "st_cb_eglimage.h"
#include "st_cb_feedback.h"
#include "st_cb_flush.h"
#include "st_atom.h"
#include "st_draw.h"
#include "st_extensions.h"
#include "st_gen_mipmap.h"
#include "st_pbo.h"
#include "st_program.h"
#include "st_sampler_view.h"
#include "st_shader_cache.h"
#include "st_texture.h"
#include "st_util.h"
#include "pipe/p_context.h"
#include "util/u_cpu_detect.h"
#include "util/u_inlines.h"
#include "util/u_upload_mgr.h"
#include "util/u_vbuf.h"
#include "util/u_memory.h"
#include "util/hash_table.h"
#include "cso_cache/cso_context.h"
#include "compiler/glsl/glsl_parser_extras.h"
#include "nir/nir_to_tgsi.h"
2007-08-10 18:37:21 +01:00
2010-08-06 22:09:51 +01:00
DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
static uint64_t
st_get_active_states(struct gl_context *ctx)
{
struct gl_program *vp = ctx->VertexProgram._Current;
struct gl_program *tcp = ctx->TessCtrlProgram._Current;
struct gl_program *tep = ctx->TessEvalProgram._Current;
struct gl_program *gp = ctx->GeometryProgram._Current;
struct gl_program *fp = ctx->FragmentProgram._Current;
struct gl_program *cp = ctx->ComputeProgram._Current;
uint64_t active_shader_states = 0;
if (vp)
active_shader_states |= vp->affected_states;
if (tcp)
active_shader_states |= tcp->affected_states;
if (tep)
active_shader_states |= tep->affected_states;
if (gp)
active_shader_states |= gp->affected_states;
if (fp)
active_shader_states |= fp->affected_states;
if (cp)
active_shader_states |= cp->affected_states;
/* Mark non-shader-resource shader states as "always active". */
return active_shader_states | ~ST_ALL_SHADER_RESOURCES;
}
void
st_invalidate_buffers(struct st_context *st)
{
st->dirty |= ST_NEW_BLEND |
ST_NEW_DSA |
ST_NEW_FB_STATE |
ST_NEW_SAMPLE_STATE |
ST_NEW_SAMPLE_SHADING |
ST_NEW_FS_STATE |
ST_NEW_POLY_STIPPLE |
ST_NEW_VIEWPORT |
ST_NEW_RASTERIZER |
ST_NEW_SCISSOR |
ST_NEW_WINDOW_RECTANGLES;
}
static inline bool
st_vp_uses_current_values(const struct gl_context *ctx)
{
const uint64_t inputs = ctx->VertexProgram._Current->info.inputs_read;
return _mesa_draw_current_bits(ctx) & inputs;
}
void
st_invalidate_state(struct gl_context *ctx)
{
GLbitfield new_state = ctx->NewState;
struct st_context *st = st_context(ctx);
if (new_state & _NEW_BUFFERS) {
st_invalidate_buffers(st);
} else {
/* These set a subset of flags set by _NEW_BUFFERS, so we only have to
* check them when _NEW_BUFFERS isn't set.
*/
if (new_state & _NEW_PROGRAM)
st->dirty |= ST_NEW_RASTERIZER;
if (new_state & _NEW_FOG)
st->dirty |= ST_NEW_FS_STATE;
}
if (new_state & (_NEW_LIGHT_STATE |
_NEW_POINT))
st->dirty |= ST_NEW_RASTERIZER;
if ((new_state & _NEW_LIGHT_STATE) &&
(st->lower_flatshade || st->lower_two_sided_color))
st->dirty |= ST_NEW_FS_STATE;
if (new_state & _NEW_PROJECTION &&
st_user_clip_planes_enabled(ctx))
st->dirty |= ST_NEW_CLIP_STATE;
if (new_state & _NEW_POINT && st->lower_texcoord_replace)
st->dirty |= ST_NEW_FS_STATE;
if (new_state & _NEW_PIXEL)
st->dirty |= ST_NEW_PIXEL_TRANSFER;
if (new_state & _NEW_CURRENT_ATTRIB && st_vp_uses_current_values(ctx)) {
st->dirty |= ST_NEW_VERTEX_ARRAYS;
/* glColor3f -> glColor4f changes the vertex format. */
ctx->Array.NewVertexElements = true;
}
/* Update the vertex shader if ctx->Light._ClampVertexColor was changed. */
if (st->clamp_vert_color_in_shader && (new_state & _NEW_LIGHT_STATE)) {
st->dirty |= ST_NEW_VS_STATE;
if (st->ctx->API == API_OPENGL_COMPAT && ctx->Version >= 32) {
st->dirty |= ST_NEW_GS_STATE | ST_NEW_TES_STATE;
}
}
/* Update the vertex shader if ctx->Point was changed. */
if (st->lower_point_size && new_state & _NEW_POINT) {
if (ctx->GeometryProgram._Current)
st->dirty |= ST_NEW_GS_STATE | ST_NEW_GS_CONSTANTS;
else if (ctx->TessEvalProgram._Current)
st->dirty |= ST_NEW_TES_STATE | ST_NEW_TES_CONSTANTS;
else
st->dirty |= ST_NEW_VS_STATE | ST_NEW_VS_CONSTANTS;
}
/* Which shaders are dirty will be determined manually. */
if (new_state & _NEW_PROGRAM) {
st->gfx_shaders_may_be_dirty = true;
st->compute_shader_may_be_dirty = true;
/* This will mask out unused shader resources. */
st->active_states = st_get_active_states(ctx);
}
if (new_state & _NEW_TEXTURE_OBJECT) {
st->dirty |= st->active_states &
(ST_NEW_SAMPLER_VIEWS |
ST_NEW_SAMPLERS |
ST_NEW_IMAGE_UNITS);
if (ctx->FragmentProgram._Current) {
struct gl_program *fp = ctx->FragmentProgram._Current;
if (fp->ExternalSamplersUsed || fp->ati_fs)
st->dirty |= ST_NEW_FS_STATE;
}
}
}
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
/*
* In some circumstances (such as running google-chrome) the state
* tracker may try to delete a resource view from a context different
* than when it was created. We don't want to do that.
*
* In that situation, st_texture_release_all_sampler_views() calls this
* function to transfer the sampler view reference to this context (expected
* to be the context which created the view.)
*/
void
st_save_zombie_sampler_view(struct st_context *st,
struct pipe_sampler_view *view)
{
struct st_zombie_sampler_view_node *entry;
assert(view->context == st->pipe);
entry = MALLOC_STRUCT(st_zombie_sampler_view_node);
if (!entry)
return;
entry->view = view;
/* We need a mutex since this function may be called from one thread
* while free_zombie_resource_views() is called from another.
*/
simple_mtx_lock(&st->zombie_sampler_views.mutex);
list_addtail(&entry->node, &st->zombie_sampler_views.list.node);
simple_mtx_unlock(&st->zombie_sampler_views.mutex);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
}
/*
* Since OpenGL shaders may be shared among contexts, we can wind up
* with variants of a shader created with different contexts.
* When we go to destroy a gallium shader, we want to free it with the
* same context that it was created with, unless the driver reports
* PIPE_CAP_SHAREABLE_SHADERS = TRUE.
*/
void
st_save_zombie_shader(struct st_context *st,
enum pipe_shader_type type,
struct pipe_shader_state *shader)
{
struct st_zombie_shader_node *entry;
/* we shouldn't be here if the driver supports shareable shaders */
assert(!st->has_shareable_shaders);
entry = MALLOC_STRUCT(st_zombie_shader_node);
if (!entry)
return;
entry->shader = shader;
entry->type = type;
/* We need a mutex since this function may be called from one thread
* while free_zombie_shaders() is called from another.
*/
simple_mtx_lock(&st->zombie_shaders.mutex);
list_addtail(&entry->node, &st->zombie_shaders.list.node);
simple_mtx_unlock(&st->zombie_shaders.mutex);
}
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
/*
* Free any zombie sampler views that may be attached to this context.
*/
static void
free_zombie_sampler_views(struct st_context *st)
{
struct st_zombie_sampler_view_node *entry, *next;
if (list_is_empty(&st->zombie_sampler_views.list.node)) {
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
return;
}
simple_mtx_lock(&st->zombie_sampler_views.mutex);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
LIST_FOR_EACH_ENTRY_SAFE(entry, next,
&st->zombie_sampler_views.list.node, node) {
list_del(&entry->node); // remove this entry from the list
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
assert(entry->view->context == st->pipe);
pipe_sampler_view_reference(&entry->view, NULL);
free(entry);
}
assert(list_is_empty(&st->zombie_sampler_views.list.node));
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
simple_mtx_unlock(&st->zombie_sampler_views.mutex);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
}
/*
* Free any zombie shaders that may be attached to this context.
*/
static void
free_zombie_shaders(struct st_context *st)
{
struct st_zombie_shader_node *entry, *next;
if (list_is_empty(&st->zombie_shaders.list.node)) {
return;
}
simple_mtx_lock(&st->zombie_shaders.mutex);
LIST_FOR_EACH_ENTRY_SAFE(entry, next,
&st->zombie_shaders.list.node, node) {
list_del(&entry->node); // remove this entry from the list
switch (entry->type) {
case PIPE_SHADER_VERTEX:
st->pipe->bind_vs_state(st->pipe, NULL);
st->pipe->delete_vs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_FRAGMENT:
st->pipe->bind_fs_state(st->pipe, NULL);
st->pipe->delete_fs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_GEOMETRY:
st->pipe->bind_gs_state(st->pipe, NULL);
st->pipe->delete_gs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_CTRL:
st->pipe->bind_tcs_state(st->pipe, NULL);
st->pipe->delete_tcs_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_TESS_EVAL:
st->pipe->bind_tes_state(st->pipe, NULL);
st->pipe->delete_tes_state(st->pipe, entry->shader);
break;
case PIPE_SHADER_COMPUTE:
st->pipe->bind_compute_state(st->pipe, NULL);
st->pipe->delete_compute_state(st->pipe, entry->shader);
break;
default:
unreachable("invalid shader type in free_zombie_shaders()");
}
free(entry);
}
assert(list_is_empty(&st->zombie_shaders.list.node));
simple_mtx_unlock(&st->zombie_shaders.mutex);
}
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
/*
* This function is called periodically to free any zombie objects
* which are attached to this context.
*/
void
st_context_free_zombie_objects(struct st_context *st)
{
free_zombie_sampler_views(st);
free_zombie_shaders(st);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
}
static void
st_destroy_context_priv(struct st_context *st, bool destroy_pipe)
{
st_destroy_atoms(st);
st_destroy_draw(st);
st_destroy_clear(st);
st_destroy_bitmap(st);
st_destroy_drawpix(st);
st_destroy_drawtex(st);
st_destroy_pbo_helpers(st);
st_destroy_bound_texture_handles(st);
st_destroy_bound_image_handles(st);
/* free glReadPixels cache data */
st_invalidate_readpix_cache(st);
util_throttle_deinit(st->screen, &st->throttle);
cso_destroy_context(st->cso_context);
if (st->pipe && destroy_pipe)
st->pipe->destroy(st->pipe);
FREE(st);
}
static void
st_init_driver_flags(struct st_context *st)
{
struct gl_driver_flags *f = &st->ctx->DriverFlags;
/* Shader resources */
if (st->has_hw_atomics)
f->NewAtomicBuffer = ST_NEW_HW_ATOMICS | ST_NEW_CS_ATOMICS;
else
f->NewAtomicBuffer = ST_NEW_ATOMIC_BUFFER;
f->NewShaderConstants[MESA_SHADER_VERTEX] = ST_NEW_VS_CONSTANTS;
f->NewShaderConstants[MESA_SHADER_TESS_CTRL] = ST_NEW_TCS_CONSTANTS;
f->NewShaderConstants[MESA_SHADER_TESS_EVAL] = ST_NEW_TES_CONSTANTS;
f->NewShaderConstants[MESA_SHADER_GEOMETRY] = ST_NEW_GS_CONSTANTS;
f->NewShaderConstants[MESA_SHADER_FRAGMENT] = ST_NEW_FS_CONSTANTS;
f->NewShaderConstants[MESA_SHADER_COMPUTE] = ST_NEW_CS_CONSTANTS;
if (st->lower_alpha_test)
f->NewAlphaTest = ST_NEW_FS_STATE | ST_NEW_FS_CONSTANTS;
else
f->NewAlphaTest = ST_NEW_DSA;
f->NewMultisampleEnable = ST_NEW_BLEND | ST_NEW_RASTERIZER |
ST_NEW_SAMPLE_STATE | ST_NEW_SAMPLE_SHADING;
f->NewSampleShading = ST_NEW_SAMPLE_SHADING;
/* This depends on what the gallium driver wants. */
if (st->force_persample_in_shader) {
f->NewMultisampleEnable |= ST_NEW_FS_STATE;
f->NewSampleShading |= ST_NEW_FS_STATE;
} else {
f->NewSampleShading |= ST_NEW_RASTERIZER;
}
if (st->clamp_frag_color_in_shader) {
f->NewFragClamp = ST_NEW_FS_STATE;
} else {
f->NewFragClamp = ST_NEW_RASTERIZER;
}
f->NewClipPlaneEnable = ST_NEW_RASTERIZER;
if (st->lower_ucp)
f->NewClipPlaneEnable |= ST_NEW_VS_STATE | ST_NEW_GS_STATE | ST_NEW_TES_STATE;
if (st->emulate_gl_clamp)
f->NewSamplersWithClamp = ST_NEW_SAMPLERS |
ST_NEW_VS_STATE | ST_NEW_TCS_STATE |
ST_NEW_TES_STATE | ST_NEW_GS_STATE |
ST_NEW_FS_STATE | ST_NEW_CS_STATE;
if (!st->has_hw_atomics && st->ctx->Const.ShaderStorageBufferOffsetAlignment > 4)
f->NewAtomicBuffer |= ST_NEW_CONSTANTS;
}
static bool
st_have_perfmon(struct st_context *st)
{
struct pipe_screen *screen = st->screen;
if (!screen->get_driver_query_info || !screen->get_driver_query_group_info)
return false;
return screen->get_driver_query_group_info(screen, 0, NULL) != 0;
}
static bool
st_have_perfquery(struct st_context *ctx)
{
struct pipe_context *pipe = ctx->pipe;
return pipe->init_intel_perf_query_info && pipe->get_intel_perf_query_info &&
pipe->get_intel_perf_query_counter_info &&
pipe->new_intel_perf_query_obj && pipe->begin_intel_perf_query &&
pipe->end_intel_perf_query && pipe->delete_intel_perf_query &&
pipe->wait_intel_perf_query && pipe->is_intel_perf_query_ready &&
pipe->get_intel_perf_query_data;
}
static struct st_context *
st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe,
const struct st_config_options *options)
{
struct pipe_screen *screen = pipe->screen;
struct st_context *st = CALLOC_STRUCT( st_context);
st->options = *options;
ctx->st_opts = &st->options;
ctx->st = st;
st->ctx = ctx;
st->screen = screen;
st->pipe = pipe;
st->dirty = ST_ALL_STATES_MASK;
st->can_bind_const_buffer_as_vertex =
screen->get_param(screen, PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX);
/* st/mesa always uploads zero-stride vertex attribs, and other user
* vertex buffers are only possible with a compatibility profile.
* So tell the u_vbuf module that user VBOs are not possible with the Core
* profile, so that u_vbuf is bypassed completely if there is nothing else
* to do.
*/
unsigned cso_flags;
switch (ctx->API) {
case API_OPENGL_CORE:
cso_flags = CSO_NO_USER_VERTEX_BUFFERS;
break;
case API_OPENGLES:
case API_OPENGLES2:
cso_flags = CSO_NO_64B_VERTEX_BUFFERS;
break;
default:
cso_flags = 0;
break;
}
st->cso_context = cso_create_context(pipe, cso_flags);
ctx->cso_context = st->cso_context;
st_init_atoms(st);
st_init_clear(st);
{
enum pipe_texture_transfer_mode val = screen->get_param(screen, PIPE_CAP_TEXTURE_TRANSFER_MODES);
st->prefer_blit_based_texture_transfer = (val & PIPE_TEXTURE_TRANSFER_BLIT) != 0;
st->allow_compute_based_texture_transfer = (val & PIPE_TEXTURE_TRANSFER_COMPUTE) != 0;
}
st_init_pbo_helpers(st);
2007-08-03 03:40:19 +01:00
/* Choose texture target for glDrawPixels, glBitmap, renderbuffers */
if (screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES))
st->internal_target = PIPE_TEXTURE_2D;
else
st->internal_target = PIPE_TEXTURE_RECT;
/* Setup vertex element info for 'struct st_util_vertex'.
*/
{
STATIC_ASSERT(sizeof(struct st_util_vertex) == 9 * sizeof(float));
memset(&st->util_velems, 0, sizeof(st->util_velems));
st->util_velems.velems[0].src_offset = 0;
st->util_velems.velems[0].vertex_buffer_index = 0;
st->util_velems.velems[0].src_format = PIPE_FORMAT_R32G32B32_FLOAT;
st->util_velems.velems[1].src_offset = 3 * sizeof(float);
st->util_velems.velems[1].vertex_buffer_index = 0;
st->util_velems.velems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
st->util_velems.velems[2].src_offset = 7 * sizeof(float);
st->util_velems.velems[2].vertex_buffer_index = 0;
st->util_velems.velems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
}
ctx->Const.PackedDriverUniformStorage =
screen->get_param(screen, PIPE_CAP_PACKED_UNIFORMS);
ctx->Const.BitmapUsesRed =
screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW);
st->has_stencil_export =
screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
st->has_etc1 = screen->is_format_supported(screen, PIPE_FORMAT_ETC1_RGB8,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW);
st->has_etc2 = screen->is_format_supported(screen, PIPE_FORMAT_ETC2_RGB8,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW);
st->transcode_etc = options->transcode_etc &&
screen->is_format_supported(screen, PIPE_FORMAT_DXT1_SRGBA,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW);
Revert "st/mesa: Transcode ASTC to BC7 (BPTC) where possible" This reverts commit 68ef895674b176b4faf875a4d7f4d787b330d4d9. When trying out transcode_astc=true with BPTC on Asphalt 9, we observed very poor image quality - to the point that basic UI icons were blocky, and buttons with a black border had smeared pixels on the edges. Using DXT5 had no such issues. I originally suspected there was a bug in the BPTC encoder, but I now believe the issue is deeper than that. The commit that introduced the encoder, 17cde55c538009764207bd29b78a909d2c5d14b4, says: "The compressor is written from scratch and takes a very simple approach. It always uses a single mode of the BPTC format (4 for unorm and 3 for half-floats) and picks the two endpoints by dividing the texels into those which have more or less than the average luminance of the block and then calculating an average color of the texels within each division. It's probably not really sensible to try to use BPTC compression at runtime because for example with the Nvidia offline compression tool it can take in the order of an hour to compress a full-screen image. With that in mind I don't think it's worth having a proper compressor in Mesa and this approach gives reasonable results for a usage that is basically a corner case." In other words, the reason our BPTC compressor was so fast is that it only implements one of the modes and does a low quality approximation. This honestly should probably be improved somewhat, but the original use case was for online-compression, the uncommon but mandatory OpenGL feature where you can supply uncompressed data and trust the driver to compress it for you (at unknown and uncontrolled quality and speed). Unfortunately, the compressor as it stands is simply not usable for transcoding ASTC data where we want to preserve the underlying image quality as much as possible. Reviewed-by: Emma Anholt <emma@anholt.net> Reviewed-by: Tapani Pälli <tapani.palli@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16566>
2022-05-17 21:51:49 +01:00
st->transcode_astc = options->transcode_astc &&
screen->is_format_supported(screen, PIPE_FORMAT_DXT5_SRGBA,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW) &&
screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
PIPE_TEXTURE_2D, 0, 0,
PIPE_BIND_SAMPLER_VIEW);
st->has_astc_2d_ldr =
screen->is_format_supported(screen, PIPE_FORMAT_ASTC_4x4_SRGB,
PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW);
st->has_astc_5x5_ldr =
screen->is_format_supported(screen, PIPE_FORMAT_ASTC_5x5_SRGB,
PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW);
st->force_persample_in_shader =
screen->get_param(screen, PIPE_CAP_SAMPLE_SHADING) &&
!screen->get_param(screen, PIPE_CAP_FORCE_PERSAMPLE_INTERP);
st->has_shareable_shaders = screen->get_param(screen,
PIPE_CAP_SHAREABLE_SHADERS);
st->needs_texcoord_semantic =
screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD);
st->apply_texture_swizzle_to_border_color =
!!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
(PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 |
PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600));
st->use_format_with_border_color =
!!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) &
PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO);
st->emulate_gl_clamp =
!screen->get_param(screen, PIPE_CAP_GL_CLAMP);
st->texture_buffer_sampler =
screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_SAMPLER);
st->has_time_elapsed =
screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED);
st->has_half_float_packing =
screen->get_param(screen, PIPE_CAP_SHADER_PACK_HALF_FLOAT);
st->has_multi_draw_indirect =
screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT);
st->has_indirect_partial_stride =
screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE);
gallium: Add the ability to query a single pipeline statistics counter Gallium historically has treated pipeline statistics queries as a single query, PIPE_QUERY_PIPELINE_STATISTICS, which returns a block of 11 values. This was originally patterned after the D3D1x API. Much later, Brian introduced an OpenGL extension that exposed these counters - but it exposes 11 separate queries, each of which returns a single value. Today, st/mesa simply queries all 11 values, and returns a single value. While pipeline statistics counters aren't typically performance critical, this is still not a great fit. A D3D1x->GL translator might request all 11 counters by creating 11 separate GL queries...which Gallium would map to reads of all 11 values each time, resulting in a total 121 counter reads. That's not ideal. This patch adds a new cap, PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE, and corresponding query type PIPE_QUERY_PIPELINE_STATISTICS_SINGLE. When calling create_query(), q->index should be set to one of the PIPE_STAT_QUERY_* enums to select a counter. Unlike the block query, this returns the value in pipe_query_result::u64 (as it's a single value) instead of the pipe_query_data_pipeline_statistics group. We update st/mesa to expose ARB_pipeline_statistics_query if either capability is set, preferring the new SINGLE variant when available. Thanks to Roland, Ilia, and Marek for helping me sort this out. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
2018-09-28 10:21:47 +01:00
st->has_single_pipe_stat =
screen->get_param(screen, PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE);
st/mesa: Optionally override RGB/RGBX dst alpha blend factors Intel's blending hardware does not properly return 1.0 for destination alpha for RGBX formats; it requires the factors to be overridden to either zero or one. Broadcom vc4 and v3d also could use this override. While overriding these factors is safe in general, Nouveau and Radeon would prefer not to. Their blending hardware already returns correct values for RGB/RGBX formats, and would like to avoid the resulting per-buffer blending and independent blend factors (rgb != a) since it can cause additional overhead. I considered simply handling this in the driver, but it's not as nice. pipe_blend_state doesn't have any format information, so we'd need the hardware blend state to depend on both pipe_blend_state and pipe_framebuffer_state. Furthermore, Intel GPUs don't have a native RGBX_SNORM format, so I avoid exposing one, which makes Gallium fall back to RGBA_SNORM. The pipe_surfaces we get in the driver have an RGBA format, making it impossible to tell that there shouldn't be an alpha channel. One could argue that st not handling it in that case is a bug. To work around this, we'd have to expose RGBX pipe formats, mapped to RGBA hardware formats, and add format swizzling special cases. All doable, but it ends up being more code than I'd like. st_atom_blend already has access to the right information and it's trivial to accomplish there, so we just add a cap bit and do that. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Eric Anholt <eric@anholt.net>
2018-07-22 07:40:16 +01:00
st->has_indep_blend_func =
screen->get_param(screen, PIPE_CAP_INDEP_BLEND_FUNC);
st->needs_rgb_dst_alpha_override =
screen->get_param(screen, PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND);
st->can_dither =
screen->get_param(screen, PIPE_CAP_DITHERING);
st->lower_flatshade =
!screen->get_param(screen, PIPE_CAP_FLATSHADE);
st->lower_alpha_test =
!screen->get_param(screen, PIPE_CAP_ALPHA_TEST);
st->lower_point_size =
!screen->get_param(screen, PIPE_CAP_POINT_SIZE_FIXED);
st->lower_two_sided_color =
!screen->get_param(screen, PIPE_CAP_TWO_SIDED_COLOR);
st->lower_ucp =
!screen->get_param(screen, PIPE_CAP_CLIP_PLANES);
st->prefer_real_buffer_in_constbuf0 =
screen->get_param(screen, PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0);
st->has_conditional_render =
screen->get_param(screen, PIPE_CAP_CONDITIONAL_RENDER);
st->lower_texcoord_replace =
!screen->get_param(screen, PIPE_CAP_POINT_SPRITE);
st->lower_rect_tex =
!screen->get_param(screen, PIPE_CAP_TEXRECT);
st->allow_st_finalize_nir_twice = screen->finalize_nir != NULL;
st->has_hw_atomics =
screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS)
? true : false;
util_throttle_init(&st->throttle,
screen->get_param(screen,
PIPE_CAP_MAX_TEXTURE_UPLOAD_MEMORY_BUDGET));
/* GL limits and extensions */
st_init_limits(screen, &ctx->Const, &ctx->Extensions);
st_init_extensions(screen, &ctx->Const,
&ctx->Extensions, &st->options, ctx->API);
if (st_have_perfmon(st)) {
ctx->Extensions.AMD_performance_monitor = GL_TRUE;
}
if (st_have_perfquery(st)) {
ctx->Extensions.INTEL_performance_query = GL_TRUE;
}
/* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */
if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
st->clamp_vert_color_in_shader = GL_TRUE;
}
if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) {
st->clamp_frag_color_in_shader = GL_TRUE;
}
/* For drivers which cannot do color clamping, it's better to just
* disable ARB_color_buffer_float in the core profile, because
* the clamping is deprecated there anyway. */
if (ctx->API == API_OPENGL_CORE &&
(st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) {
st->clamp_vert_color_in_shader = GL_FALSE;
st->clamp_frag_color_in_shader = GL_FALSE;
ctx->Extensions.ARB_color_buffer_float = GL_FALSE;
}
}
/* called after _mesa_create_context/_mesa_init_point, fix default user
* settable max point size up
*/
ctx->Point.MaxSize = MAX2(ctx->Const.MaxPointSize,
ctx->Const.MaxPointSizeAA);
ctx->Const.PointCoordOriginUpperLeft =
screen->get_param(screen, PIPE_CAP_POINT_COORD_ORIGIN_UPPER_LEFT);
ctx->Const.NoClippingOnCopyTex = screen->get_param(screen,
PIPE_CAP_NO_CLIP_ON_COPY_TEX);
ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].PositionAlwaysInvariant = options->vs_position_always_invariant;
ctx->Const.ShaderCompilerOptions[MESA_SHADER_TESS_EVAL].PositionAlwaysPrecise = options->vs_position_always_precise;
/* NIR drivers that support tess shaders and compact arrays need to use
* GLSLTessLevelsAsInputs / PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS. The NIR
* linker doesn't support linking these as compat arrays of sysvals.
*/
assert(ctx->Const.GLSLTessLevelsAsInputs ||
!screen->get_param(screen, PIPE_CAP_NIR_COMPACT_ARRAYS) ||
!ctx->Extensions.ARB_tessellation_shader);
/* Set which shader types can be compiled at link time. */
st->shader_has_one_variant[MESA_SHADER_VERTEX] =
st->has_shareable_shaders &&
!st->clamp_vert_color_in_shader &&
!st->lower_point_size &&
!st->lower_ucp;
st->shader_has_one_variant[MESA_SHADER_FRAGMENT] =
st->has_shareable_shaders &&
!st->lower_flatshade &&
!st->lower_alpha_test &&
!st->clamp_frag_color_in_shader &&
!st->force_persample_in_shader &&
!st->lower_two_sided_color &&
!st->lower_texcoord_replace;
st->shader_has_one_variant[MESA_SHADER_TESS_CTRL] = st->has_shareable_shaders;
st->shader_has_one_variant[MESA_SHADER_TESS_EVAL] =
st->has_shareable_shaders &&
!st->clamp_vert_color_in_shader &&
!st->lower_point_size &&
!st->lower_ucp;
st->shader_has_one_variant[MESA_SHADER_GEOMETRY] =
st->has_shareable_shaders &&
!st->clamp_vert_color_in_shader &&
!st->lower_point_size &&
!st->lower_ucp;
st->shader_has_one_variant[MESA_SHADER_COMPUTE] = st->has_shareable_shaders;
if (util_get_cpu_caps()->num_L3_caches == 1 ||
!st->pipe->set_context_param)
st->pin_thread_counter = ST_L3_PINNING_DISABLED;
st->bitmap.cache.empty = true;
if (ctx->Const.ForceGLNamesReuse && ctx->Shared->RefCount == 1) {
_mesa_HashEnableNameReuse(ctx->Shared->TexObjects);
_mesa_HashEnableNameReuse(ctx->Shared->ShaderObjects);
_mesa_HashEnableNameReuse(ctx->Shared->BufferObjects);
_mesa_HashEnableNameReuse(ctx->Shared->SamplerObjects);
_mesa_HashEnableNameReuse(ctx->Shared->FrameBuffers);
_mesa_HashEnableNameReuse(ctx->Shared->RenderBuffers);
_mesa_HashEnableNameReuse(ctx->Shared->MemoryObjects);
_mesa_HashEnableNameReuse(ctx->Shared->SemaphoreObjects);
}
/* SPECviewperf13/sw-04 crashes since a56849ddda6 if Mesa is build with
* -O3 on gcc 7.5, which doesn't happen with ForceGLNamesReuse, which is
* the default setting for SPECviewperf because it simulates glGen behavior
* of closed source drivers.
*/
if (ctx->Const.ForceGLNamesReuse)
_mesa_HashEnableNameReuse(ctx->Query.QueryObjects);
_mesa_override_extensions(ctx);
_mesa_compute_version(ctx);
if (ctx->Version == 0) {
/* This can happen when a core profile was requested, but the driver
* does not support some features of GL 3.1 or later.
*/
st_destroy_context_priv(st, false);
return NULL;
}
/* This must be done after extensions are initialized to enable persistent
* mappings immediately.
*/
_vbo_CreateContext(ctx);
_mesa_initialize_dispatch_tables(ctx);
st_init_driver_flags(st);
/* Initialize context's winsys buffers list */
list_inithead(&st->winsys_buffers);
list_inithead(&st->zombie_sampler_views.list.node);
simple_mtx_init(&st->zombie_sampler_views.mutex, mtx_plain);
list_inithead(&st->zombie_shaders.list.node);
simple_mtx_init(&st->zombie_shaders.mutex, mtx_plain);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
ctx->Const.DriverSupportedPrimMask = screen->get_param(screen, PIPE_CAP_SUPPORTED_PRIM_MODES) |
/* patches is always supported */
BITFIELD_BIT(PIPE_PRIM_PATCHES);
return st;
}
void
st_set_background_context(struct gl_context *ctx,
struct util_queue_monitoring *queue_info)
{
struct st_context *st = ctx->st;
struct st_manager *smapi =
(struct st_manager *) st->iface.st_context_private;
assert(smapi->set_background_context);
smapi->set_background_context(&st->iface, queue_info);
}
static void
st_init_driver_functions(struct pipe_screen *screen,
struct dd_function_table *functions,
bool has_egl_image_validate)
{
st_init_draw_functions(screen, functions);
st_init_eglimage_functions(functions, has_egl_image_validate);
functions->NewProgram = _mesa_new_program;
st_init_flush_functions(screen, functions);
/* GL_ARB_get_program_binary */
functions->ShaderCacheSerializeDriverBlob = st_serialise_nir_program;
functions->ProgramBinarySerializeDriverBlob =
st_serialise_nir_program_binary;
functions->ProgramBinaryDeserializeDriverBlob =
st_deserialise_nir_program;
}
struct st_context *
st_create_context(gl_api api, struct pipe_context *pipe,
const struct gl_config *visual,
struct st_context *share,
const struct st_config_options *options,
bool no_error, bool has_egl_image_validate)
{
struct gl_context *ctx;
struct gl_context *shareCtx = share ? share->ctx : NULL;
struct dd_function_table funcs;
struct st_context *st;
memset(&funcs, 0, sizeof(funcs));
st_init_driver_functions(pipe->screen, &funcs, has_egl_image_validate);
/* gl_context must be 16-byte aligned due to the alignment on GLmatrix. */
ctx = align_malloc(sizeof(struct gl_context), 16);
if (!ctx)
return NULL;
memset(ctx, 0, sizeof(*ctx));
ctx->pipe = pipe;
ctx->screen = pipe->screen;
if (!_mesa_initialize_context(ctx, api, no_error, visual, shareCtx, &funcs)) {
align_free(ctx);
return NULL;
}
st_debug_init();
if (pipe->screen->get_disk_shader_cache)
ctx->Cache = pipe->screen->get_disk_shader_cache(pipe->screen);
/* XXX: need a capability bit in gallium to query if the pipe
* driver prefers DP4 or MUL/MAD for vertex transformation.
*/
if (debug_get_option_mesa_mvp_dp4())
ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE;
if (pipe->screen->get_param(pipe->screen, PIPE_CAP_INVALIDATE_BUFFER))
ctx->has_invalidate_buffer = true;
st = st_create_context_priv(ctx, pipe, options);
if (!st) {
_mesa_free_context_data(ctx, true);
align_free(ctx);
}
return st;
}
/**
* When we destroy a context, we must examine all texture objects to
* find/release any sampler views created by that context.
*
* This callback is called per-texture object. It releases all the
* texture's sampler views which belong to the context.
*/
static void
destroy_tex_sampler_cb(void *data, void *userData)
{
struct gl_texture_object *texObj = (struct gl_texture_object *) data;
struct st_context *st = (struct st_context *) userData;
st_texture_release_context_sampler_view(st, texObj);
}
static void
destroy_framebuffer_attachment_sampler_cb(void *data, void *userData)
{
struct gl_framebuffer* glfb = (struct gl_framebuffer*) data;
struct st_context *st = (struct st_context *) userData;
for (unsigned i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = &glfb->Attachment[i];
if (att->Texture) {
st_texture_release_context_sampler_view(st, att->Texture);
}
}
}
void
st_destroy_context(struct st_context *st)
{
struct gl_context *ctx = st->ctx;
struct gl_framebuffer *stfb, *next;
struct gl_framebuffer *save_drawbuffer;
struct gl_framebuffer *save_readbuffer;
/* Save the current context and draw/read buffers*/
GET_CURRENT_CONTEXT(save_ctx);
if (save_ctx) {
save_drawbuffer = save_ctx->WinSysDrawBuffer;
save_readbuffer = save_ctx->WinSysReadBuffer;
} else {
save_drawbuffer = save_readbuffer = NULL;
}
/*
* We need to bind the context we're deleting so that
* _mesa_reference_texobj_() uses this context when deleting textures.
* Similarly for framebuffer objects, etc.
*/
_mesa_make_current(ctx, NULL, NULL);
/* This must be called first so that glthread has a chance to finish */
_mesa_glthread_destroy(ctx, NULL);
_mesa_HashWalk(ctx->Shared->TexObjects, destroy_tex_sampler_cb, st);
/* For the fallback textures, free any sampler views belonging to this
* context.
*/
for (unsigned i = 0; i < NUM_TEXTURE_TARGETS; i++) {
struct gl_texture_object *stObj =
ctx->Shared->FallbackTex[i];
if (stObj) {
st_texture_release_context_sampler_view(st, stObj);
}
}
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
st_context_free_zombie_objects(st);
simple_mtx_destroy(&st->zombie_sampler_views.mutex);
simple_mtx_destroy(&st->zombie_shaders.mutex);
st/mesa: implement "zombie" sampler views (v2) When st_texture_release_all_sampler_views() is called the texture may have sampler views belonging to several contexts. If we unreference a sampler view and its refcount hits zero, we need to be sure to destroy the sampler view with the same context which created it. This was not the case with the previous code which used pipe_sampler_view_release(). That function could end up freeing a sampler view with a context different than the one which created it. In the case of the VMware svga driver, we detected this but leaked the sampler view. This led to a crash with google-chrome when the kernel module had too many sampler views. VMware bug 2274734. Alternately, if we try to delete a sampler view with the correct context, we may be "reaching into" a context which is active on another thread. That's not safe. To fix these issues this patch adds a per-context list of "zombie" sampler views. These are views which are to be freed at some point when the context is active. Other contexts may safely add sampler views to the zombie list at any time (it's mutex protected). This avoids the context/view ownership mix-ups we had before. Tested with: google-chrome, google earth, Redway3D Watch/Turbine demos a few Linux games. If anyone can recomment some other multi-threaded, multi-context GL apps to test, please let me know. v2: avoid potential race issue by always adding sampler views to the zombie list if the view's context doesn't match the current context, ignoring the refcount. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Reviewed-by: Neha Bhende <bhenden@vmware.com> Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> Reviewed-By: Jose Fonseca <jfonseca@vmware.com>
2019-03-12 15:13:00 +00:00
st_release_program(st, &st->fp);
st_release_program(st, &st->gp);
st_release_program(st, &st->vp);
st_release_program(st, &st->tcp);
st_release_program(st, &st->tep);
st_release_program(st, &st->cp);
if (st->hw_select_shaders) {
hash_table_foreach(st->hw_select_shaders, entry)
st->pipe->delete_gs_state(st->pipe, entry->data);
_mesa_hash_table_destroy(st->hw_select_shaders, NULL);
}
/* release framebuffer in the winsys buffers list */
LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) {
_mesa_reference_framebuffer(&stfb, NULL);
}
_mesa_HashWalk(ctx->Shared->FrameBuffers, destroy_framebuffer_attachment_sampler_cb, st);
pipe_sampler_view_reference(&st->pixel_xfer.pixelmap_sampler_view, NULL);
pipe_resource_reference(&st->pixel_xfer.pixelmap_texture, NULL);
_vbo_DestroyContext(ctx);
st_destroy_program_variants(st);
/* Do not release debug_output yet because it might be in use by other threads.
* These threads will be terminated by _mesa_free_context_data and
* st_destroy_context_priv.
*/
_mesa_free_context_data(ctx, false);
/* This will free the st_context too, so 'st' must not be accessed
* afterwards. */
st_destroy_context_priv(st, true);
st = NULL;
_mesa_destroy_debug_output(ctx);
align_free(ctx);
if (save_ctx == ctx) {
/* unbind the context we just deleted */
_mesa_make_current(NULL, NULL, NULL);
} else {
/* Restore the current context and draw/read buffers (may be NULL) */
_mesa_make_current(save_ctx, save_drawbuffer, save_readbuffer);
}
}
const struct nir_shader_compiler_options *
st_get_nir_compiler_options(struct st_context *st, gl_shader_stage stage)
{
const struct nir_shader_compiler_options *options =
st->ctx->Const.ShaderCompilerOptions[stage].NirOptions;
if (options) {
return options;
} else {
return nir_to_tgsi_get_compiler_options(st->screen,
PIPE_SHADER_IR_NIR,
pipe_shader_type_from_mesa(stage));
}
}