BVB Source Codes

CRYENGINE Show CCullThread.cpp Source code

Return Download CRYENGINE: download CCullThread.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "CCullThread.h"
  5. #include "ObjMan.h"
  6. #include "CCullRenderer.h"
  7. #include <CryThreading/IJobManager_JobDelegator.h>
  8. SHWOccZBuffer HWZBuffer;
  9.  
  10. DECLARE_JOB("CheckOcclusion", TOcclusionCheckJob, NAsyncCull::CCullThread::CheckOcclusion);
  11. DECLARE_JOB("PrepareOcclusion", TOcclusionPrepareJob, NAsyncCull::CCullThread::PrepareOcclusion);
  12. DECLARE_JOB("PrepareOcclusion_ReprojectZBuffer", TOcclusionPrepareReprojectJob, NAsyncCull::CCullThread::PrepareOcclusion_ReprojectZBuffer);
  13. DECLARE_JOB("PrepareOcclusion_ReprojectZBufferLine", TOcclusionPrepareReprojectLineJob, NAsyncCull::CCullThread::PrepareOcclusion_ReprojectZBufferLine);
  14. DECLARE_JOB("PrepareOcclusion_ReprojectZBufferLineAfterMerge", TOcclusionPrepareReprojectLineJob2, NAsyncCull::CCullThread::PrepareOcclusion_ReprojectZBufferLineAfterMerge);
  15. DECLARE_JOB("PrepareOcclusion_RasterizeZBuffer", TOcclusionPrepareRasterizeJob, NAsyncCull::CCullThread::PrepareOcclusion_RasterizeZBuffer);
  16.  
  17. typedef NAsyncCull::CCullRenderer<CULL_SIZEX, CULL_SIZEY> tdCullRasterizer;
  18.  
  19. volatile static NAsyncCull::tdVertexCache g_VertexCache;
  20. uint8 g_RasterizerBuffer[sizeof(tdCullRasterizer) + 16];
  21. tdCullRasterizer* g_Rasterizer;
  22. #define RASTERIZER (*g_Rasterizer)
  23.  
  24. namespace NAsyncCull
  25. {
  26.  
  27. const NVMath::vec4 MaskNot3 = NVMath::Vec4(~3u, ~0u, ~0u, ~0u);
  28.  
  29. CCullThread::CCullThread()
  30.         : m_Enabled(false)
  31.         , m_Active(false)
  32.         , m_nPrepareState(IDLE)
  33.         , m_nRunningReprojJobs(0)
  34.         , m_nRunningReprojJobsAfterMerge(0)
  35.         , m_bCheckOcclusionRequested(0)
  36.         , m_pCheckOcclusionJob(nullptr)
  37.         , m_ViewDir(ZERO)
  38.         , m_Position(ZERO)
  39.         , m_NearPlane(0.0f)
  40.         , m_FarPlane(0.0f)
  41.         , m_NearestMax(0.0f)
  42.         , m_pOCMBufferAligned(nullptr)
  43.         , m_OCMMeshCount(0)
  44.         , m_OCMInstCount(0)
  45.         , m_OCMOffsetInstances(0)
  46. {
  47.         ZeroArray(m_passInfoForCheckOcclusion);
  48.  
  49.         size_t Buffer = reinterpret_cast<size_t>(g_RasterizerBuffer);
  50.         Buffer += 127;
  51.         Buffer &= ~127;
  52.         g_Rasterizer = new(reinterpret_cast<void*>(Buffer))tdCullRasterizer();
  53. }
  54.  
  55. bool CCullThread::LoadLevel(const char* pFolderName)
  56. {
  57.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Occluder Mesh");
  58.         m_OCMBuffer.resize(0);
  59.         //FILE* pFile   =       gEnv->pCryPak->FOpen("Canyon25.ocm","rbx");
  60.         FILE* pFile = gEnv->pCryPak->FOpen((string(pFolderName) + "/occluder.ocm").c_str(), "rbx");
  61.         if (!pFile)
  62.         {
  63.                 //__debugbreak();
  64.                 return false;
  65.         }
  66.         gEnv->pCryPak->FSeek(pFile, 0, SEEK_END);
  67.         const size_t Size = gEnv->pCryPak->FTell(pFile);
  68.         gEnv->pCryPak->FSeek(pFile, 0L, SEEK_SET);
  69.         m_OCMBuffer.reserve(Size + 144 * 3 + 16);   //48tri*9byte padding for unrolled loop in rasterization without special case (not 144 algined poly count)
  70.                                                     //16 for alignment
  71.         m_OCMBuffer.resize(Size);
  72.         size_t BufferOffset = reinterpret_cast<size_t>(&m_OCMBuffer[0]);
  73.         BufferOffset = (BufferOffset + 15) & ~15;
  74.         m_pOCMBufferAligned = reinterpret_cast<uint8*>(BufferOffset);
  75.  
  76.         gEnv->pCryPak->FRead(m_pOCMBufferAligned, Size, pFile, false);
  77.         gEnv->pCryPak->FClose(pFile);
  78.  
  79.         const uint32 Version = Swap(*reinterpret_cast<uint32*>(&m_pOCMBufferAligned[0]));
  80.         m_OCMMeshCount = *reinterpret_cast<uint32*>(&m_pOCMBufferAligned[4]);
  81.         m_OCMInstCount = *reinterpret_cast<uint32*>(&m_pOCMBufferAligned[8]);
  82.         m_OCMOffsetInstances = *reinterpret_cast<uint32*>(&m_pOCMBufferAligned[12]);
  83.  
  84.         if (Version != ~3u && Version != ~4u)
  85.         {
  86.                 CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_ERROR, "Unsupported occlusion mesh format version. Please reexport the occluder mesh.");
  87.                 stl::free_container(m_OCMBuffer);
  88.                 return false;
  89.         }
  90.  
  91.         if (m_OCMOffsetInstances & 3)
  92.         {
  93.                 CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_ERROR, "The occluder mesh contains invalid data. Please reexport the occluder mesh.");
  94.                 stl::free_container(m_OCMBuffer);
  95.                 return false;
  96.         }
  97.  
  98.         if (Version == ~3u)  //bump to version ~4
  99.         {
  100.                 m_OCMMeshCount = Swap(m_OCMMeshCount);
  101.                 m_OCMInstCount = Swap(m_OCMInstCount);
  102.                 m_OCMOffsetInstances = Swap(m_OCMOffsetInstances);
  103.                 PodArray<uint8> OCMBufferOut(Size * 8, Size * 8);
  104.                 uint8* pOut = &OCMBufferOut[0];
  105.                 *reinterpret_cast<uint32*>(&pOut[0]) = ~4u; //version
  106.                 *reinterpret_cast<uint32*>(&pOut[4]) = m_OCMMeshCount;
  107.                 *reinterpret_cast<uint32*>(&pOut[8]) = m_OCMInstCount;
  108.                 *reinterpret_cast<uint32*>(&pOut[12]) = m_OCMOffsetInstances;//needs to be patched at the end
  109.                 pOut += 16;
  110.                 uint8* pMeshes = &m_pOCMBufferAligned[0]; //actually starts at 16, but MeshOffset is zero based
  111.                 uint8* pInstances = &m_pOCMBufferAligned[m_OCMOffsetInstances];
  112.                 std::map<uint32, uint32> Offsets; //<old Offset, new Offset>
  113.                 for (size_t a = 0; a < m_OCMInstCount; a++)
  114.                 {
  115.                         Matrix44 World(IDENTITY);
  116.                         uint8* pInstance = pInstances + a * (sizeof(int) + 12 * sizeof(float));//meshoffset+worldmatrix43
  117.                         uint32& MeshOffset = *reinterpret_cast<uint32*>(&pInstance[0]);
  118.                         float* pWorldMat = reinterpret_cast<float*>(&pInstance[4]);
  119.                         Swap(MeshOffset);
  120.                         Swap(pWorldMat[0x0]);
  121.                         Swap(pWorldMat[0x1]);
  122.                         Swap(pWorldMat[0x2]);
  123.                         Swap(pWorldMat[0x3]);
  124.                         Swap(pWorldMat[0x4]);
  125.                         Swap(pWorldMat[0x5]);
  126.                         Swap(pWorldMat[0x6]);
  127.                         Swap(pWorldMat[0x7]);
  128.                         Swap(pWorldMat[0x8]);
  129.                         Swap(pWorldMat[0x9]);
  130.                         Swap(pWorldMat[0xA]);
  131.                         Swap(pWorldMat[0xB]);
  132.  
  133.                         if (Offsets.find(MeshOffset) != Offsets.end())//already endian swapped?
  134.                                 continue;
  135.                         Offsets[MeshOffset] = static_cast<uint32>(pOut - &OCMBufferOut[0]);//zero based offset
  136.  
  137.                         uint8* pMesh = pMeshes + MeshOffset;
  138.                         uint16& QuadCount = *reinterpret_cast<uint16*>(pMesh);
  139.                         uint16& TriCount = *reinterpret_cast<uint16*>(pMesh + 2);
  140.                         Swap(QuadCount);
  141.                         Swap(TriCount);
  142.                         *reinterpret_cast<uint32*>(pOut) = TriCount + QuadCount / 4 * 6;
  143.                         pOut += 16;//to keep 16byte alignment
  144.  
  145.                         const size_t Quads16 = (reinterpret_cast<size_t>(pMesh + 4) + 15) & ~15;
  146.                         const size_t Tris16 = (Quads16 + QuadCount * 3 + 15) & ~15;
  147.                         const int8* pQuads = reinterpret_cast<const int8*>(Quads16);
  148.                         const int8* pTris = reinterpret_cast<const int8*>(Tris16);
  149.  
  150.                         for (size_t a = 0, S = QuadCount; a < S; a += 4)
  151.                         {
  152.                                 const float x0 = *pQuads++;
  153.                                 const float y0 = *pQuads++;
  154.                                 const float z0 = *pQuads++;
  155.                                 const float x1 = *pQuads++;
  156.                                 const float y1 = *pQuads++;
  157.                                 const float z1 = *pQuads++;
  158.                                 const float x2 = *pQuads++;
  159.                                 const float y2 = *pQuads++;
  160.                                 const float z2 = *pQuads++;
  161.                                 const float x3 = *pQuads++;
  162.                                 const float y3 = *pQuads++;
  163.                                 const float z3 = *pQuads++;
  164.                                 reinterpret_cast<float*>(pOut)[0x00] = x0;
  165.                                 reinterpret_cast<float*>(pOut)[0x01] = y0;
  166.                                 reinterpret_cast<float*>(pOut)[0x02] = z0;
  167.                                 reinterpret_cast<float*>(pOut)[0x03] = 1.f;
  168.                                 reinterpret_cast<float*>(pOut)[0x04] = x2;
  169.                                 reinterpret_cast<float*>(pOut)[0x05] = y2;
  170.                                 reinterpret_cast<float*>(pOut)[0x06] = z2;
  171.                                 reinterpret_cast<float*>(pOut)[0x07] = 1.f;
  172.                                 reinterpret_cast<float*>(pOut)[0x08] = x3;
  173.                                 reinterpret_cast<float*>(pOut)[0x09] = y3;
  174.                                 reinterpret_cast<float*>(pOut)[0x0a] = z3;
  175.                                 reinterpret_cast<float*>(pOut)[0x0b] = 1.f;
  176.  
  177.                                 reinterpret_cast<float*>(pOut)[0x0c] = x2;
  178.                                 reinterpret_cast<float*>(pOut)[0x0d] = y2;
  179.                                 reinterpret_cast<float*>(pOut)[0x0e] = z2;
  180.                                 reinterpret_cast<float*>(pOut)[0x0f] = 1.f;
  181.                                 reinterpret_cast<float*>(pOut)[0x10] = x0;
  182.                                 reinterpret_cast<float*>(pOut)[0x11] = y0;
  183.                                 reinterpret_cast<float*>(pOut)[0x12] = z0;
  184.                                 reinterpret_cast<float*>(pOut)[0x13] = 1.f;
  185.                                 reinterpret_cast<float*>(pOut)[0x14] = x1;
  186.                                 reinterpret_cast<float*>(pOut)[0x15] = y1;
  187.                                 reinterpret_cast<float*>(pOut)[0x16] = z1;
  188.                                 reinterpret_cast<float*>(pOut)[0x17] = 1.f;
  189.                                 pOut += 0x18 * sizeof(float);
  190.                         }
  191.                         for (size_t a = 0, S = TriCount; a < S; a++)
  192.                         {
  193.                                 const float x = *pTris++;
  194.                                 const float y = *pTris++;
  195.                                 const float z = *pTris++;
  196.                                 reinterpret_cast<float*>(pOut)[0x00] = x;
  197.                                 reinterpret_cast<float*>(pOut)[0x01] = y;
  198.                                 reinterpret_cast<float*>(pOut)[0x02] = z;
  199.                                 reinterpret_cast<float*>(pOut)[0x03] = 1.f;
  200.                                 pOut += 4 * sizeof(float);
  201.                         }
  202.  
  203.                 }
  204.                 m_OCMOffsetInstances = static_cast<uint32>(pOut - &OCMBufferOut[0]);
  205.                 const size_t InstanceSize = m_OCMInstCount * (sizeof(int) + 12 * sizeof(float));
  206.                 memcpy(pOut, pInstances, InstanceSize);
  207.                 for (size_t a = 0; a < m_OCMInstCount; a++)
  208.                 {
  209.                         uint8* pInstance = pOut + a * (sizeof(int) + 12 * sizeof(float));//meshoffset+worldmatrix43
  210.                         uint32& MeshOffset = *reinterpret_cast<uint32*>(&pInstance[0]);
  211.                         MeshOffset = Offsets[MeshOffset];
  212.                 }
  213.                 pOut += InstanceSize;
  214.  
  215.                 m_OCMBuffer.resize(pOut - &OCMBufferOut[0]);
  216.                 size_t BufferOffset = reinterpret_cast<size_t>(&m_OCMBuffer[0]);
  217.                 BufferOffset = (BufferOffset + 15) & ~15;
  218.                 m_pOCMBufferAligned = reinterpret_cast<uint8*>(BufferOffset);
  219.                 memcpy(m_pOCMBufferAligned, &OCMBufferOut[0], m_OCMBuffer.size());
  220.         }
  221.  
  222.         // Integrity check: each mesh data must be aligned to 4 bytes
  223.         uint8* pInstances = &m_pOCMBufferAligned[m_OCMOffsetInstances];
  224.         for (size_t a = 0; a < m_OCMInstCount; a++)
  225.         {
  226.                 uint8* pInstance = pInstances + a * (sizeof(int) + 12 * sizeof(float));//meshoffset+worldmatrix43
  227.                 uint32 MeshOffset = *reinterpret_cast<uint32*>(&pInstance[0]);
  228.                 if (MeshOffset & 3)
  229.                 {
  230.                         CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_ERROR, "The occluder mesh contains invalid data. Please reexport the occluder mesh.");
  231.                         stl::free_container(m_OCMBuffer);
  232.                         return false;
  233.                 }
  234.         }
  235.  
  236.         //OutputMeshList();
  237.  
  238.         return true;
  239. }
  240.  
  241. void CCullThread::UnloadLevel()
  242. {
  243.         stl::free_container(m_OCMBuffer);
  244.         m_pOCMBufferAligned = NULL;
  245.  
  246.         m_OCMMeshCount = 0;
  247.         m_OCMInstCount = 0;
  248.         m_OCMOffsetInstances = 0;
  249.  
  250.         if (m_pCheckOcclusionJob)
  251.                 delete static_cast<TOcclusionCheckJob*>(m_pCheckOcclusionJob);
  252.         m_pCheckOcclusionJob = NULL;
  253. }
  254.  
  255. CCullThread::~CCullThread()
  256. {
  257.         READ_WRITE_BARRIER
  258.         gEnv->pJobManager->WaitForJob(m_JobStatePrepareOcclusionBuffer);
  259.         delete static_cast<TOcclusionCheckJob*>(m_pCheckOcclusionJob);
  260. }
  261.  
  262. void CCullThread::PrepareCullbufferAsync(const CCamera& rCamera)
  263. {
  264.         Matrix44 MatProj;
  265.         Matrix44 MatView;
  266.         Matrix44 MatViewProj;
  267.  
  268. #if !defined(_RELEASE) // debug code to catch double invocations of the prepare occlusion buffer job per frame
  269.         static int _debug = -1;
  270.         if (_debug == -1)
  271.                 _debug = gEnv->pRenderer->GetFrameID(false);
  272.         else if (_debug == gEnv->pRenderer->GetFrameID(false))
  273.                 __debugbreak();
  274.         else
  275.                 _debug = gEnv->pRenderer->GetFrameID(false);
  276. #endif
  277.  
  278.         // sync a possible job from the last frame
  279.         gEnv->pJobManager->WaitForJob(m_JobStatePrepareOcclusionBuffer);
  280.  
  281.         const CCamera& rCam = rCamera;
  282.  
  283.         CCamera tmp_cam = m_pRenderer->GetCamera();
  284.         m_pRenderer->SetCamera(rCam);
  285.         m_pRenderer->GetModelViewMatrix(reinterpret_cast<f32*>(&MatView));
  286.         m_pRenderer->GetProjectionMatrix(reinterpret_cast<f32*>(&MatProj));
  287.         m_pRenderer->SetCamera(tmp_cam);
  288.  
  289.         uint32 nReverseDepthEnabled = 0;
  290.         m_pRenderer->EF_Query(EFQ_ReverseDepthEnabled, nReverseDepthEnabled);
  291.  
  292.         if (nReverseDepthEnabled) // Convert to regular depth again. TODO: make occlusion culler work with reverse depth
  293.         {
  294.                 MatProj.m22 = -MatProj.m22 + MatProj.m23;
  295.                 MatProj.m32 = -MatProj.m32 + MatProj.m33;
  296.         }
  297.  
  298.         m_ViewDir = rCam.GetViewdir();
  299.         MatViewProj = MatView * MatProj;
  300.  
  301.         MatViewProj.Transpose();
  302.  
  303.         const float SCALEX = static_cast<float>(CULL_SIZEX / 2);
  304.         const float SCALEY = static_cast<float>(CULL_SIZEY / 2);
  305.         const Matrix44A MatScreen(SCALEX, 0.f, 0.f, SCALEX,
  306.                                   0.f, -SCALEY, 0.f, SCALEY,
  307.                                   0.f, 0.f, 1.f, 0.f,
  308.                                   0.f, 0.f, 0.f, 1.f);
  309.         m_MatScreenViewProj = MatScreen * MatViewProj;
  310.         m_MatScreenViewProjTransposed = m_MatScreenViewProj.GetTransposed();
  311.         m_NearPlane = rCam.GetNearPlane();
  312.         m_FarPlane = rCam.GetFarPlane();
  313.         m_NearestMax = m_pRenderer->GetNearestRangeMax();
  314.  
  315.         m_Position = rCam.GetPosition();
  316.  
  317.         HWZBuffer.ZBufferSizeX = CULL_SIZEX;
  318.         HWZBuffer.ZBufferSizeY = CULL_SIZEY;
  319.  
  320.         GetObjManager()->BeginCulling();
  321.  
  322.         m_nPrepareState = PREPARE_STARTED;
  323.         m_Enabled = false;
  324.         m_bCheckOcclusionRequested = 0;
  325.  
  326.         RASTERIZER.Prepare();
  327.  
  328.         m_PrepareBufferSync.SetRunning();
  329.  
  330.         TOcclusionPrepareJob job;
  331.         job.SetClassInstance(this);
  332.         job.SetPriorityLevel(JobManager::eHighPriority);
  333.         job.SetBlocking();
  334.         job.Run();
  335. }
  336.  
  337. void CCullThread::CullStart(const SRenderingPassInfo& passInfo)
  338. {
  339.         FUNCTION_PROFILER_3DENGINE;
  340.  
  341.         // signal rasterizer that it should stop
  342.         m_bCheckOcclusionRequested = 1;
  343.  
  344.         // tell the job that the PPU is ready for occlusion culling, this call will
  345.         // start the check occlusion job if the prepare step has finished, if not
  346.         // the prepare job itself will start the culling job
  347.         bool bNeedJobStart = false;
  348.         {
  349.                 AUTO_LOCK(m_FollowUpLock);
  350.                 if (m_nPrepareState == PREPARE_DONE)
  351.                 {
  352.                         m_nPrepareState = CHECK_STARTED;
  353.                         bNeedJobStart = true;
  354.                 }
  355.                 else
  356.                 {
  357.                         m_nPrepareState = CHECK_REQUESTED;
  358.                         *((SRenderingPassInfo*)m_passInfoForCheckOcclusion) = passInfo;
  359.                 }
  360.         }
  361.  
  362.         if (bNeedJobStart)
  363.         {
  364.                 TOcclusionCheckJob job(passInfo);
  365.                 job.SetClassInstance(this);
  366.                 job.SetPriorityLevel(JobManager::eHighPriority);
  367.                 job.Run();
  368.         }
  369. }
  370.  
  371. void CCullThread::CullEnd()
  372. {
  373.         // If no frame was rendered, we need to remove the producer added in BeginCulling
  374.         gEnv->pJobManager->WaitForJob(m_PrepareBufferSync);
  375.  
  376.         bool bNeedRemoveProducer = false;
  377.         {
  378.                 if (m_nPrepareState != CHECK_STARTED && m_nPrepareState != IDLE)
  379.                 {
  380.                         bNeedRemoveProducer = true;
  381.                 }
  382.         }
  383.  
  384.         if (bNeedRemoveProducer)
  385.         {
  386.                 GetObjManager()->RemoveCullJobProducer();
  387.         }
  388. }
  389.  
  390. void CCullThread::OutputMeshList()
  391. {
  392.         /*
  393.            const uint8* pMeshes =       &m_pOCMBufferAligned[0];//actually starts at 16, but MeshOffset is zero based
  394.            const uint8* pInstances      =       &m_pOCMBufferAligned[m_OCMOffsetInstances];
  395.            const uint8* pInstance       =       pInstances;//+b*(sizeof(int)+12*sizeof(float));//meshoffset+worldmatrix43
  396.            for(size_t b=0;b<m_OCMInstCount;b++,pInstance+=sizeof(int)+12*sizeof(float))
  397.            {
  398.             //const uint8*      pInstance       =       pInstances+b*(sizeof(int)+12*sizeof(float));//meshoffset+worldmatrix43
  399.             const uint32        MeshOffset=     reinterpret_cast<const uint32*>(pInstance)[0];
  400.             const uint8*        pMesh                   =       pMeshes+MeshOffset;
  401.             printf("%d Poly:%10d pInstance:0x%x MeshOffset:0x%x this:0x%x pMeshes:0x%x pMesh:0x%x- \n",(int)b,*reinterpret_cast<const uint32*>(pMesh),(int)pInstance,(int)MeshOffset,(int)this,(int)pMeshes,(int)pMesh);
  402.            }
  403.            printf("\n");
  404.          */
  405. }
  406.  
  407. float DistToBox(Vec3 Center, Vec3 Extends, Vec3 ViewPos)
  408. {
  409.         Vec3 Delta = (ViewPos - Center).abs();
  410.         Delta = (Delta - Extends);
  411.         Delta.x = max(Delta.x, 0.f);
  412.         Delta.y = max(Delta.y, 0.f);
  413.         Delta.z = max(Delta.z, 0.f);
  414.         return Delta.x * Delta.x + Delta.y * Delta.y + Delta.z * Delta.z;
  415. }
  416.  
  417. void CCullThread::RasterizeZBuffer(uint32 PolyLimit)
  418. {
  419.         if (m_OCMInstCount == 0)
  420.         {
  421.                 float fRed[4] = { 1, 0, 0, 1 };
  422.                 IRenderAuxText::Draw2dLabel(1.0f, 5.0f, 1.6f, fRed, false, "OCM file failed to load -> no occlusion checking possible!");
  423.                 return;
  424.         }
  425.  
  426.         uint Tmp[16 * sizeof(float) * 2 + 16];
  427.         const uint8* pMeshes = m_pOCMBufferAligned; //actually starts at 16, but MeshOffset is zero based
  428.         uint8* pInstances = &m_pOCMBufferAligned[m_OCMOffsetInstances];
  429.         //std::vector<uint16>   Indices;
  430.         //Indices.resize(65536);
  431.         //for(size_t a=0,S=Indices.size();a<S;a++)
  432.         //      Indices[a]      =       a;
  433.  
  434.         Matrix44A& rTmp0 = *reinterpret_cast<Matrix44A*>((reinterpret_cast<size_t>(Tmp) + 15) & ~15);
  435.         Matrix44A& rTmp1 = *reinterpret_cast<Matrix44A*>((reinterpret_cast<size_t>(Tmp) + 15 + 64) & ~15);
  436.         rTmp0 = m_MatScreenViewProj.GetTransposed();
  437.         //rTmp  =       m_MatScreenViewProjTransposed;
  438.  
  439.         int Visible = 0;
  440.         int Invisible = 0;
  441.         uint32 Poly = 0;
  442.         float LastDist;
  443.         uint8* pLastInstance = 0;
  444.  
  445.         bool Swapped = true;
  446.         for (size_t c = 0; c < 20 && Swapped; c++)//incrementally (max 20 rounds) bubblesort instances front to back
  447.         {
  448.                 Swapped = false;
  449.                 LastDist = -1.f;
  450.                 for (size_t a = 0; a < m_OCMInstCount; a++)
  451.                 {
  452.                         Matrix44 World(IDENTITY);
  453.                         uint8* pInstance = pInstances + a * (sizeof(int) + 12 * sizeof(float));//meshoffset+worldmatrix43
  454.                         const uint32 MeshOffset = *reinterpret_cast<const uint32*>(&pInstance[0]);
  455.                         const float* pWorldMat = reinterpret_cast<const float*>(&pInstance[4]);
  456.                         memcpy(&World, (void*)pWorldMat, 12 * sizeof(float));
  457.                         Vec3 Pos = World.GetTranslation(), Extend;
  458.                         Extend.x = (fabsf(World.m00) + fabsf(World.m01) + fabsf(World.m02)) * (127.f);
  459.                         Extend.y = (fabsf(World.m10) + fabsf(World.m11) + fabsf(World.m12)) * (127.f);
  460.                         Extend.z = (fabsf(World.m20) + fabsf(World.m21) + fabsf(World.m22)) * (127.f);
  461.  
  462.                         //simple incremental bubblesort
  463.                         const float Dist = DistToBox(Pos, Extend, m_Position);
  464.                         if (Dist < LastDist)
  465.                         {
  466.                                 PREFAST_ASSUME(pLastInstance);
  467.                                 Swapped = true;
  468.                                 for (size_t b = 0; b < 13; b++)
  469.                                         std::swap(reinterpret_cast<uint32*>(pLastInstance)[b], reinterpret_cast<uint32*>(pInstance)[b]);
  470.                         }
  471.                         else
  472.                                 LastDist = Dist;
  473.                         pLastInstance = pInstance;
  474.                 }
  475.         }
  476.  
  477.         //OutputMeshList();
  478.         //__SetHWThreadPriorityHigh();
  479.  
  480.         const bool EarlyOut = GetCVars()->e_CoverageBufferEarlyOut == 1;
  481.         const int64 MaxEarlyOutDelay = (int64)(GetCVars()->e_CoverageBufferEarlyOutDelay * 1000.0f);
  482.         LastDist = -1.f;
  483.  
  484.         ITimer* pTimer = gEnv->pTimer;
  485.         int64 StartTime = -1;
  486.  
  487.         for (size_t a = 0; a < m_OCMInstCount && (PolyLimit == 0 || Poly < PolyLimit); a++)
  488.         {
  489.                 // stop if MT need to run check occlusion
  490.                 if (EarlyOut && *const_cast<volatile int*>(&m_bCheckOcclusionRequested))
  491.                 {
  492.                         if (StartTime < 0)
  493.                                 StartTime = pTimer->GetAsyncTime().GetMicroSecondsAsInt64();
  494.  
  495.                         int64 CurTime = pTimer->GetAsyncTime().GetMicroSecondsAsInt64();
  496.                         if (CurTime - StartTime > MaxEarlyOutDelay)
  497.                                 break;
  498.                 }
  499.  
  500.                 Matrix44 World(IDENTITY);
  501.                 uint8* pInstance = pInstances + a * (sizeof(int) + 12 * sizeof(float));//meshoffset+worldmatrix43
  502.                 const uint32 MeshOffset = *reinterpret_cast<volatile const uint32*>(&pInstance[0]);
  503.                 const float* pWorldMat = reinterpret_cast<const float*>(&pInstance[4]);
  504.                 memcpy(&World, (void*)pWorldMat, 12 * sizeof(float));
  505.                 //World =       World.GetInverted();
  506.                 Vec3 Pos = World.GetTranslation(), Extend;
  507.                 Extend.x = (fabsf(World.m00) + fabsf(World.m01) + fabsf(World.m02)) * (127.f);
  508.                 Extend.y = (fabsf(World.m10) + fabsf(World.m11) + fabsf(World.m12)) * (127.f);
  509.                 Extend.z = (fabsf(World.m20) + fabsf(World.m21) + fabsf(World.m22)) * (127.f);
  510.                 /*
  511.                     //simple incremental bubblesort
  512.                     const float Dist    =       DistToBox(Pos,Extend,m_Position);
  513.                     if(Dist<LastDist)
  514.                     {
  515.                       for(size_t a=0;a<13;a++)
  516.                         std::swap(reinterpret_cast<uint32*>(pLastInstance)[a],reinterpret_cast<uint32*>(pInstance)[a]);
  517.                     }
  518.                     else
  519.                       LastDist  =       Dist;
  520.                     pLastInstance       =       pInstance;
  521.                  */
  522.                 const int InFrustum = RASTERIZER.AABBInFrustum(reinterpret_cast<NVMath::vec4*>(&rTmp0), Pos - Extend, Pos + Extend, m_Position);
  523.                 if (!InFrustum)
  524.                 {
  525.                         Invisible++;
  526.                         continue;
  527.                 }
  528.                 else
  529.                         Visible++;
  530.  
  531.                 rTmp1 = (m_MatScreenViewProj * World).GetTransposed();
  532.                 const uint8* pMesh = pMeshes + MeshOffset;
  533.                 const size_t TriCount = *reinterpret_cast<const uint32*>(pMesh);
  534.                 const size_t Tris16 = (reinterpret_cast<size_t>(pMesh + 4) + 15) & ~15;
  535.                 const int8* pTris = reinterpret_cast<const int8*>(Tris16);
  536.                 if (InFrustum & 2)
  537.                         RASTERIZER.Rasterize<true>(reinterpret_cast<NVMath::vec4*>(&rTmp1), reinterpret_cast<const NVMath::vec4*>(pTris), TriCount);
  538.                 else
  539.                         RASTERIZER.Rasterize<false>(reinterpret_cast<NVMath::vec4*>(&rTmp1), reinterpret_cast<const NVMath::vec4*>(pTris), TriCount);
  540.                 Poly += TriCount;
  541.         }
  542.  
  543. }
  544.  
  545. #if !defined(_RELEASE)
  546. void CCullThread::CoverageBufferDebugDraw()
  547. {
  548.         //static ICVar *pDebug = gEnv->pConsole->GetCVar("e_CoverageBufferDebug");
  549.         //RASTERIZER.m_DebugRender = pDebug->GetIVal() > 0? 1:0;
  550.         RASTERIZER.DrawDebug(m_pRenderer, 1);
  551. }
  552. #endif
  553.  
  554. void CCullThread::PrepareOcclusion()
  555. {
  556.         if (!GetCVars()->e_CameraFreeze)
  557.         {
  558.                 FUNCTION_PROFILER_3DENGINE;
  559.                 using namespace NVMath;
  560.  
  561.                 int bHWZBuffer = GetCVars()->e_CoverageBufferReproj;
  562.  
  563.                 if (bHWZBuffer > 3 && m_OCMBuffer.empty())
  564.                         bHWZBuffer = 2;
  565.  
  566.                 if ((bHWZBuffer & 3) > 0)
  567.                 {
  568.                         CRY_PROFILE_REGION(PROFILE_3DENGINE, "Transfer Previous Frame Z-Buffer");
  569.                         CRYPROFILE_SCOPE_PROFILE_MARKER("Transfer Previous Frame Z-Buffer");
  570.                         m_Enabled = RASTERIZER.DownLoadHWDepthBuffer(m_NearPlane, m_FarPlane, m_NearestMax, GetCVars()->e_CoverageBufferBias);
  571.                 }
  572.                 else
  573.                         RASTERIZER.Clear();
  574.         }
  575.  
  576.         TOcclusionPrepareReprojectJob job;
  577.         job.SetClassInstance(this);
  578.         job.SetPriorityLevel(JobManager::eHighPriority);
  579.         job.Run();
  580. }
  581.  
  582. void CCullThread::PrepareOcclusion_ReprojectZBuffer()
  583. {
  584.  
  585.         int bHWZBuffer = GetCVars()->e_CoverageBufferReproj;
  586.         int PolyLimit = GetCVars()->e_CoverageBufferRastPolyLimit;
  587.  
  588.         if (bHWZBuffer > 3 && m_OCMBuffer.empty())
  589.                 bHWZBuffer = 2;
  590.  
  591.         if (!GetCVars()->e_CameraFreeze && (bHWZBuffer & 3) > 0 && m_Enabled)
  592.         {
  593.                 enum { nLinesPerJob = 8 };
  594.                 m_nRunningReprojJobs = tdCullRasterizer::RESOLUTION_Y / nLinesPerJob;
  595.                 m_nRunningReprojJobsAfterMerge = tdCullRasterizer::RESOLUTION_Y / nLinesPerJob;
  596.                 for (int i = 0; i < tdCullRasterizer::RESOLUTION_Y; i += nLinesPerJob)
  597.                 {
  598.                         TOcclusionPrepareReprojectLineJob job((int)i, (int)nLinesPerJob);
  599.                         job.SetClassInstance(this);
  600.                         job.SetPriorityLevel(JobManager::eHighPriority);
  601.                         job.Run();
  602.                 }
  603.         }
  604.         else
  605.         {
  606.                 TOcclusionPrepareRasterizeJob job;
  607.                 job.SetClassInstance(this);
  608.                 job.SetPriorityLevel(JobManager::eHighPriority);
  609.                 job.Run();
  610.         }
  611. }
  612.  
  613. void CCullThread::PrepareOcclusion_ReprojectZBufferLine(int nStartLine, int nNumLines)
  614. {
  615.         if (!GetCVars()->e_CameraFreeze)
  616.         {
  617.                 uint Tmp[80];
  618.                 Matrix44A& rTmp = *reinterpret_cast<Matrix44A*>((reinterpret_cast<size_t>(Tmp) + 15) & ~15);
  619.                 rTmp = m_MatScreenViewProjTransposed;
  620.                 RASTERIZER.ReprojectHWDepthBuffer(rTmp, m_NearPlane, m_FarPlane, m_NearestMax, GetCVars()->e_CoverageBufferBias, nStartLine, nNumLines);
  621.         }
  622.  
  623.         uint32 nRemainingJobs = CryInterlockedDecrement((volatile int*)&m_nRunningReprojJobs);
  624.         if (nRemainingJobs == 0)
  625.         {
  626.                 enum { nLinesPerJob = 8 };
  627.                 for (int i = 0; i < tdCullRasterizer::RESOLUTION_Y; i += nLinesPerJob)
  628.                 {
  629.                         TOcclusionPrepareReprojectLineJob2 job((int)i, (int)nLinesPerJob);
  630.                         job.SetClassInstance(this);
  631.                         job.SetPriorityLevel(JobManager::eHighPriority);
  632.                         job.Run();
  633.                 }
  634.         }
  635. }
  636.  
  637. void CCullThread::PrepareOcclusion_ReprojectZBufferLineAfterMerge(int nStartLine, int nNumLines)
  638. {
  639.         // merge the reprojected buffer bevore new jobs are started on it
  640.         RASTERIZER.MergeReprojectHWDepthBuffer(nStartLine, nNumLines);
  641.  
  642.         if (!GetCVars()->e_CameraFreeze)
  643.         {
  644.                 uint Tmp[80];
  645.                 Matrix44A& rTmp = *reinterpret_cast<Matrix44A*>((reinterpret_cast<size_t>(Tmp) + 15) & ~15);
  646.                 rTmp = m_MatScreenViewProjTransposed;
  647.                 RASTERIZER.ReprojectHWDepthBufferAfterMerge(rTmp, m_NearPlane, m_FarPlane, m_NearestMax, GetCVars()->e_CoverageBufferBias, nStartLine, nNumLines);
  648.         }
  649.  
  650.         uint32 nRemainingJobs = CryInterlockedDecrement((volatile int*)&m_nRunningReprojJobsAfterMerge);
  651.         if (nRemainingJobs == 0)
  652.         {
  653.                 TOcclusionPrepareRasterizeJob job;
  654.                 job.SetClassInstance(this);
  655.                 job.SetPriorityLevel(JobManager::eHighPriority);
  656.                 job.Run();
  657.         }
  658. }
  659.  
  660. void CCullThread::PrepareOcclusion_RasterizeZBuffer()
  661. {
  662.         m_Enabled = true;
  663.         if (!GetCVars()->e_CameraFreeze)
  664.         {
  665.                 int bHWZBuffer = GetCVars()->e_CoverageBufferReproj;
  666.                 int PolyLimit = GetCVars()->e_CoverageBufferRastPolyLimit;
  667.  
  668.                 if (bHWZBuffer > 3 && m_OCMBuffer.empty())
  669.                         bHWZBuffer = 2;
  670.  
  671.                 if (bHWZBuffer & 4)
  672.                 {
  673.                         CRY_PROFILE_REGION(PROFILE_3DENGINE, "Rasterize Z-Buffer");
  674.                         CRYPROFILE_SCOPE_PROFILE_MARKER("Rasterize Z-Buffer");
  675.                         m_Enabled = true;
  676.                         RasterizeZBuffer((uint32)PolyLimit);
  677.                 }
  678.         }
  679.  
  680.         bool bNeedJobStart = false;
  681.         {
  682.                 AUTO_LOCK(m_FollowUpLock);
  683.                 if (m_nPrepareState == CHECK_REQUESTED)
  684.                 {
  685.                         m_nPrepareState = CHECK_STARTED;
  686.                         bNeedJobStart = true;
  687.                 }
  688.                 else
  689.                         m_nPrepareState = PREPARE_DONE;
  690.         }
  691.  
  692.         m_PrepareBufferSync.SetStopped();
  693.         if (bNeedJobStart)
  694.         {
  695.                 TOcclusionCheckJob job(*((SRenderingPassInfo*)m_passInfoForCheckOcclusion));
  696.                 job.SetClassInstance(this);
  697.                 job.SetPriorityLevel(JobManager::eHighPriority);
  698.                 job.Run();
  699.         }
  700. }
  701.  
  702. void CCullThread::CheckOcclusion(SRenderingPassInfo passInfo)
  703. {
  704.         uint8 AlignBuffer[2 * sizeof(Matrix44A) + 16];
  705.         size_t pBuffer = (reinterpret_cast<size_t>(AlignBuffer) + 15) & ~15;
  706.         Matrix44A& RESTRICT_REFERENCE rMatFinalT = reinterpret_cast<Matrix44A*>(pBuffer)[1];
  707.  
  708.         Vec3 localPostion;
  709.         memcpy(&localPostion, &m_Position, sizeof(Vec3));
  710.  
  711.         const AABB PosAABB = AABB(m_Position, 0.5f);
  712.         const float Bias = GetCVars()->e_CoverageBufferAABBExpand;
  713.         const float TerrainBias = GetCVars()->e_CoverageBufferTerrainExpand;
  714.         rMatFinalT = m_MatScreenViewProj.GetTransposed();
  715.         bool bEnabled = m_Enabled;
  716.  
  717.         while (1)
  718.         {
  719.                 SCheckOcclusionJobData jobData;
  720.                 GetObjManager()->PopFromCullQueue(&jobData);
  721.  
  722.                 // stop processing when beeing told so
  723.                 if (jobData.type == SCheckOcclusionJobData::QUIT)
  724.                         break;
  725.  
  726.                 if (jobData.type == SCheckOcclusionJobData::OCTREE_NODE)
  727.                 {
  728.                         AABB rAABB;
  729.                         COctreeNode* pOctTreeNode = jobData.octTreeData.pOctTreeNode;
  730.  
  731.                         memcpy(&rAABB, &pOctTreeNode->GetObjectsBBox(), sizeof(AABB));
  732.                         float fDistance = sqrtf(Distance::Point_AABBSq(passInfo.GetCamera().GetPosition(), rAABB));
  733.  
  734.                         // Test OctTree BoundingBox
  735.                         if (TestAABB(rAABB, fDistance))
  736.                         {
  737.                                 Vec3 vAmbColor(jobData.octTreeData.vAmbColor[0], jobData.octTreeData.vAmbColor[1], jobData.octTreeData.vAmbColor[2]);
  738.  
  739.                                 // Pass info is a copy
  740.                                 passInfo.OverrideRenderItemSorter(jobData.rendItemSorter);
  741.                                 //passInfo.m_pCamera = jobData.pCam;
  742.                                 pOctTreeNode->COctreeNode::RenderContent(jobData.octTreeData.nRenderMask, vAmbColor, passInfo);
  743.                         }
  744.                 }
  745.                 else if (jobData.type == SCheckOcclusionJobData::TERRAIN_NODE)
  746.                 {
  747.                         AABB rAABB(Vec3(jobData.terrainData.vAABBMin[0], jobData.terrainData.vAABBMin[1], jobData.terrainData.vAABBMin[2]),
  748.                                    Vec3(jobData.terrainData.vAABBMax[0], jobData.terrainData.vAABBMax[1], jobData.terrainData.vAABBMax[2]));
  749.  
  750.                         float fDistance = jobData.terrainData.fDistance;
  751.  
  752.                         // special case for terrain, they are direclty tested and send back to PPU
  753.                         if (TestAABB(rAABB, fDistance, TerrainBias))
  754.                         {
  755.                                 GetObjManager()->PushIntoCullOutputQueue(SCheckOcclusionOutput::CreateTerrainOutput(jobData.terrainData.pTerrainNode, passInfo));
  756.                         }
  757.  
  758.                 }
  759.                 else
  760.                 {
  761.                         __debugbreak(); // unknown culler job type
  762.                 }
  763.  
  764.         }
  765.  
  766.         GetObjManager()->RemoveCullJobProducer();
  767. }
  768.  
  769. ///////////////////////////////////////////////////////////////////////////////
  770. bool CCullThread::TestAABB(const AABB& rAABB, float fEntDistance, float fVerticalExpand)
  771. {
  772.         IF (GetCVars()->e_CheckOcclusion == 0, 0)
  773.                 return true;
  774.  
  775.         const AABB PosAABB = AABB(m_Position, 0.5f);
  776.         const float Bias = GetCVars()->e_CoverageBufferAABBExpand;
  777.         Matrix44A rMatFinalT(m_MatScreenViewProj.GetTransposed());
  778.         AABB bbox(rAABB);
  779.  
  780.         if (Bias < 0.f)
  781.                 bbox.Expand((bbox.max - bbox.min) * -Bias - Vec3(Bias, Bias, Bias));
  782.         else
  783.                 bbox.Expand(Vec3(Bias * fEntDistance));
  784.  
  785.         float fVerticalExpandScaled = fVerticalExpand * fEntDistance;
  786.         bbox.min.z -= fVerticalExpandScaled;
  787.         bbox.max.z += fVerticalExpandScaled;
  788.  
  789.         if (!m_Enabled)
  790.                 return true;
  791.  
  792.         if (bbox.IsIntersectBox(PosAABB))
  793.                 return true;
  794.  
  795.         if (RASTERIZER.TestAABB(reinterpret_cast<const NVMath::vec4*>(&rMatFinalT), bbox.min, bbox.max, m_Position))
  796.                 return true;
  797.  
  798.         return false;
  799. }
  800.  
  801. bool CCullThread::TestQuad(const Vec3& vCenter, const Vec3& vAxisX, const Vec3& vAxisY)
  802. {
  803.         IF (GetCVars()->e_CheckOcclusion == 0, 0)
  804.                 return true;
  805.  
  806.         if (!m_Enabled)
  807.                 return true;
  808.  
  809.         Matrix44A rMatFinalT(m_MatScreenViewProj.GetTransposed());
  810.         if (RASTERIZER.TestQuad(reinterpret_cast<const NVMath::vec4*>(&rMatFinalT), vCenter, vAxisX, vAxisY))
  811.                 return true;
  812.  
  813.         return false;
  814. }
  815.  
  816. } // namespace NAsyncCull
  817.  
downloadCCullThread.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top