[Mesa-dev] [PATCH] mesa: per-texture locking
Frank Henigman
fjhenigman at google.com
Mon Jun 10 13:35:15 PDT 2013
Replace the one texture lock with a lock per texture. This allows
uploading textures from one thread concurrently with drawing in another
thread. _mesa_lock_context_textures() was used to check for texture
updates from other contexts and also to acquire the texture lock.
It's been replaced with _mesa_check_context_textures() which only does
the checking. Code sections that were between
_mesa_lock_context_textures() and _mesa_unlock_context_textures()
have been updated to lock individual textures as needed.
No piglit regressions on pineview with intel driver.
Passes new piglit test glx-multithread-texture.
Signed-off-by: Frank Henigman <fjhenigman at google.com>
---
src/mesa/drivers/dri/i915/i915_texstate.c | 23 +++++++++++++++--------
src/mesa/drivers/dri/i915/intel_tris.c | 6 ++----
src/mesa/main/attrib.c | 16 ++++++++--------
src/mesa/main/mtypes.h | 7 +++----
src/mesa/main/state.c | 7 +++----
src/mesa/main/state.h | 5 ++---
src/mesa/main/teximage.h | 10 +++++-----
src/mesa/main/texobj.c | 21 ++++-----------------
src/mesa/main/texobj.h | 5 +----
src/mesa/main/texparam.c | 2 +-
src/mesa/main/texstate.c | 6 ++++--
11 files changed, 48 insertions(+), 60 deletions(-)
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index 43c802b..bf701c3 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -30,6 +30,7 @@
#include "main/macros.h"
#include "main/colormac.h"
#include "main/samplerobj.h"
+#include "main/teximage.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
@@ -150,6 +151,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
GLint lodbias, aniso = 0;
GLubyte border[4];
GLfloat maxlod;
+ bool rc = false;
memset(state, 0, sizeof(*state));
@@ -160,8 +162,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
i915->state.tex_buffer[unit] = NULL;
}
+ _mesa_lock_texture(ctx, tObj);
+
if (!intel_finalize_mipmap_tree(intel, unit))
- return false;
+ goto finish;
/* Get first image here, since intelObj->firstLevel will get set in
* the intel_finalize_mipmap_tree() call above.
@@ -226,7 +230,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
mipFilt = MIPFILTER_LINEAR;
break;
default:
- return false;
+ goto finish;
}
if (sampler->MaxAnisotropy > 1.0) {
@@ -246,7 +250,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
magFilt = FILTER_LINEAR;
break;
default:
- return false;
+ goto finish;
}
}
@@ -269,7 +273,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
tObj->Target != GL_TEXTURE_3D) {
if (tObj->Target == GL_TEXTURE_1D)
- return false;
+ goto finish;
state[I915_TEXREG_SS2] |=
(SS2_SHADOW_ENABLE |
@@ -313,7 +317,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
wr == GL_CLAMP ||
ws == GL_CLAMP_TO_BORDER ||
wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
- return false;
+ goto finish;
/* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not
* used) when using cube map texture coordinates
@@ -321,7 +325,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
(((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
- return false;
+ goto finish;
/*
* According to 3DSTATE_MAP_STATE at page of 104 in Bspec
@@ -343,7 +347,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
*/
if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
!is_power_of_two(firstImage->Height))
- return false;
+ goto finish;
state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */
@@ -404,7 +408,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
#endif
- return true;
+ rc = true;
+ finish:
+ _mesa_unlock_texture(ctx, tObj);
+ return rc;
}
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
index 7c60d84..f09ecbd 100644
--- a/src/mesa/drivers/dri/i915/intel_tris.c
+++ b/src/mesa/drivers/dri/i915/intel_tris.c
@@ -1070,10 +1070,10 @@ intelRunPipeline(struct gl_context * ctx)
{
struct intel_context *intel = intel_context(ctx);
- _mesa_lock_context_textures(ctx);
+ _mesa_check_context_textures(ctx);
if (ctx->NewState)
- _mesa_update_state_locked(ctx);
+ _mesa_update_state_checked(ctx);
/* We need to get this done before we start the pipeline, or a
* change in the INTEL_FALLBACK() of its intel_draw_buffers() call
@@ -1098,8 +1098,6 @@ intelRunPipeline(struct gl_context * ctx)
intel->tnl_pipeline_running = true;
_tnl_run_pipeline(ctx);
intel->tnl_pipeline_running = false;
-
- _mesa_unlock_context_textures(ctx);
}
static void
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 9358e69..593ed2f 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -51,6 +51,7 @@
#include "stencil.h"
#include "texenv.h"
#include "texgen.h"
+#include "teximage.h"
#include "texobj.h"
#include "texparam.h"
#include "texstate.h"
@@ -424,7 +425,7 @@ _mesa_PushAttrib(GLbitfield mask)
goto end;
}
- _mesa_lock_context_textures(ctx);
+ _mesa_check_context_textures(ctx);
/* copy/save the bulk of texture state here */
memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture));
@@ -442,15 +443,16 @@ _mesa_PushAttrib(GLbitfield mask)
/* copy state/contents of the currently bound texture objects */
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
- _mesa_copy_texture_object(&texstate->SavedObj[u][tex],
- ctx->Texture.Unit[u].CurrentTex[tex]);
+ struct gl_texture_object *texObj =
+ ctx->Texture.Unit[u].CurrentTex[tex];
+ _mesa_lock_texture(ctx, texObj);
+ _mesa_copy_texture_object(&texstate->SavedObj[u][tex], texObj);
+ _mesa_unlock_texture(ctx, texObj);
}
}
_mesa_reference_shared_state(ctx, &texstate->SharedRef, ctx->Shared);
- _mesa_unlock_context_textures(ctx);
-
save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
}
@@ -670,7 +672,7 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
{
GLuint u;
- _mesa_lock_context_textures(ctx);
+ _mesa_check_context_textures(ctx);
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
@@ -824,8 +826,6 @@ pop_texture_group(struct gl_context *ctx, struct texture_state *texstate)
_mesa_ActiveTexture(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
_mesa_reference_shared_state(ctx, &texstate->SharedRef, NULL);
-
- _mesa_unlock_context_textures(ctx);
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 92a70f4..96503ab 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1156,7 +1156,8 @@ struct gl_sampler_object
*/
struct gl_texture_object
{
- _glthread_Mutex Mutex; /**< for thread safety */
+ _glthread_Mutex DataMutex; /**< data lock */
+ _glthread_Mutex Mutex; /**< RefCount lock */
GLint RefCount; /**< reference count */
GLuint Name; /**< the user-visible texture object ID */
GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
@@ -2519,11 +2520,9 @@ struct gl_shared_state
/**
* \name Thread safety and statechange notification for texture
* objects.
- *
- * \todo Improve the granularity of locking.
*/
/*@{*/
- _glthread_Mutex TexMutex; /**< texobj thread safety */
+ _glthread_Mutex TexMutex; /**< TextureStateStamp lock */
GLuint TextureStateStamp; /**< state notification for shared tex */
/*@}*/
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 2392641..f4f15a4 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -327,7 +327,7 @@ update_twoside(struct gl_context *ctx)
* _mesa_update_lighting() and _mesa_update_tnl_spaces().
*/
void
-_mesa_update_state_locked( struct gl_context *ctx )
+_mesa_update_state_checked( struct gl_context *ctx )
{
GLbitfield new_state = ctx->NewState;
GLbitfield prog_flags = _NEW_PROGRAM;
@@ -438,9 +438,8 @@ _mesa_update_state_locked( struct gl_context *ctx )
void
_mesa_update_state( struct gl_context *ctx )
{
- _mesa_lock_context_textures(ctx);
- _mesa_update_state_locked(ctx);
- _mesa_unlock_context_textures(ctx);
+ _mesa_check_context_textures(ctx);
+ _mesa_update_state_checked(ctx);
}
diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h
index c57dc0e..4cd6ce0 100644
--- a/src/mesa/main/state.h
+++ b/src/mesa/main/state.h
@@ -31,11 +31,10 @@
extern void
_mesa_update_state(struct gl_context *ctx);
-/* As above but can only be called between _mesa_lock_context_textures() and
- * _mesa_unlock_context_textures().
+/* As above but should only be called after _mesa_check_context_textures().
*/
extern void
-_mesa_update_state_locked(struct gl_context *ctx);
+_mesa_update_state_checked(struct gl_context *ctx);
extern void
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
index 8895247..4a24c0c 100644
--- a/src/mesa/main/teximage.h
+++ b/src/mesa/main/teximage.h
@@ -148,21 +148,21 @@ _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
GLint depth, GLint border);
/**
- * Lock a texture for updating. See also _mesa_lock_context_textures().
+ * Lock/unlock a texture for updating. See also _mesa_check_context_textures().
*/
static inline void
_mesa_lock_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
{
- _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
- ctx->Shared->TextureStateStamp++;
- (void) texObj;
+ _glthread_LOCK_MUTEX(texObj->DataMutex);
}
static inline void
_mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
{
- (void) texObj;
+ _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
+ ctx->Shared->TextureStateStamp++;
_glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
+ _glthread_UNLOCK_MUTEX(texObj->DataMutex);
}
/*@}*/
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 2168bff..1b6a48f 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -115,6 +115,7 @@ _mesa_initialize_texture_object( struct gl_texture_object *obj,
memset(obj, 0, sizeof(*obj));
/* init the non-zero fields */
_glthread_INIT_MUTEX(obj->Mutex);
+ _glthread_INIT_MUTEX(obj->DataMutex);
obj->RefCount = 1;
obj->Name = name;
obj->Target = target;
@@ -236,6 +237,7 @@ _mesa_delete_texture_object(struct gl_context *ctx,
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
_glthread_DESTROY_MUTEX(texObj->Mutex);
+ _glthread_DESTROY_MUTEX(texObj->DataMutex);
/* free this object */
free(texObj);
@@ -1442,21 +1444,13 @@ _mesa_IsTexture( GLuint texture )
/**
- * Simplest implementation of texture locking: grab the shared tex
- * mutex. Examine the shared context state timestamp and if there has
- * been a change, set the appropriate bits in ctx->NewState.
- *
- * This is used to deal with synchronizing things when a texture object
- * is used/modified by different contexts (or threads) which are sharing
- * the texture.
+ * Check for changes made in other contexts with which we might share textures.
*
* See also _mesa_lock/unlock_texture() in teximage.h
*/
void
-_mesa_lock_context_textures( struct gl_context *ctx )
+_mesa_check_context_textures( struct gl_context *ctx )
{
- _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
-
if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
ctx->NewState |= _NEW_TEXTURE;
ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
@@ -1464,13 +1458,6 @@ _mesa_lock_context_textures( struct gl_context *ctx )
}
-void
-_mesa_unlock_context_textures( struct gl_context *ctx )
-{
- assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
- _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
-}
-
void GLAPIENTRY
_mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
GLint yoffset, GLint zoffset, GLsizei width,
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index a99f45b..54a0c6e 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -135,10 +135,7 @@ extern GLuint
_mesa_total_texture_memory(struct gl_context *ctx);
extern void
-_mesa_unlock_context_textures( struct gl_context *ctx );
-
-extern void
-_mesa_lock_context_textures( struct gl_context *ctx );
+_mesa_check_context_textures( struct gl_context *ctx );
/*@}*/
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 9507bc3..d584c7b 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -1414,7 +1414,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
goto invalid_pname;
if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
- _mesa_update_state_locked(ctx);
+ _mesa_update_state(ctx);
if (_mesa_get_clamp_fragment_color(ctx)) {
params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 741985c..c99c05d 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -102,13 +102,12 @@ _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
*/
if (dst->Shared == src->Shared) {
/* copy texture object bindings, not contents of texture objects */
- _mesa_lock_context_textures(dst);
+ _mesa_check_context_textures(dst);
for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
_mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
src->Texture.Unit[u].CurrentTex[tex]);
}
- _mesa_unlock_context_textures(dst);
}
}
}
@@ -604,14 +603,17 @@ update_texture_state( struct gl_context *ctx )
struct gl_sampler_object *sampler = texUnit->Sampler ?
texUnit->Sampler : &texObj->Sampler;
+ _mesa_lock_texture(ctx, texObj);
if (!_mesa_is_texture_complete(texObj, sampler)) {
_mesa_test_texobj_completeness(ctx, texObj);
}
if (_mesa_is_texture_complete(texObj, sampler)) {
texUnit->_ReallyEnabled = 1 << texIndex;
_mesa_reference_texobj(&texUnit->_Current, texObj);
+ _mesa_unlock_texture(ctx, texObj);
break;
}
+ _mesa_unlock_texture(ctx, texObj);
}
}
--
1.8.3
More information about the mesa-dev
mailing list