void scContUnit::Iter( SubstituteFunc func, long startLocation, long& limitOffset ) { UCS2 chBuf[64]; UCS2* chP; CharRecordP startChRec; scSpecRecord* specRec; long startOffset, endOffset, wordLen; LockMem( startChRec, specRec ); startOffset = startLocation; endOffset = startOffset; for ( ; endOffset < limitOffset; ) { startOffset = TXTStartSelectableWord( startChRec, endOffset ); endOffset = TXTEndSelectableWord( startChRec, endOffset ); wordLen = endOffset - startOffset; if ( wordLen > 1 ) { BuildTestWord( chBuf, startChRec + startOffset, wordLen ); status stat = (*func)( &chP, chBuf, NULL ); if ( stat == scSuccess || stat == scUserAbort ) { if ( !ReplaceWord( startChRec, specRec, startOffset, endOffset, limitOffset, chBuf, chP ) ) { UnlockMem( ); return; } fCharArray.RepairText( fSpecRun, startOffset, endOffset ); Mark( scREBREAK ); if ( stat == scUserAbort ) goto exit; } } endOffset = FindNextSpellingWord( startChRec, endOffset, limitOffset ); } exit: UnlockMem( ); }
void GarbageCollector::PerformGC(RunTimeStack &s) { // Perform mark-and-sweep garbage collection. We // follow every pointer in every activation record // in the RunTimeStack, marking all Objects found. // Before marking an Object, we make sure it is not // already marked, so we don't enter an infinite loop. // Then we sweep once through the ObjectList. For // each Object in the ObjectList, if it is not marked, // we remove it from the list and delete it; otherwise, // we unmark it so it is ready for the next round of // mark-and-sweep. Mark(s); Sweep(s); }
ColorMenu::ColorMenu (const char *name, BView *_view, int h, int v, float s) : BMenu (name, h*s, v*s) { index = 0; for (int i = 0; i < v; i++) for (int j = 0; j < h; j++) { BRect cframe = BRect (j*s, i*s, (j + 1)*s, (i + 1)*s); AddItem (new ColorItem (system_colors()->color_list[index]), cframe); } Mark (0); view = _view; hs = h*s; vs = v*s; parent = NULL; fWindow = NULL; }
//***************************************************************************** // cascading Mark of a CustomAttribute //***************************************************************************** HRESULT FilterManager::MarkCustomAttribute(mdCustomAttribute cv) { HRESULT hr = NOERROR; CustomAttributeRec *pRec; // We know that the filter table is not null here. Tell PREFIX that we know it. PREFIX_ASSUME(m_pMiniMd->GetFilterTable() != NULL); IfFailGo( m_pMiniMd->GetFilterTable()->MarkCustomAttribute( cv ) ); // Mark the type (and any family) of the CustomAttribue. IfFailGo(m_pMiniMd->GetCustomAttributeRecord(RidFromToken(cv), &pRec)); IfFailGo( Mark(m_pMiniMd->getTypeOfCustomAttribute(pRec)) ); ErrExit: return hr; } // HRESULT FilterManager::MarkCustomAttribute()
void assignAttVar(Word av, Word value, int flags ARG_LD) { Word a; mark m; assert(isAttVar(*av)); assert(!isRef(*value)); assert(gTop+8 <= gMax && tTop+6 <= tMax); DEBUG(CHK_SECURE, assert(on_attvar_chain(av))); DEBUG(1, Sdprintf("assignAttVar(%s)\n", vName(av))); if ( isAttVar(*value) ) { if ( value > av ) { Word tmp = av; av = value; value = tmp; } else if ( av == value ) return; } if( !(flags & ATT_ASSIGNONLY) ) { a = valPAttVar(*av); registerWakeup(av, a, value PASS_LD); } if ( (flags&ATT_WAKEBINDS) ) return; Mark(m); /* must be trailed, even if above last choice */ LD->mark_bar = NO_MARK_BAR; TrailAssignment(av); DiscardMark(m); if ( isAttVar(*value) ) { DEBUG(1, Sdprintf("Unifying two attvars\n")); *av = makeRef(value); } else if ( isVar(*value) ) { DEBUG(1, Sdprintf("Assigning attvar with plain var\n")); *av = makeRef(value); /* JW: Does this happen? */ } else *av = *value; return; }
int CGUIListItem::MouseLeft(float x, float y, UINT mouseState, UINT keyState) { // kliknuti levym tlacitkem (mouseState 0 = pusteni, 1 = stisknuti cudlitka) if(mouseState) { if(listBox->markListItem==this) { OnClick(); EventArise(EClicked); } else { Mark(); } } return 0; }
void Registry::GarbageCollect() { // unmark all objects MarkAll(false); // mark everything that is reachable from the root Mark(root, true); // everything that is not now marked is not reachable and can be deleted deathrow.clear(); foreach (Instances::value_type const &val, instances) { StorageBase const *base = val.second; if (!base->IsMarked()) { //OM_TRACE_1(4, base->GetHandle().value) << " adding to deathrow"; deathrow.push_back(base->GetHandle()); } }
void CProductCheckListBoxItem::UpdateProductItem(void) { if (Mark()) { m_pItem->SetFlag(PRODUCT_ITEM_Marked); } else { m_pItem->ClearFlag(PRODUCT_ITEM_Marked); } if (Select()) { m_pItem->SetFlag(PRODUCT_ITEM_Selected); } else { m_pItem->ClearFlag(PRODUCT_ITEM_Selected); } }
/* ==================================================================== */ void scTextline::MarkForDeletion( void ) { scXRect xrect = QueryExtents( xrect, 1 ); if ( fPara && fPara->GetFirstline() == this ) fPara->SetFirstline( 0 ); // de-normalize extents if ( fColumn->GetFlowdir().IsVertical() ) xrect.Translate( fVJOffset, 0 ); else xrect.Translate( 0, -fVJOffset ); fInkExtents = xrect; fPara = 0; fLineCount = -1; fStartOffset = -1; fEndOffset = -1; Mark( scINVALID ); }
static void find_levels_r(struct block *b) { int level; if (isMarked(b)) return; Mark(b); b->link = 0; if (JT(b)) { find_levels_r(JT(b)); find_levels_r(JF(b)); level = MAX(JT(b)->level, JF(b)->level) + 1; } else level = 0; b->level = level; b->link = levels[level]; levels[level] = b; }
//***************************************************************************** // cascading Mark of all GenericPar associated with a TypeDef or MethodDef token //***************************************************************************** HRESULT FilterManager::MarkGenericParamWithParentToken( mdToken tk) { HRESULT hr = NOERROR; RID ulStart, ulEnd; RID index; GenericParamRec *pGenericParamRec; mdToken constraint; HENUMInternal hEnum; // To enumerate constraints. // Enumerate the GenericPar //@todo: Handle the unsorted case. IfFailGo( m_pMiniMd->GetGenericParamsForToken(tk, &ulStart, &ulEnd) ); for (; ulStart < ulEnd; ++ulStart) { index = m_pMiniMd->GetGenericParamRid(ulStart); IfFailGo(m_pMiniMd->GetGenericParamRecord(index, &pGenericParamRec)); RID ridConstraint; IfFailGo( m_pMiniMd->FindGenericParamConstraintHelper(TokenFromRid(ulStart, mdtGenericParam), &hEnum) ); while (HENUMInternal::EnumNext(&hEnum, (mdToken *) &ridConstraint)) { // Get the constraint. GenericParamConstraintRec *pRec; IfFailGo(m_pMiniMd->GetGenericParamConstraintRecord(RidFromToken(ridConstraint), &pRec)); constraint = m_pMiniMd->getConstraintOfGenericParamConstraint(pRec); // Mark it. IfFailGo( Mark(constraint) ); } HENUMInternal::ClearEnum(&hEnum); } ErrExit: HENUMInternal::ClearEnum(&hEnum); return hr; } // HRESULT FilterManager::MarkGenericParamWithParentToken()
//***************************************************************************** // cascading Mark of an TypeDef token //***************************************************************************** HRESULT FilterManager::MarkInterfaceImpls( mdTypeDef td) { HRESULT hr = NOERROR; ULONG ridStart, ridEnd; ULONG i; InterfaceImplRec *pRec; // We know that the filter table is not null here. Tell PREFIX that we know it. PREFIX_ASSUME(m_pMiniMd->GetFilterTable() != NULL); if ( m_pMiniMd->IsSorted(TBL_InterfaceImpl) ) { IfFailGo(m_pMiniMd->getInterfaceImplsForTypeDef(RidFromToken(td), &ridEnd, &ridStart)); } else { ridStart = 1; ridEnd = m_pMiniMd->getCountInterfaceImpls() + 1; } // Search for the interfaceimpl with the parent of td for (i = ridStart; i < ridEnd; i++) { IfFailGo(m_pMiniMd->GetInterfaceImplRecord(i, &pRec)); if ( td != m_pMiniMd->getClassOfInterfaceImpl(pRec) ) continue; // found an InterfaceImpl associate with td. Mark the interface row and the interfaceimpl type IfFailGo( m_pMiniMd->GetFilterTable()->MarkInterfaceImpl(TokenFromRid(i, mdtInterfaceImpl)) ); IfFailGo( MarkCustomAttributesWithParentToken(TokenFromRid(i, mdtInterfaceImpl)) ); // IfFailGo( MarkDeclSecuritiesWithParentToken(TokenFromRid(i, mdtInterfaceImpl)) ); IfFailGo( Mark(m_pMiniMd->getInterfaceOfInterfaceImpl(pRec)) ); } ErrExit: return hr; } // HRESULT FilterManager::MarkInterfaceImpls()
void scContUnit::ApplyAnnotation( long start, long end, const scAnnotation& annot ) { eChTranType chTranType = eNormalTran; if ( !fRubiArray ) { AllocRubiArray(); } else if ( fRubiArray->IsRubiData( start, end ) ) { int nth; int index; scRubiData rd; fCharArray.Transform( start, end, eRemoveJapTran, end - start ); for ( nth = 1; fRubiArray->GetNthRubi( index, rd, nth, start, end ); ) fRubiArray->RemoveDataAt( index ); } if ( annot.fAnnotate ) { scRubiData rd( annot.fCharStr, start, end, SpecAtOffset( start + 1 ) ); fRubiArray->AddRubiData( rd ); chTranType = eRubiTran; } else { // i should have already removed any annotations if ( fRubiArray->GetNumItems() == 0 ) DeleteRubiArray(); chTranType = eRemoveJapTran; } Mark( scREBREAK ); ForceRepaint( start, end ); fCharArray.Transform( start, end, chTranType, end - start ); }
void StencilComp::Write (ostream& out) { GraphicComp::Write(out); UStencil* stencil = GetStencil(); Bitmap* image, *mask; stencil->GetOriginal(image, mask); WriteBitmap(image, out); Mark(out); if (mask == nil) { out << no_mask; } else if (mask == image) { out << mask_equals_image; } else { out << valid_mask; WriteBitmap(mask, out); } WriteBgFilled(stencil->BgFilled(), out); WriteColor(stencil->GetFgColor(), out); WriteColor(stencil->GetBgColor(), out); WriteTransformer(stencil->GetTransformer(), out); WriteString(_filename, out); }
list<class Mark> Mark::RewriteWithSimpleTokens () { list<Mark> ret; // example : <{1,2},{a,b,c},{x}> -> <{2},{c},{x}> + <{2},{b},{x}> + <{2},{a},{x}> + <{1},{c},{x}> + <{1},{b},{x}> + <{1},{a},{x}> list<pair <int,int> > pos; for (list<vector<Element> >::iterator it = elts.begin() ; it != elts.end() ; it++) { pos.push_back( make_pair(0,it->size()) ); } list< pair<int,int> >::iterator pit; list<vector<Element> >::iterator cit; do { list<vector<Element> > forret; for (pit = pos.begin(),cit = elts.begin() ; pit != pos.end() ;pit++,cit++) { forret.push_back(vector<Element> (1,(*cit)[pit->first])); } ret.push_back ( Mark(dom,forret,mult)); } while (! calcSub::next(pos) ); return ret; }
cSkinDisplayReplay::cProgressBar::cProgressBar(int Width, int Height, int Current, int Total, const cMarks *Marks, tColor ColorSeen, tColor ColorRest, tColor ColorSelected, tColor ColorMark, tColor ColorCurrent) :cBitmap(Width, Height, 2) { total = Total; if (total > 0) { int p = Pos(Current); DrawRectangle(0, 0, p, Height - 1, ColorSeen); DrawRectangle(p + 1, 0, Width - 1, Height - 1, ColorRest); if (Marks) { bool Start = true; for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) { int p1 = Pos(m->position); if (Start) { const cMark *m2 = Marks->Next(m); int p2 = Pos(m2 ? m2->position : total); int h = Height / 3; DrawRectangle(p1, h, p2, Height - h, ColorSelected); } Mark(p1, Start, m->position == Current, ColorMark, ColorCurrent); Start = !Start; } } } }
void scContUnit::CharInsert( long computedOffset, long& offset, scKeyRecord& keyRec, long& tmMove, short& rebreak, Bool textCleared, TypeSpec clearedSpec ) { #if SCDEBUG > 1 { static int doit; if ( doit ) fSpecRun.PrintRun( "scContUnit::CharInsert" ); } #endif #ifdef _RUBI_SUPPORT if ( fRubiArray ) { if ( fRubiArray->IsRubiData( offset + computedOffset ) ) { scRubiData rd; fRubiArray->GetRubiAt( rd, offset + computedOffset ); fCharArray.Transform( rd.fStartOffset, rd.fEndOffset, eRemoveJapTran, 0 ); fRubiArray->DeleteRubiData( offset ); if ( !fRubiArray->GetNumItems() ) DeleteRubiArray(); } } #endif if ( computedOffset >= 0 ) fCharArray.SetNumSlots( fCharArray.GetNumItems() + 1 ); fCharArray.CharInsert( tmMove, fSpecRun, #ifdef _RUBI_SUPPORT fRubiArray, #endif offset, keyRec, textCleared, clearedSpec ); fSpecRun.SetContentSize( GetContentSize() ); #if SCDEBUG > 1 { static int doit; if ( doit ) fSpecRun.PrintRun( "void scContUnit::CharInsert 2" ); } #endif scTextline* txl = FindLine( offset ); if ( txl ) txl->Mark( scREPAINT ); /* force repaint */ Mark( scREBREAK ); rebreak = true; }
void scContUnit::ReadAPPText( stTextImportExport& appText ) { fCharArray.ReadAPPText( fSpecRun, appText ); Mark( scRETABULATE ); }
Bool scContUnit::ClearText( long offset1, long offset2 ) { scTextline* txl; Bool entireParaDeleted = false; offset1 = MAX( MIN( offset1, GetContentSize() ), 0 ); offset2 = MIN( MAX( offset2, 0 ), GetContentSize() ); if ( offset1 == 0 && offset2 == GetContentSize() ) entireParaDeleted = true; if ( entireParaDeleted ) { GetCharArray().RemoveBetweenOffsets( offset1, offset2 ); fSpecRun.SetContentSize( 0 ); #ifdef _RUBI_SUPPORT DeleteRubiArray(); #endif } else { GetCharArray().RemoveBetweenOffsets( offset1, offset2 ); fSpecRun.Clear( offset1, offset2 ); GetCharArray().RepairText( fSpecRun, offset1, offset1 ); #ifdef _RUBI_SUPPORT if ( GetRubiArray() ) { GetRubiArray()->DeleteRubiData( offset1, offset2 ); if ( !GetRubiArray()->GetNumItems() ) DeleteRubiArray(); } #endif } Mark( scREBREAK ); /* break link to first line if we remove that text, the refernece * to this text will be patched in the reformatting process */ txl = GetFirstline(); if ( txl ) { scColumn* col = txl->GetColumn(); if ( txl && col->GetRecomposition() ) { scTextline* nextTxl; for ( ; txl && txl->GetPara( ) == this; txl = nextTxl ) { nextTxl = txl->GetNextLogical(); if ( offset2 >= txl->GetEndOffset( ) ) { // the delete takes care of patching the para txl->MarkForDeletion( ); } else { long startOffset = MIN( txl->GetStartOffset( ) - offset2, GetContentSize() ); long endOffset = MIN( txl->GetEndOffset( ) - offset2, GetContentSize() ); txl->SetOffsets( startOffset, endOffset ); } } } } return entireParaDeleted; }
/** * If the Bsp's point and vector tables are nearly full, reorder them and delete unused ones. */ void FBSPOps::bspRefresh( UModel* Model, bool NoRemapSurfs ) { FMemMark Mark(FMemStack::Get()); int32 *VectorRef, *PointRef, *NodeRef, *PolyRef, i; TArray<int32*> VertexRef; uint8 B; // Remove unreferenced Bsp surfs. NodeRef = new(FMemStack::Get(),MEM_Oned,Model->Nodes.Num())int32; PolyRef = new(FMemStack::Get(),MEM_Oned,Model->Surfs.Num())int32; if( Model->Nodes.Num() > 0 ) TagReferencedNodes( Model, NodeRef, PolyRef, 0 ); if( NoRemapSurfs ) FMemory::Memzero(PolyRef,Model->Surfs.Num() * sizeof (int32)); // Remap Bsp nodes and surfs. int32 n=0; for( i=0; i<Model->Surfs.Num(); i++ ) { if( PolyRef[i]!=INDEX_NONE ) { Model->Surfs[n] = Model->Surfs[i]; PolyRef[i]=n++; } } //UE_LOG(LogBSPOps, Log, TEXT("Polys: %i -> %i"), Model->Surfs.Num(), n ); Model->Surfs.RemoveAt( n, Model->Surfs.Num()-n ); n=0; for( i=0; i<Model->Nodes.Num(); i++ ) if( NodeRef[i]!=INDEX_NONE ) { Model->Nodes[n] = Model->Nodes[i]; NodeRef[i]=n++; } //UE_LOG(LogBSPOps, Log, TEXT("Nodes: %i -> %i"), Model->Nodes.Num(), n ); Model->Nodes.RemoveAt( n, Model->Nodes.Num()-n ); // Update Bsp nodes. for( i=0; i<Model->Nodes.Num(); i++ ) { FBspNode *Node = &Model->Nodes[i]; Node->iSurf = PolyRef[Node->iSurf]; if (Node->iFront != INDEX_NONE) Node->iFront = NodeRef[Node->iFront]; if (Node->iBack != INDEX_NONE) Node->iBack = NodeRef[Node->iBack]; if (Node->iPlane != INDEX_NONE) Node->iPlane = NodeRef[Node->iPlane]; } // Remove unreferenced points and vectors. VectorRef = new(FMemStack::Get(),MEM_Oned,Model->Vectors.Num())int32; PointRef = new(FMemStack::Get(),MEM_Oned,Model->Points .Num ())int32; // Check Bsp surfs. for( i=0; i<Model->Surfs.Num(); i++ ) { FBspSurf *Surf = &Model->Surfs[i]; VectorRef [Surf->vNormal ] = 0; VectorRef [Surf->vTextureU ] = 0; VectorRef [Surf->vTextureV ] = 0; PointRef [Surf->pBase ] = 0; } // Check Bsp nodes. for( i=0; i<Model->Nodes.Num(); i++ ) { // Tag all points used by nodes. FBspNode* Node = &Model->Nodes[i]; FVert* VertPool = &Model->Verts[Node->iVertPool]; for( B=0; B<Node->NumVertices; B++ ) { PointRef[VertPool->pVertex] = 0; VertPool++; } Node++; } // Remap points. n=0; for( i=0; i<Model->Points.Num(); i++ ) if( PointRef[i]!=INDEX_NONE ) { Model->Points[n] = Model->Points[i]; PointRef[i] = n++; } //UE_LOG(LogBSPOps, Log, TEXT("Points: %i -> %i"), Model->Points.Num(), n ); Model->Points.RemoveAt( n, Model->Points.Num()-n ); check(Model->Points.Num()==n); // Remap vectors. n=0; for (i=0; i<Model->Vectors.Num(); i++) if (VectorRef[i]!=INDEX_NONE) { Model->Vectors[n] = Model->Vectors[i]; VectorRef[i] = n++; } //UE_LOG(LogBSPOps, Log, TEXT("Vectors: %i -> %i"), Model->Vectors.Num(), n ); Model->Vectors.RemoveAt( n, Model->Vectors.Num()-n ); // Update Bsp surfs. for( i=0; i<Model->Surfs.Num(); i++ ) { FBspSurf *Surf = &Model->Surfs[i]; Surf->vNormal = VectorRef [Surf->vNormal ]; Surf->vTextureU = VectorRef [Surf->vTextureU]; Surf->vTextureV = VectorRef [Surf->vTextureV]; Surf->pBase = PointRef [Surf->pBase ]; } // Update Bsp nodes. for( i=0; i<Model->Nodes.Num(); i++ ) { FBspNode* Node = &Model->Nodes[i]; FVert* VertPool = &Model->Verts[Node->iVertPool]; for( B=0; B<Node->NumVertices; B++ ) { VertPool->pVertex = PointRef [VertPool->pVertex]; VertPool++; } Node++; } // Shrink the objects. Model->ShrinkModel(); Mark.Pop(); }
/** Applies Temporal AA to the light shaft source. */ void ApplyTemporalAA( FRHICommandListImmediate& RHICmdList, FViewInfo& View, const TCHAR* HistoryRTName, /** Contains last frame's history, if non-NULL. This will be updated with the new frame's history. */ TRefCountPtr<IPooledRenderTarget>* HistoryState, /** Source mask (for either occlusion or bloom). */ TRefCountPtr<IPooledRenderTarget>& LightShaftsSource, /** Output of Temporal AA for the next step in the pipeline. */ TRefCountPtr<IPooledRenderTarget>& HistoryOutput) { if (View.FinalPostProcessSettings.AntiAliasingMethod == AAM_TemporalAA && HistoryState) { if (*HistoryState && !View.bCameraCut) { FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); // Nodes for input render targets FRenderingCompositePass* LightShaftSetup = Context.Graph.RegisterPass( new(FMemStack::Get()) FRCPassPostProcessInput( LightShaftsSource ) ); FRenderingCompositePass* HistoryInput = Context.Graph.RegisterPass( new(FMemStack::Get()) FRCPassPostProcessInput( *HistoryState ) ); // Temporal AA node FRenderingCompositePass* NodeTemporalAA = Context.Graph.RegisterPass( new(FMemStack::Get()) FRCPassPostProcessLightShaftTemporalAA ); // Setup inputs on Temporal AA node as the shader expects NodeTemporalAA->SetInput( ePId_Input0, LightShaftSetup ); NodeTemporalAA->SetInput( ePId_Input1, FRenderingCompositeOutputRef( HistoryInput ) ); NodeTemporalAA->SetInput( ePId_Input2, FRenderingCompositeOutputRef( HistoryInput ) ); // Reuse a render target from the pool with a consistent name, for vis purposes TRefCountPtr<IPooledRenderTarget> NewHistory; AllocateOrReuseLightShaftRenderTarget(RHICmdList, NewHistory, HistoryRTName); // Setup the output to write to the new history render target Context.FinalOutput = FRenderingCompositeOutputRef(NodeTemporalAA); Context.FinalOutput.GetOutput()->RenderTargetDesc = NewHistory->GetDesc(); Context.FinalOutput.GetOutput()->PooledRenderTarget = NewHistory; // Execute Temporal AA CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("LightShaftTemporalAA")); // Update the view state's render target reference with the new history *HistoryState = NewHistory; HistoryOutput = NewHistory; } else { // Use the current frame's mask for next frame's history, without invoking the Temporal AA shader *HistoryState = LightShaftsSource; HistoryOutput = LightShaftsSource; LightShaftsSource = NULL; AllocateOrReuseLightShaftRenderTarget(RHICmdList, LightShaftsSource, HistoryRTName); } } else { // Temporal AA is disabled or there is no view state - pass through HistoryOutput = LightShaftsSource; } }
// // Pick a splitter poly then split a pool of polygons into front and back polygons and // recurse. // // iParent = Parent Bsp node, or INDEX_NONE if this is the root node. // IsFront = 1 if this is the front node of iParent, 0 of back (undefined if iParent==INDEX_NONE) // void FBSPOps::SplitPolyList ( UModel *Model, int32 iParent, ENodePlace NodePlace, int32 NumPolys, FPoly **PolyList, EBspOptimization Opt, int32 Balance, int32 PortalBias, int32 RebuildSimplePolys ) { FMemMark Mark(FMemStack::Get()); // Keeping track of allocated FPoly structures to delete later on. TArray<FPoly*> AllocatedFPolys; // To account for big EdPolys split up. int32 NumPolysToAlloc = NumPolys + 8 + NumPolys/4; int32 NumFront=0; FPoly **FrontList = new(FMemStack::Get(),NumPolysToAlloc)FPoly*; int32 NumBack =0; FPoly **BackList = new(FMemStack::Get(),NumPolysToAlloc)FPoly*; FPoly *SplitPoly = FindBestSplit( NumPolys, PolyList, Opt, Balance, PortalBias ); // Add the splitter poly to the Bsp with either a new BspSurf or an existing one. if( RebuildSimplePolys ) { SplitPoly->iLink = Model->Surfs.Num(); } int32 iOurNode = bspAddNode(Model,iParent,NodePlace,0,SplitPoly); int32 iPlaneNode = iOurNode; // Now divide all polygons in the pool into (A) polygons that are // in front of Poly, and (B) polygons that are in back of Poly. // Coplanar polys are inserted immediately, before recursing. // If any polygons are split by Poly, we ignrore the original poly, // split it into two polys, and add two new polys to the pool. FPoly *FrontEdPoly = new FPoly; FPoly *BackEdPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontEdPoly ); AllocatedFPolys.Add( BackEdPoly ); for( int32 i=0; i<NumPolys; i++ ) { FPoly *EdPoly = PolyList[i]; if( EdPoly == SplitPoly ) { continue; } switch( EdPoly->SplitWithPlane( SplitPoly->Vertices[0], SplitPoly->Normal, FrontEdPoly, BackEdPoly, 0 ) ) { case SP_Coplanar: if( RebuildSimplePolys ) { EdPoly->iLink = Model->Surfs.Num()-1; } iPlaneNode = bspAddNode( Model, iPlaneNode, NODE_Plane, 0, EdPoly ); break; case SP_Front: FrontList[NumFront++] = PolyList[i]; break; case SP_Back: BackList[NumBack++] = PolyList[i]; break; case SP_Split: // Create front & back nodes. FrontList[NumFront++] = FrontEdPoly; BackList [NumBack ++] = BackEdPoly; FrontEdPoly = new FPoly; BackEdPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontEdPoly ); AllocatedFPolys.Add( BackEdPoly ); break; } } // Recursively split the front and back pools. if( NumFront > 0 ) SplitPolyList( Model, iOurNode, NODE_Front, NumFront, FrontList, Opt, Balance, PortalBias, RebuildSimplePolys ); if( NumBack > 0 ) SplitPolyList( Model, iOurNode, NODE_Back, NumBack, BackList, Opt, Balance, PortalBias, RebuildSimplePolys ); // Delete FPolys allocated above. We cannot use FMemStack::Get() for FPoly as the array data FPoly contains will be allocated in regular memory. for( int32 i=0; i<AllocatedFPolys.Num(); i++ ) { FPoly* AllocatedFPoly = AllocatedFPolys[i]; delete AllocatedFPoly; } Mark.Pop(); }
/** * Builds Bsp from the editor polygon set (EdPolys) of a model. * * Opt = Bsp optimization, BSP_Lame (fast), BSP_Good (medium), BSP_Optimal (slow) * Balance = 0-100, 0=only worry about minimizing splits, 100=only balance tree. */ void FBSPOps::bspBuild( UModel* Model, enum EBspOptimization Opt, int32 Balance, int32 PortalBias, int32 RebuildSimplePolys, int32 iNode ) { int32 OriginalPolys = Model->Polys->Element.Num(); // Empty the model's tables. if( RebuildSimplePolys==1 ) { // Empty everything but polys. Model->EmptyModel( 1, 0 ); } else if( RebuildSimplePolys==0 ) { // Empty node vertices. for( int32 i=0; i<Model->Nodes.Num(); i++ ) Model->Nodes[i].NumVertices = 0; // Refresh the Bsp. bspRefresh(Model,1); // Empty nodes. Model->EmptyModel( 0, 0 ); } if( Model->Polys->Element.Num() ) { // Allocate polygon pool. FMemMark Mark(FMemStack::Get()); FPoly** PolyList = new( FMemStack::Get(), Model->Polys->Element.Num() )FPoly*; // Add all FPolys to active list. for( int32 i=0; i<Model->Polys->Element.Num(); i++ ) if( Model->Polys->Element[i].Vertices.Num() ) PolyList[i] = &Model->Polys->Element[i]; // Now split the entire Bsp by splitting the list of all polygons. SplitPolyList ( Model, INDEX_NONE, NODE_Root, Model->Polys->Element.Num(), PolyList, Opt, Balance, PortalBias, RebuildSimplePolys ); // Now build the bounding boxes for all nodes. if( RebuildSimplePolys==0 ) { // Remove unreferenced things. bspRefresh( Model, 1 ); // Rebuild all bounding boxes. bspBuildBounds( Model ); } Mark.Pop(); } // UE_LOG(LogBSPOps, Log, TEXT("bspBuild built %i convex polys into %i nodes"), OriginalPolys, Model->Nodes.Num() ); }
// Add an editor polygon to the Bsp, and also stick a reference to it // in the editor polygon's BspNodes list. If the editor polygon has more sides // than the Bsp will allow, split it up into several sub-polygons. // // Returns: Index to newly-created node of Bsp. If several nodes were created because // of split polys, returns the parent (highest one up in the Bsp). int32 FBSPOps::bspAddNode( UModel* Model, int32 iParent, ENodePlace NodePlace, uint32 NodeFlags, FPoly* EdPoly ) { if( NodePlace == NODE_Plane ) { // Make sure coplanars are added at the end of the coplanar list so that // we don't insert NF_IsNew nodes with non NF_IsNew coplanar children. while( Model->Nodes[iParent].iPlane != INDEX_NONE ) { iParent = Model->Nodes[iParent].iPlane; } } FBspSurf* Surf = NULL; if( EdPoly->iLink == Model->Surfs.Num() ) { int32 NewIndex = Model->Surfs.AddZeroed(); Surf = &Model->Surfs[NewIndex]; // This node has a new polygon being added by bspBrushCSG; must set its properties here. Surf->pBase = bspAddPoint (Model,&EdPoly->Base,1); Surf->vNormal = bspAddVector (Model,&EdPoly->Normal,1); Surf->vTextureU = bspAddVector (Model,&EdPoly->TextureU,0); Surf->vTextureV = bspAddVector (Model,&EdPoly->TextureV,0); Surf->Material = EdPoly->Material; Surf->Actor = NULL; Surf->PolyFlags = EdPoly->PolyFlags & ~PF_NoAddToBSP; Surf->LightMapScale= EdPoly->LightMapScale; // Find the LightmassPrimitiveSettings in the UModel... int32 FoundLightmassIndex = INDEX_NONE; if (Model->LightmassSettings.Find(EdPoly->LightmassSettings, FoundLightmassIndex) == false) { FoundLightmassIndex = Model->LightmassSettings.Add(EdPoly->LightmassSettings); } Surf->iLightmassIndex = FoundLightmassIndex; Surf->Actor = EdPoly->Actor; Surf->iBrushPoly = EdPoly->iBrushPoly; Surf->Plane = FPlane(EdPoly->Vertices[0],EdPoly->Normal); } else { check(EdPoly->iLink!=INDEX_NONE); check(EdPoly->iLink<Model->Surfs.Num()); Surf = &Model->Surfs[EdPoly->iLink]; } // Set NodeFlags. if( Surf->PolyFlags & PF_NotSolid ) NodeFlags |= NF_NotCsg; if( Surf->PolyFlags & (PF_Invisible|PF_Portal) ) NodeFlags |= NF_NotVisBlocking; if( EdPoly->Vertices.Num() > FBspNode::MAX_NODE_VERTICES ) { // Split up into two coplanar sub-polygons (one with MAX_NODE_VERTICES vertices and // one with all the remaining vertices) and recursively add them. // EdPoly1 is just the first MAX_NODE_VERTICES from EdPoly. FMemMark Mark(FMemStack::Get()); FPoly *EdPoly1 = new FPoly; *EdPoly1 = *EdPoly; EdPoly1->Vertices.RemoveAt(FBspNode::MAX_NODE_VERTICES,EdPoly->Vertices.Num() - FBspNode::MAX_NODE_VERTICES); // EdPoly2 is the first vertex from EdPoly, and the last EdPoly->Vertices.Num() - MAX_NODE_VERTICES + 1. FPoly *EdPoly2 = new FPoly; *EdPoly2 = *EdPoly; EdPoly2->Vertices.RemoveAt(1,FBspNode::MAX_NODE_VERTICES - 2); int32 iNode = bspAddNode( Model, iParent, NodePlace, NodeFlags, EdPoly1 ); // Add this poly first. bspAddNode( Model, iNode, NODE_Plane, NodeFlags, EdPoly2 ); // Then add other (may be bigger). delete EdPoly1; delete EdPoly2; Mark.Pop(); return iNode; // Return coplanar "parent" node (not coplanar child) } else { // Add node. if( NodePlace!=NODE_Root ) { Model->Nodes.ModifyItem( iParent ); } int32 iNode = Model->Nodes.AddZeroed(); FBspNode& Node = Model->Nodes[iNode]; // Tell transaction tracking system that parent is about to be modified. FBspNode* Parent=NULL; if( NodePlace!=NODE_Root ) Parent = &Model->Nodes[iParent]; // Set node properties. Node.iSurf = EdPoly->iLink; Node.NodeFlags = NodeFlags; Node.iCollisionBound = INDEX_NONE; Node.Plane = FPlane( EdPoly->Vertices[0], EdPoly->Normal ); Node.iVertPool = Model->Verts.AddUninitialized(EdPoly->Vertices.Num()); Node.iFront = INDEX_NONE; Node.iBack = INDEX_NONE; Node.iPlane = INDEX_NONE; if( NodePlace==NODE_Root ) { Node.iLeaf[0] = INDEX_NONE; Node.iLeaf[1] = INDEX_NONE; Node.iZone[0] = 0; Node.iZone[1] = 0; } else if( NodePlace==NODE_Front || NodePlace==NODE_Back ) { int32 ZoneFront=NodePlace==NODE_Front; Node.iLeaf[0] = Parent->iLeaf[ZoneFront]; Node.iLeaf[1] = Parent->iLeaf[ZoneFront]; Node.iZone[0] = Parent->iZone[ZoneFront]; Node.iZone[1] = Parent->iZone[ZoneFront]; } else { int32 IsFlipped = (Node.Plane|Parent->Plane)<0.0; Node.iLeaf[0] = Parent->iLeaf[IsFlipped ]; Node.iLeaf[1] = Parent->iLeaf[1-IsFlipped]; Node.iZone[0] = Parent->iZone[IsFlipped ]; Node.iZone[1] = Parent->iZone[1-IsFlipped]; } // Link parent to this node. if ( NodePlace==NODE_Front ) Parent->iFront = iNode; else if( NodePlace==NODE_Back ) Parent->iBack = iNode; else if( NodePlace==NODE_Plane ) Parent->iPlane = iNode; // Add all points to point table, merging nearly-overlapping polygon points // with other points in the poly to prevent criscrossing vertices from // being generated. // Must maintain Node->NumVertices on the fly so that bspAddPoint is always // called with the Bsp in a clean state. Node.NumVertices = 0; FVert* VertPool = &Model->Verts[ Node.iVertPool ]; for( uint8 i=0; i<EdPoly->Vertices.Num(); i++ ) { int32 pVertex = bspAddPoint(Model,&EdPoly->Vertices[i],0); if( Node.NumVertices==0 || VertPool[Node.NumVertices-1].pVertex!=pVertex ) { VertPool[Node.NumVertices].iSide = INDEX_NONE; VertPool[Node.NumVertices].pVertex = pVertex; Node.NumVertices++; } } if( Node.NumVertices>=2 && VertPool[0].pVertex==VertPool[Node.NumVertices-1].pVertex ) { Node.NumVertices--; } if( Node.NumVertices < 3 ) { GErrors++; // UE_LOG(LogBSPOps, Warning, TEXT("bspAddNode: Infinitesimal polygon %i (%i)"), Node.NumVertices, EdPoly->Vertices.Num() ); Node.NumVertices = 0; } return iNode; } }
// // Recursively filter a set of polys defining a convex hull down the Bsp, // splitting it into two halves at each node and adding in the appropriate // face polys at splits. // static void FilterBound ( UModel* Model, FBox* ParentBound, int32 iNode, FPoly** PolyList, int32 nPolys, int32 Outside ) { FMemMark Mark(FMemStack::Get()); FBspNode& Node = Model->Nodes [iNode]; FBspSurf& Surf = Model->Surfs [Node.iSurf]; FVector Base = Surf.Plane * Surf.Plane.W; FVector& Normal = Model->Vectors[Surf.vNormal]; FBox Bound(0); Bound.Min.X = Bound.Min.Y = Bound.Min.Z = +WORLD_MAX; Bound.Max.X = Bound.Max.Y = Bound.Max.Z = -WORLD_MAX; // Split bound into front half and back half. FPoly** FrontList = new(FMemStack::Get(),nPolys*2+16)FPoly*; int32 nFront=0; FPoly** BackList = new(FMemStack::Get(),nPolys*2+16)FPoly*; int32 nBack=0; // Keeping track of allocated FPoly structures to delete later on. TArray<FPoly*> AllocatedFPolys; FPoly* FrontPoly = new FPoly; FPoly* BackPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontPoly ); AllocatedFPolys.Add( BackPoly ); for( int32 i=0; i<nPolys; i++ ) { FPoly *Poly = PolyList[i]; switch( Poly->SplitWithPlane( Base, Normal, FrontPoly, BackPoly, 0 ) ) { case SP_Coplanar: // UE_LOG(LogBSPOps, Log, TEXT("FilterBound: Got coplanar") ); FrontList[nFront++] = Poly; BackList[nBack++] = Poly; break; case SP_Front: FrontList[nFront++] = Poly; break; case SP_Back: BackList[nBack++] = Poly; break; case SP_Split: FrontList[nFront++] = FrontPoly; BackList [nBack++] = BackPoly; FrontPoly = new FPoly; BackPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontPoly ); AllocatedFPolys.Add( BackPoly ); break; default: UE_LOG(LogBSPOps, Fatal, TEXT("FZoneFilter::FilterToLeaf: Unknown split code") ); } } if( nFront && nBack ) { // Add partitioner plane to front and back. FPoly InfiniteEdPoly = FBSPOps::BuildInfiniteFPoly( Model, iNode ); InfiniteEdPoly.iBrushPoly = iNode; SplitPartitioner(Model,PolyList,FrontList,BackList,0,nPolys,nFront,nBack,InfiniteEdPoly,AllocatedFPolys); } else { // if( !nFront ) UE_LOG(LogBSPOps, Log, TEXT("FilterBound: Empty fronthull") ); // if( !nBack ) UE_LOG(LogBSPOps, Log, TEXT("FilterBound: Empty backhull") ); } // Recursively update all our childrens' bounding volumes. if( nFront > 0 ) { if( Node.iFront != INDEX_NONE ) FilterBound( Model, &Bound, Node.iFront, FrontList, nFront, Outside || Node.IsCsg() ); else if( Outside || Node.IsCsg() ) UpdateBoundWithPolys( Bound, FrontList, nFront ); else UpdateConvolutionWithPolys( Model, iNode, FrontList, nFront ); } if( nBack > 0 ) { if( Node.iBack != INDEX_NONE) FilterBound( Model, &Bound,Node.iBack, BackList, nBack, Outside && !Node.IsCsg() ); else if( Outside && !Node.IsCsg() ) UpdateBoundWithPolys( Bound, BackList, nBack ); else UpdateConvolutionWithPolys( Model, iNode, BackList, nBack ); } // Update parent bound to enclose this bound. if( ParentBound ) *ParentBound += Bound; // Delete FPolys allocated above. We cannot use FMemStack::Get() for FPoly as the array data FPoly contains will be allocated in regular memory. for( int32 i=0; i<AllocatedFPolys.Num(); i++ ) { FPoly* AllocatedFPoly = AllocatedFPolys[i]; delete AllocatedFPoly; } Mark.Pop(); }
void FCompositionLighting::ProcessAfterLighting(FRHICommandListImmediate& RHICmdList, FViewInfo& View) { check(IsInRenderingThread()); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.ReflectiveShadowMapDiffuse); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.ReflectiveShadowMapNormal); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.ReflectiveShadowMapDepth); { FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); FRenderingCompositeOutputRef AmbientOcclusion; // Screen Space Subsurface Scattering { float Radius = CVarSSSScale.GetValueOnRenderThread(); bool bSimpleDynamicLighting = IsSimpleDynamicLightingEnabled(); bool bScreenSpaceSubsurfacePassNeeded = (View.ShadingModelMaskInView & (1 << MSM_SubsurfaceProfile)) != 0; if (bScreenSpaceSubsurfacePassNeeded && Radius > 0 && !bSimpleDynamicLighting && View.Family->EngineShowFlags.SubsurfaceScattering && //@todo-rco: Remove this when we fix the cross-compiler !IsOpenGLPlatform(View.GetShaderPlatform())) { // can be optimized out if we don't do split screen/stereo rendering (should be done after we some post process refactoring) FRenderingCompositePass* PassExtractSpecular = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessSubsurfaceExtractSpecular()); PassExtractSpecular->SetInput(ePId_Input0, Context.FinalOutput); FRenderingCompositePass* PassSetup = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessSubsurfaceSetup(View)); PassSetup->SetInput(ePId_Input0, Context.FinalOutput); FRenderingCompositePass* Pass0 = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessSubsurface(0)); Pass0->SetInput(ePId_Input0, PassSetup); FRenderingCompositePass* Pass1 = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessSubsurface(1)); Pass1->SetInput(ePId_Input0, Pass0); Pass1->SetInput(ePId_Input1, PassSetup); // full res composite pass, no blurring (Radius=0) FRenderingCompositePass* RecombinePass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessSubsurfaceRecombine()); RecombinePass->SetInput(ePId_Input0, Pass1); RecombinePass->SetInput(ePId_Input1, PassExtractSpecular); SCOPED_DRAW_EVENT(RHICmdList, CompositionLighting_SSSSS); CompositeContext.Process(RecombinePass, TEXT("CompositionLighting_SSSSS")); } } // The graph setup should be finished before this line ---------------------------------------- SCOPED_DRAW_EVENT(RHICmdList, CompositionAfterLighting); // we don't replace the final element with the scenecolor because this is what those passes should do by themself CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("CompositionLighting")); } // We only release the after the last view was processed (SplitScreen) if(View.Family->Views[View.Family->Views.Num() - 1] == &View) { // The RT should be released as early as possible to allow sharing of that memory for other purposes. // This becomes even more important with some limited VRam (XBoxOne). SceneContext.SetLightAttenuation(0); } }
void FCompositionLighting::ProcessAfterBasePass(FRHICommandListImmediate& RHICmdList, FViewInfo& View) { check(IsInRenderingThread()); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); // might get renamed to refracted or ...WithAO SceneContext.GetSceneColor()->SetDebugName(TEXT("SceneColor")); // to be able to observe results with VisualizeTexture GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GetSceneColor()); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferC); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferD); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferE); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferVelocity); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.ScreenSpaceAO); // so that the passes can register themselves to the graph { FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); // Add the passes we want to add to the graph ---------- if(Context.View.Family->EngineShowFlags.Decals && !Context.View.Family->EngineShowFlags.ShaderComplexity) { // DRS_AfterBasePass is for Volumetric decals which don't support ShaderComplexity yet FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDeferredDecals(DRS_AfterBasePass)); Pass->SetInput(ePId_Input0, Context.FinalOutput); Context.FinalOutput = FRenderingCompositeOutputRef(Pass); } // decals are before AmbientOcclusion so the decal can output a normal that AO is affected by if( Context.View.Family->EngineShowFlags.Decals && !Context.View.Family->EngineShowFlags.VisualizeLightCulling) // decal are distracting when looking at LightCulling { FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDeferredDecals(DRS_BeforeLighting)); Pass->SetInput(ePId_Input0, Context.FinalOutput); Context.FinalOutput = FRenderingCompositeOutputRef(Pass); } FRenderingCompositeOutputRef AmbientOcclusion; if(uint32 Levels = ComputeAmbientOcclusionPassCount(Context)) { AmbientOcclusion = AddPostProcessingAmbientOcclusion(RHICmdList, Context, Levels); } if(IsAmbientCubemapPassRequired(Context)) { AddPostProcessingAmbientCubemap(Context, AmbientOcclusion); } // The graph setup should be finished before this line ---------------------------------------- SCOPED_DRAW_EVENT(RHICmdList, LightCompositionTasks_PreLighting); TRefCountPtr<IPooledRenderTarget>& SceneColor = SceneContext.GetSceneColor(); Context.FinalOutput.GetOutput()->RenderTargetDesc = SceneColor->GetDesc(); Context.FinalOutput.GetOutput()->PooledRenderTarget = SceneColor; CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("CompositionLighting_AfterBasePass")); } }
int FWindowsPlatformStackWalkExt::GetCallstacks() { const int32 MAX_NAME_LENGHT = FProgramCounterSymbolInfo::MAX_NAME_LENGHT; int32 NumValidFunctionNames = 0; FCrashExceptionInfo& Exception = CrashInfo.Exception; FMemMark Mark(FMemStack::Get()); //const float int int32 FString const int32 ContextSize = 4096; byte* Context = new(FMemStack::Get()) byte[ContextSize]; ULONG DebugEvent = 0; ULONG ProcessID = 0; ULONG ThreadID = 0; ULONG ContextUsed = 0; // Get the context of the crashed thread HRESULT hr = Control->GetStoredEventInformation(&DebugEvent, &ProcessID, &ThreadID, Context, ContextSize, &ContextUsed, NULL, 0, 0); if( FAILED(hr) ) { return NumValidFunctionNames; } // Some magic number checks if( ContextUsed == 716 ) { UE_LOG( LogCrashDebugHelper, Log, TEXT( "Context size matches x86 sizeof( CONTEXT )" ) ); } else if( ContextUsed == 1232 ) { UE_LOG( LogCrashDebugHelper, Log, TEXT( "Context size matches x64 sizeof( CONTEXT )" ) ); } // Get the entire stack trace const uint32 MaxFrames = 8192; const uint32 MaxFramesSize = MaxFrames * ContextUsed; DEBUG_STACK_FRAME* StackFrames = new(FMemStack::Get()) DEBUG_STACK_FRAME[MaxFrames]; ULONG Count = 0; bool bFoundSourceFile = false; void* ContextData = FMemStack::Get().PushBytes( MaxFramesSize, 0 ); FMemory::Memzero( ContextData, MaxFramesSize ); HRESULT HR = Control->GetContextStackTrace( Context, ContextUsed, StackFrames, MaxFrames, ContextData, MaxFramesSize, ContextUsed, &Count ); int32 AssertOrEnsureIndex = -1; for( uint32 StackIndex = 0; StackIndex < Count; StackIndex++ ) { const uint64 Offset = StackFrames[StackIndex].InstructionOffset; if( IsOffsetWithinModules( Offset ) ) { // Get the module, function, and offset uint64 Displacement = 0; TCHAR NameByOffset[MAX_PATH] = {0}; Symbol->GetNameByOffsetWide( Offset, NameByOffset, ARRAYSIZE( NameByOffset ) - 1, NULL, &Displacement ); FString ModuleAndFunction = NameByOffset; // Don't care about any more entries higher than this if (ModuleAndFunction.Contains( TEXT( "tmainCRTStartup" ) ) || ModuleAndFunction.Contains( TEXT( "FRunnableThreadWin::GuardedRun" ) )) { break; } // Look for source file name and line number TCHAR SourceName[MAX_PATH] = { 0 }; ULONG LineNumber = 0; Symbol->GetLineByOffsetWide( Offset, &LineNumber, SourceName, ARRAYSIZE( SourceName ) - 1, NULL, NULL ); // Remember the top of the stack to locate in the source file if( !bFoundSourceFile && FCString::Strlen( SourceName ) > 0 && LineNumber > 0 ) { CrashInfo.SourceFile = ExtractRelativePath( TEXT( "source" ), SourceName ); CrashInfo.SourceLineNumber = LineNumber; bFoundSourceFile = true; } FString ModuleName; FString FunctionName; // According to MSDN, the symbol name will include an ! if the function name could be discovered, delimiting it from the module name // https://msdn.microsoft.com/en-us/library/windows/hardware/ff547186(v=vs.85).aspx if( ModuleAndFunction.Contains( TEXT( "!" ) ) ) { NumValidFunctionNames++; ModuleAndFunction.Split( TEXT( "!" ), &ModuleName, &FunctionName ); FunctionName += TEXT( "()" ); } else { ModuleName = ModuleAndFunction; } // #YRX_Crash: 2015-07-24 Add for other platforms // If we find an assert, the actual source file we're interested in is the next one up, so reset the source file found flag if( FunctionName.Len() > 0 ) { if( FunctionName.Contains( TEXT( "FDebug::" ), ESearchCase::CaseSensitive ) || FunctionName.Contains( TEXT( "NewReportEnsure" ), ESearchCase::CaseSensitive ) ) { bFoundSourceFile = false; AssertOrEnsureIndex = FMath::Max( AssertOrEnsureIndex, (int32)StackIndex ); } } // FString InModuleName, FString InFunctionName, FString InFilename, uint32 InLineNumber, uint64 InSymbolDisplacement, uint64 InOffsetInModule, uint64 InProgramCounter FProgramCounterSymbolInfoEx SymbolInfo( ModuleName, FunctionName, SourceName, LineNumber, Displacement, Offset, 0 ); FString GenericFormattedCallstackLine; FGenericPlatformStackWalk::SymbolInfoToHumanReadableStringEx( SymbolInfo, GenericFormattedCallstackLine ); Exception.CallStackString.Add( GenericFormattedCallstackLine ); UE_LOG( LogCrashDebugHelper, Log, TEXT( "%3u: %s" ), StackIndex, *GenericFormattedCallstackLine ); } } // Remove callstack entries below FDebug, we don't need them. if (AssertOrEnsureIndex > 0) { Exception.CallStackString.RemoveAt( 0, AssertOrEnsureIndex ); UE_LOG( LogCrashDebugHelper, Warning, TEXT( "Callstack trimmed to %i entries" ), Exception.CallStackString.Num() ); } UE_LOG( LogCrashDebugHelper, Warning, TEXT( "Callstack generated with %i valid function names" ), NumValidFunctionNames ); return NumValidFunctionNames; }
FUniformBufferRHIRef FUniformExpressionSet::CreateUniformBuffer(const FMaterialRenderContext& MaterialRenderContext, FRHICommandList* CommandListIfLocalMode, struct FLocalUniformBuffer* OutLocalUniformBuffer) const { check(UniformBufferStruct); check(IsInParallelRenderingThread()); FUniformBufferRHIRef UniformBuffer; if (UniformBufferStruct->GetSize() > 0) { FMemMark Mark(FMemStack::Get()); void* const TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct->GetSize(),UNIFORM_BUFFER_STRUCT_ALIGNMENT); FLinearColor* TempVectorBuffer = (FLinearColor*)TempBuffer; for(int32 VectorIndex = 0;VectorIndex < UniformVectorExpressions.Num();++VectorIndex) { TempVectorBuffer[VectorIndex] = FLinearColor(0,0,0,0); UniformVectorExpressions[VectorIndex]->GetNumberValue(MaterialRenderContext,TempVectorBuffer[VectorIndex]); } float* TempScalarBuffer = (float*)(TempVectorBuffer + UniformVectorExpressions.Num()); for(int32 ScalarIndex = 0;ScalarIndex < UniformScalarExpressions.Num();++ScalarIndex) { FLinearColor VectorValue(0,0,0,0); UniformScalarExpressions[ScalarIndex]->GetNumberValue(MaterialRenderContext,VectorValue); TempScalarBuffer[ScalarIndex] = VectorValue.R; } void** ResourceTable = (void**)((uint8*)TempBuffer + UniformBufferStruct->GetLayout().ResourceOffset); check(((UPTRINT)ResourceTable & 0x7) == 0); check(UniformBufferStruct->GetLayout().Resources.Num() == Uniform2DTextureExpressions.Num() * 2 + UniformCubeTextureExpressions.Num() * 2 + 2); // Cache 2D texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < Uniform2DTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; Uniform2DTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if (Value && Value->Resource) { //@todo-rco: Help track down a invalid values checkf(Value->IsA(UTexture::StaticClass()), TEXT("Expecting a UTexture! Value='%s' class='%s'"), *Value->GetName(), *Value->GetClass()->GetName()); // UMaterial / UMaterialInstance should have caused all dependent textures to be PostLoaded, which initializes their rendering resource checkf(Value->TextureReference.TextureReferenceRHI, TEXT("Texture %s of class %s had invalid texture reference"), *Value->GetName(), *Value->GetClass()->GetName()); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } // Cache cube texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < UniformCubeTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; UniformCubeTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if(Value && Value->Resource) { check(Value->TextureReference.TextureReferenceRHI); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } *ResourceTable++ = Wrap_WorldGroupSettings->SamplerStateRHI; *ResourceTable++ = Clamp_WorldGroupSettings->SamplerStateRHI; if (CommandListIfLocalMode) { check(OutLocalUniformBuffer); *OutLocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct->GetSize(), UniformBufferStruct->GetLayout()); check(OutLocalUniformBuffer->IsValid()); } else { UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct->GetLayout(), UniformBuffer_MultiFrame); check(!OutLocalUniformBuffer->IsValid()); } } return UniformBuffer; }
void FObjectReplicator::PostReceivedBunch() { // Call PostNetReceive const bool bIsServer = (OwningChannel->Connection->Driver->ServerConnection == NULL); if (!bIsServer && bHasReplicatedProperties) { PostNetReceive(); bHasReplicatedProperties = false; } // Check if PostNetReceive() destroyed Object UObject *Object = GetObject(); if (Object == NULL || Object->IsPendingKill()) { return; } RepLayout->CallRepNotifies( RepState, Object ); // Call RepNotifies if ( RepNotifies.Num() > 0 ) { for (int32 RepNotifyIdx = 0; RepNotifyIdx < RepNotifies.Num(); RepNotifyIdx++) { //UE_LOG(LogNet, Log, TEXT("Calling Object->%s with %s"), *RepNotifies(RepNotifyIdx)->RepNotifyFunc.ToString(), *RepNotifies(RepNotifyIdx)->GetName()); UProperty* RepProperty = RepNotifies[RepNotifyIdx]; UFunction* RepNotifyFunc = Object->FindFunctionChecked(RepProperty->RepNotifyFunc); if (RepNotifyFunc->NumParms == 0) { Object->ProcessEvent(RepNotifyFunc, NULL); } else if (RepNotifyFunc->NumParms == 1) { Object->ProcessEvent(RepNotifyFunc, RepProperty->ContainerPtrToValuePtr<uint8>(RepState->StaticBuffer.GetTypedData()) ); } else if (RepNotifyFunc->NumParms == 2) { // Fixme: this isn't as safe as it could be. Right now we have two types of parameters: MetaData (a TArray<uint8>) // and the last local value (pointer into the Recent[] array). // // Arrays always expect MetaData. Everything else, including structs, expect last value. // This is enforced with UHT only. If a ::NetSerialize function ever starts producing a MetaData array thats not in UArrayProperty, // we have no static way of catching this and the replication system could pass the wrong thing into ProcessEvent here. // // But this is all sort of an edge case feature anyways, so its not worth tearing things up too much over. FMemMark Mark(FMemStack::Get()); uint8* Parms = new(FMemStack::Get(),MEM_Zeroed,RepNotifyFunc->ParmsSize)uint8; TFieldIterator<UProperty> Itr(RepNotifyFunc); check(Itr); Itr->CopyCompleteValue( Itr->ContainerPtrToValuePtr<void>(Parms), RepProperty->ContainerPtrToValuePtr<uint8>(RepState->StaticBuffer.GetTypedData()) ); ++Itr; check(Itr); TArray<uint8> *NotifyMetaData = RepNotifyMetaData.Find(RepNotifies[RepNotifyIdx]); check(NotifyMetaData); Itr->CopyCompleteValue( Itr->ContainerPtrToValuePtr<void>(Parms), NotifyMetaData ); Object->ProcessEvent(RepNotifyFunc, Parms ); Mark.Pop(); } if (Object == NULL || Object->IsPendingKill()) { // script event destroyed Object break; } } } RepNotifies.Reset(); RepNotifyMetaData.Empty(); }