Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactor: Cache MaterialSnapshots produced by MaterialsPrepare
Now that we have render context variants of Material (i.e., MaterialVariant)
it is no longer necessary to allocate MaterialSnapshots on the stack
each time they are needed. Instead, store a copy of the snapshot in the
variant instance.

Todo: Presently the cached MaterialSnapshot owned by MaterialVariant is
updated on each call to Materials::Prepare (when snapshot updating is
enabled). It should now be possible to update only once per render frame.

Todo: Cleanup the object API for material preparation.
  • Loading branch information
danij-deng committed Oct 29, 2011
1 parent e18768b commit 0b6f5ec
Show file tree
Hide file tree
Showing 20 changed files with 361 additions and 242 deletions.
17 changes: 17 additions & 0 deletions doomsday/engine/portable/include/materialvariant.h
Expand Up @@ -129,6 +129,9 @@ typedef struct materialvariant_s {

/// Specification used to derive this variant.
materialvariantspecification_t* _spec;

/// Cached copy of current state if any.
material_snapshot_t* _snapshot;
} materialvariant_t;

materialvariant_t* MaterialVariant_New(struct material_s* generalCase,
Expand Down Expand Up @@ -160,6 +163,20 @@ materialvariantspecification_t* MaterialVariant_Spec(const materialvariant_t* ma
*/
const materialvariant_layer_t* MaterialVariant_Layer(materialvariant_t* mat, int layer);

/**
* Attach MaterialSnapshot data to this. MaterialVariant is given ownership of @a materialSnapshot.
* @return Same as @a materialSnapshot for caller convenience.
*/
material_snapshot_t* MaterialVariant_AttachSnapshot(materialvariant_t* mat, material_snapshot_t* materialSnapshot);

/**
* Detach MaterialSnapshot data from this. Ownership of the data is relinquished to the caller.
*/
material_snapshot_t* MaterialVariant_DetachSnapshot(materialvariant_t* mat);

/// @return MaterialSnapshot data associated with this.
material_snapshot_t* MaterialVariant_Snapshot(const materialvariant_t* mat);

/// @return Translated 'next' (or target) MaterialVariant if set, else this.
materialvariant_t* MaterialVariant_TranslationNext(materialvariant_t* mat);

Expand Down
4 changes: 2 additions & 2 deletions doomsday/engine/portable/include/p_materialmanager.h
Expand Up @@ -151,8 +151,8 @@ uint Materials_Count(void);
const ded_decor_t* Materials_DecorationDef(struct material_s* material);
const ded_ptcgen_t* Materials_PtcGenDef(struct material_s* material);

struct materialvariant_s* Materials_Prepare(struct material_snapshot_s* snapshot,
struct material_s* material, boolean smoothed, struct materialvariantspecification_s* spec);
struct materialvariant_s* Materials_Prepare(struct material_s* material,
struct materialvariantspecification_s* spec, boolean smoothed, boolean updateSnapshot);

int Materials_AnimGroupCount(void);
void Materials_ResetAnimGroups(void);
Expand Down
23 changes: 13 additions & 10 deletions doomsday/engine/portable/src/gl_main.c
Expand Up @@ -971,24 +971,27 @@ int GL_GetTexAnisoMul(int level)

void GL_SetMaterialUI(material_t* mat)
{
material_snapshot_t ms;
materialvariant_t* variant;
material_snapshot_t* ms;

if(!mat)
return; // \fixme we need a "NULL material".
if(!mat) return; // \fixme we need a "NULL material".

Materials_Prepare(&ms, mat,
variant = Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_UI, 0, 1, 0, 0,
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0, 1, 0, false, false, false, false), true);
GL_BindTexture(MSU(&ms, MTU_PRIMARY).tex.glName, MSU(&ms, MTU_PRIMARY).magMode);
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0, 1, 0, false, false, false, false), true, true);
ms = MaterialVariant_Snapshot(variant);
GL_BindTexture(MSU(ms, MTU_PRIMARY).tex.glName, MSU(ms, MTU_PRIMARY).magMode);
}

void GL_SetPSprite(material_t* mat, int tClass, int tMap)
{
material_snapshot_t ms;
Materials_Prepare(&ms, mat,
materialvariant_t* variant;
material_snapshot_t* ms;
variant = Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_PSPRITE, 0, 1, tClass,
tMap, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0, 1, 0, false, true, true, false), true);
GL_BindTexture(MSU(&ms, MTU_PRIMARY).tex.glName, MSU(&ms, MTU_PRIMARY).magMode);
tMap, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0, 1, 0, false, true, true, false), true, true);
ms = MaterialVariant_Snapshot(variant);
GL_BindTexture(MSU(ms, MTU_PRIMARY).tex.glName, MSU(ms, MTU_PRIMARY).magMode);
}

void GL_SetRawImage(lumpnum_t lumpNum, int wrapS, int wrapT)
Expand Down
10 changes: 6 additions & 4 deletions doomsday/engine/portable/src/material.c
Expand Up @@ -163,12 +163,14 @@ boolean Material_HasGlow(material_t* mat)
{
assert(mat);
{
material_snapshot_t ms;
/// \fixme We should not need to prepare to determine this.
Materials_Prepare(&ms, mat,
materialvariant_t* variant;
material_snapshot_t* ms;
variant = Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_MAPSURFACE, 0, 0, 0, 0,
GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), true);
return (ms.glowing > .0001f);
GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), true, true);
ms = MaterialVariant_Snapshot(variant);
return (ms->glowing > .0001f);
}
}

Expand Down
34 changes: 34 additions & 0 deletions doomsday/engine/portable/src/materialvariant.c
Expand Up @@ -46,6 +46,7 @@ materialvariant_t* MaterialVariant_New(material_t* generalCase,
mat->_spec = spec;
mat->_current = mat->_next = mat;
mat->_inter = 0;
mat->_snapshot = NULL;

// Initialize layers.
{ int i;
Expand All @@ -65,6 +66,8 @@ materialvariant_t* MaterialVariant_New(material_t* generalCase,
void MaterialVariant_Delete(materialvariant_t* mat)
{
assert(mat);
if(mat->_snapshot)
free(mat->_snapshot), mat->_snapshot = NULL;
free(mat);
}

Expand Down Expand Up @@ -184,6 +187,37 @@ const materialvariant_layer_t* MaterialVariant_Layer(materialvariant_t* mat, int
return NULL;
}

material_snapshot_t* MaterialVariant_AttachSnapshot(materialvariant_t* mat, material_snapshot_t* ms)
{
assert(mat && ms);
if(mat->_snapshot)
{
#if _DEBUG
Con_Message("Warning:MaterialVariant::AttachSnapshot: A snapshot is already attached to %p, "
"it will be replaced.\n", (void*) mat);
#endif
free(mat->_snapshot);
}
mat->_snapshot = ms;
return ms;
}

material_snapshot_t* MateriVariant_DetachSnapshot(materialvariant_t* mat)
{
assert(mat);
{
material_snapshot_t* ms = mat->_snapshot;
mat->_snapshot = NULL;
return ms;
}
}

material_snapshot_t* MaterialVariant_Snapshot(const materialvariant_t* mat)
{
assert(mat);
return mat->_snapshot;
}

materialvariant_t* MaterialVariant_TranslationNext(materialvariant_t* mat)
{
assert(mat);
Expand Down
55 changes: 38 additions & 17 deletions doomsday/engine/portable/src/p_materialmanager.c
Expand Up @@ -708,7 +708,7 @@ void Materials_ProcessCacheQueue(void)
while(variantCacheQueue)
{
variantcachequeue_node_t* next = variantCacheQueue->next;
Materials_Prepare(NULL, variantCacheQueue->mat, variantCacheQueue->spec, true);
Materials_Prepare(variantCacheQueue->mat, variantCacheQueue->spec, true, false);
free(variantCacheQueue);
variantCacheQueue = next;
}
Expand Down Expand Up @@ -1182,26 +1182,37 @@ static void setTexUnit(material_snapshot_t* ss, byte unit, const texturevariant_
}
}

void Materials_InitSnapshot(material_snapshot_t* ss)
void Materials_InitSnapshot(material_snapshot_t* ms)
{
assert(ss);
assert(ms);

memset(ms, 0, sizeof(material_snapshot_t));
ms->width = ms->height = 0;

{ int i;
for(i = 0; i < MATERIALVARIANT_MAXLAYERS; ++i)
setTexUnit(ss, i, NULL, BM_NORMAL, GL_LINEAR, 1, 1, 0, 0, 0);
}
V3_Set(ss->topColor, 1, 1, 1);
V3_Set(ss->color, 1, 1, 1);
V3_Set(ss->colorAmplified, 1, 1, 1);
{
setTexUnit(ms, i, NULL, BM_NORMAL, GL_LINEAR, 1, 1, 0, 0, 0);
}}

V3_Set(ms->topColor, 1, 1, 1);
V3_Set(ms->color, 1, 1, 1);
V3_Set(ms->colorAmplified, 1, 1, 1);
V3_Set(ms->shinyMinColor, 0, 0, 0);

ms->glowing = 0;
ms->isOpaque = true;
}

materialvariant_t* Materials_Prepare(material_snapshot_t* snapshot, material_t* mat,
materialvariantspecification_t* spec, boolean smoothed)
materialvariant_t* Materials_Prepare(material_t* mat, materialvariantspecification_t* spec,
boolean smoothed, boolean updateSnapshot)
{
assert(mat && spec);
{
struct materialtextureunit_s {
const texturevariant_t* tex;
} static texUnits[NUM_MATERIAL_TEXTURE_UNITS];
material_snapshot_t* snapshot;
materialvariant_t* variant;

memset(texUnits, 0, sizeof(texUnits));
Expand Down Expand Up @@ -1310,8 +1321,18 @@ materialvariant_t* Materials_Prepare(material_snapshot_t* snapshot, material_t*
}

// If we aren't taking a snapshot; get out of here.
if(!snapshot) return variant;
if(!updateSnapshot) return variant;

// Acquire the snapshot we will be updating.
snapshot = MaterialVariant_Snapshot(variant);
if(!snapshot)
{
// Time to allocate the snapshot.
snapshot = (material_snapshot_t*)malloc(sizeof *snapshot);
if(!snapshot)
Con_Error("Materials::Prepare: Failed on allocation of %lu bytes for new MaterialSnapshot.", (unsigned long) sizeof *snapshot);
snapshot = MaterialVariant_AttachSnapshot(variant, snapshot);
}
Materials_InitSnapshot(snapshot);

if(0 == Material_Width(mat) && 0 == Material_Height(mat))
Expand Down Expand Up @@ -1426,19 +1447,19 @@ const ded_decor_t* Materials_DecorationDef(material_t* mat)
{
if(!mat) return 0;
if(!Material_Prepared(mat))
Materials_Prepare(NULL, mat,
Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_MAPSURFACE,
0, 0, 0, 0, GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), false);
0, 0, 0, 0, GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), false, false);
return MaterialBind_DecorationDef(Materials_PrimaryBind(mat));
}

const ded_ptcgen_t* Materials_PtcGenDef(material_t* mat)
{
if(!mat) return 0;
if(!Material_Prepared(mat))
Materials_Prepare(NULL, mat,
Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_MAPSURFACE,
0, 0, 0, 0, GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), false);
0, 0, 0, 0, GL_REPEAT, GL_REPEAT, -1, -1, -1, true, true, false, false), false, false);
return MaterialBind_PtcGenDef(Materials_PrimaryBind(mat));
}

Expand Down Expand Up @@ -1855,8 +1876,8 @@ static int setVariantTranslationWorker(materialvariant_t* variant, void* paramat
setmaterialtranslationworker_paramaters_t* params =
(setmaterialtranslationworker_paramaters_t*) paramaters;
materialvariantspecification_t* spec = MaterialVariant_Spec(variant);
materialvariant_t* current = Materials_Prepare(NULL, params->current, spec, false);
materialvariant_t* next = Materials_Prepare(NULL, params->next, spec, false);
materialvariant_t* current = Materials_Prepare(params->current, spec, false, false);
materialvariant_t* next = Materials_Prepare(params->next, spec, false, false);

MaterialVariant_SetTranslation(variant, current, next);
return 0; // Continue iteration.
Expand Down
4 changes: 2 additions & 2 deletions doomsday/engine/portable/src/pathdirectory.c
Expand Up @@ -1355,10 +1355,10 @@ void PathDirectoryNode_AttachUserData(pathdirectory_node_t* node, void* data)
{
assert(NULL != node);
#if _DEBUG
if(NULL != node->_pair.data)
if(node->_pair.data)
{
Con_Message("Warning:PathDirectoryNode::AttachUserData: Data is already associated "
"with this node, will be replaced.");
"with this node, will be replaced.\n");
}
#endif
node->_pair.data = data;
Expand Down
11 changes: 6 additions & 5 deletions doomsday/engine/portable/src/r_draw.c
Expand Up @@ -246,12 +246,13 @@ void R_DrawViewBorder(void)
mat = Materials_MaterialForUri2(borderGraphicsNames[BG_BACKGROUND], true/*quiet please*/);
if(mat)
{
material_snapshot_t ms;
Materials_Prepare(&ms, mat,
material_snapshot_t* ms;
materialvariant_t* variant = Materials_Prepare(mat,
Materials_VariantSpecificationForContext(MC_UI, 0, 0, 0, 0,
GL_REPEAT, GL_REPEAT, 0, 1, 0, false, false, false, false), true);
GL_BindTexture(MSU(&ms, MTU_PRIMARY).tex.glName, (filterUI ? GL_LINEAR : GL_NEAREST));
GL_DrawCutRectTiled(0, 0, port->dimensions.width, port->dimensions.height, ms.width, ms.height, 0, 0,
GL_REPEAT, GL_REPEAT, 0, 1, 0, false, false, false, false), true, true);
ms = MaterialVariant_Snapshot(variant);
GL_BindTexture(MSU(ms, MTU_PRIMARY).tex.glName, (filterUI ? GL_LINEAR : GL_NEAREST));
GL_DrawCutRectTiled(0, 0, port->dimensions.width, port->dimensions.height, ms->width, ms->height, 0, 0,
vd->window.x - border, vd->window.y - border,
vd->window.width + 2 * border, vd->window.height + 2 * border);
}
Expand Down

0 comments on commit 0b6f5ec

Please sign in to comment.