"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/swr/rasterizer/core/tilemgr.h" (16 Sep 2020, 12897 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tilemgr.h" see the Fossies "Dox" file reference documentation.

    1 /****************************************************************************
    2  * Copyright (C) 2014-2018 Intel Corporation.   All Rights Reserved.
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice (including the next
   12  * paragraph) shall be included in all copies or substantial portions of the
   13  * Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   21  * IN THE SOFTWARE.
   22  *
   23  * @file tilemgr.h
   24  *
   25  * @brief Definitions for Macro Tile Manager which provides the facilities
   26  *        for threads to work on an macro tile.
   27  *
   28  ******************************************************************************/
   29 #pragma once
   30 
   31 #include <set>
   32 #include <unordered_map>
   33 #include "common/formats.h"
   34 #include "common/intrin.h"
   35 #include "fifo.hpp"
   36 #include "context.h"
   37 #include "format_traits.h"
   38 
   39 //////////////////////////////////////////////////////////////////////////
   40 /// MacroTile - work queue for a tile.
   41 //////////////////////////////////////////////////////////////////////////
   42 struct MacroTileQueue
   43 {
   44     MacroTileQueue() {}
   45     ~MacroTileQueue() { destroy(); }
   46 
   47     //////////////////////////////////////////////////////////////////////////
   48     /// @brief Returns number of work items queued for this tile.
   49     uint32_t getNumQueued() { return mFifo.getNumQueued(); }
   50 
   51     //////////////////////////////////////////////////////////////////////////
   52     /// @brief Attempt to lock the work fifo. If already locked then return false.
   53     bool tryLock() { return mFifo.tryLock(); }
   54 
   55     //////////////////////////////////////////////////////////////////////////
   56     /// @brief Clear fifo and unlock it.
   57     template <typename ArenaT>
   58     void clear(ArenaT& arena)
   59     {
   60         mFifo.clear(arena);
   61     }
   62 
   63     //////////////////////////////////////////////////////////////////////////
   64     /// @brief Peek at work sitting at the front of the fifo.
   65     BE_WORK* peek() { return mFifo.peek(); }
   66 
   67     template <typename ArenaT>
   68     bool enqueue_try_nosync(ArenaT& arena, const BE_WORK* entry)
   69     {
   70         return mFifo.enqueue_try_nosync(arena, entry);
   71     }
   72 
   73     //////////////////////////////////////////////////////////////////////////
   74     /// @brief Move to next work item
   75     void dequeue() { mFifo.dequeue_noinc(); }
   76 
   77     //////////////////////////////////////////////////////////////////////////
   78     /// @brief Destroy fifo
   79     void destroy() { mFifo.destroy(); }
   80 
   81     ///@todo This will all be private.
   82     uint32_t mWorkItemsFE = 0;
   83     uint32_t mWorkItemsBE = 0;
   84     uint32_t mId          = 0;
   85 
   86 private:
   87     QUEUE<BE_WORK> mFifo;
   88 };
   89 
   90 //////////////////////////////////////////////////////////////////////////
   91 /// MacroTileMgr - Manages macrotiles for a draw.
   92 //////////////////////////////////////////////////////////////////////////
   93 class MacroTileMgr
   94 {
   95 public:
   96     MacroTileMgr(CachingArena& arena);
   97     ~MacroTileMgr()
   98     {
   99         for (auto* pTile : mTiles)
  100         {
  101             delete pTile;
  102         }
  103     }
  104 
  105     INLINE void initialize()
  106     {
  107         mWorkItemsProduced = 0;
  108         mWorkItemsConsumed = 0;
  109 
  110         mDirtyTiles.clear();
  111     }
  112 
  113     INLINE std::vector<MacroTileQueue*>& getDirtyTiles() { return mDirtyTiles; }
  114     void                                 markTileComplete(uint32_t id);
  115 
  116     INLINE bool isWorkComplete() { return mWorkItemsProduced == mWorkItemsConsumed; }
  117 
  118     void enqueue(uint32_t x, uint32_t y, BE_WORK* pWork);
  119 
  120     static INLINE void getTileIndices(uint32_t tileID, uint32_t& x, uint32_t& y)
  121     {
  122         // Morton / Z order of tiles
  123         x = pext_u32(tileID, 0x55555555);
  124         y = pext_u32(tileID, 0xAAAAAAAA);
  125     }
  126 
  127     static INLINE uint32_t getTileId(uint32_t x, uint32_t y)
  128     {
  129         // Morton / Z order of tiles
  130         return pdep_u32(x, 0x55555555) | pdep_u32(y, 0xAAAAAAAA);
  131     }
  132 
  133 private:
  134     CachingArena&                mArena;
  135     std::vector<MacroTileQueue*> mTiles;
  136 
  137     // Any tile that has work queued to it is a dirty tile.
  138     std::vector<MacroTileQueue*> mDirtyTiles;
  139 
  140     OSALIGNLINE(long) mWorkItemsProduced{0};
  141     OSALIGNLINE(volatile long) mWorkItemsConsumed{0};
  142 };
  143 
  144 typedef void (*PFN_DISPATCH)(DRAW_CONTEXT* pDC,
  145                              uint32_t      workerId,
  146                              uint32_t      threadGroupId,
  147                              void*&        pSpillFillBuffer,
  148                              void*&        pScratchSpace);
  149 
  150 //////////////////////////////////////////////////////////////////////////
  151 /// DispatchQueue - work queue for dispatch
  152 //////////////////////////////////////////////////////////////////////////
  153 class DispatchQueue
  154 {
  155 public:
  156     DispatchQueue() {}
  157 
  158     //////////////////////////////////////////////////////////////////////////
  159     /// @brief Setup the producer consumer counts.
  160     void initialize(uint32_t totalTasks, void* pTaskData, PFN_DISPATCH pfnDispatch)
  161     {
  162         // The available and outstanding counts start with total tasks.
  163         // At the start there are N tasks available and outstanding.
  164         // When both the available and outstanding counts have reached 0 then all work has
  165         // completed. When a worker starts on a threadgroup then it decrements the available count.
  166         // When a worker completes a threadgroup then it decrements the outstanding count.
  167 
  168         mTasksAvailable   = totalTasks;
  169         mTasksOutstanding = totalTasks;
  170 
  171         mpTaskData   = pTaskData;
  172         mPfnDispatch = pfnDispatch;
  173     }
  174 
  175     //////////////////////////////////////////////////////////////////////////
  176     /// @brief Returns number of tasks available for this dispatch.
  177     uint32_t getNumQueued() { return (mTasksAvailable > 0) ? mTasksAvailable : 0; }
  178 
  179     //////////////////////////////////////////////////////////////////////////
  180     /// @brief Atomically decrement the work available count. If the result
  181     //         is greater than 0 then we can on the associated thread group.
  182     //         Otherwise, there is no more work to do.
  183     bool getWork(uint32_t& groupId)
  184     {
  185         long result = InterlockedDecrement(&mTasksAvailable);
  186 
  187         if (result >= 0)
  188         {
  189             groupId = result;
  190             return true;
  191         }
  192 
  193         return false;
  194     }
  195 
  196     //////////////////////////////////////////////////////////////////////////
  197     /// @brief Atomically decrement the outstanding count. A worker is notifying
  198     ///        us that he just finished some work. Also, return true if we're
  199     ///        the last worker to complete this dispatch.
  200     bool finishedWork()
  201     {
  202         long result = InterlockedDecrement(&mTasksOutstanding);
  203         SWR_ASSERT(result >= 0, "Should never oversubscribe work");
  204 
  205         return (result == 0) ? true : false;
  206     }
  207 
  208     //////////////////////////////////////////////////////////////////////////
  209     /// @brief Work is complete once both the available/outstanding counts have reached 0.
  210     bool isWorkComplete() { return ((mTasksAvailable <= 0) && (mTasksOutstanding <= 0)); }
  211 
  212     //////////////////////////////////////////////////////////////////////////
  213     /// @brief Return pointer to task data.
  214     const void* GetTasksData() { return mpTaskData; }
  215 
  216     //////////////////////////////////////////////////////////////////////////
  217     /// @brief Dispatches a unit of work
  218     void dispatch(DRAW_CONTEXT* pDC,
  219                   uint32_t      workerId,
  220                   uint32_t      threadGroupId,
  221                   void*&        pSpillFillBuffer,
  222                   void*&        pScratchSpace)
  223     {
  224         SWR_ASSERT(mPfnDispatch != nullptr);
  225         mPfnDispatch(pDC, workerId, threadGroupId, pSpillFillBuffer, pScratchSpace);
  226     }
  227 
  228     void* mpTaskData{nullptr}; // The API thread will set this up and the callback task function
  229                                // will interpet this.
  230     PFN_DISPATCH mPfnDispatch{nullptr}; // Function to call per dispatch
  231 
  232     OSALIGNLINE(volatile long) mTasksAvailable{0};
  233     OSALIGNLINE(volatile long) mTasksOutstanding{0};
  234 };
  235 
  236 /// @note this enum needs to be kept in sync with SWR_TILE_STATE!
  237 enum HOTTILE_STATE
  238 {
  239     HOTTILE_INVALID,  // tile is in unitialized state and should be loaded with surface contents
  240                       // before rendering
  241     HOTTILE_CLEAR,    // tile should be cleared
  242     HOTTILE_DIRTY,    // tile has been rendered to
  243     HOTTILE_RESOLVED, // tile is consistent with memory (either loaded or stored)
  244 };
  245 
  246 struct HOTTILE
  247 {
  248     uint8_t*      pBuffer;
  249     HOTTILE_STATE state;
  250     uint32_t clearData[4]; // May need to change based on pfnClearTile implementation.  Reorder for
  251                         // alignment?
  252     uint32_t numSamples;
  253     uint32_t renderTargetArrayIndex; // current render target array index loaded
  254 };
  255 
  256 union HotTileSet
  257 {
  258     struct
  259     {
  260         HOTTILE Color[SWR_NUM_RENDERTARGETS];
  261         HOTTILE Depth;
  262         HOTTILE Stencil;
  263     };
  264     HOTTILE Attachment[SWR_NUM_ATTACHMENTS];
  265 };
  266 
  267 class HotTileMgr
  268 {
  269 public:
  270     HotTileMgr()
  271     {
  272         memset(mHotTiles, 0, sizeof(mHotTiles));
  273 
  274         // cache hottile size
  275         for (uint32_t i = SWR_ATTACHMENT_COLOR0; i <= SWR_ATTACHMENT_COLOR7; ++i)
  276         {
  277             mHotTileSize[i] = KNOB_MACROTILE_X_DIM * KNOB_MACROTILE_Y_DIM *
  278                               FormatTraits<KNOB_COLOR_HOT_TILE_FORMAT>::bpp / 8;
  279         }
  280         mHotTileSize[SWR_ATTACHMENT_DEPTH] = KNOB_MACROTILE_X_DIM * KNOB_MACROTILE_Y_DIM *
  281                                              FormatTraits<KNOB_DEPTH_HOT_TILE_FORMAT>::bpp / 8;
  282         mHotTileSize[SWR_ATTACHMENT_STENCIL] = KNOB_MACROTILE_X_DIM * KNOB_MACROTILE_Y_DIM *
  283                                                FormatTraits<KNOB_STENCIL_HOT_TILE_FORMAT>::bpp / 8;
  284     }
  285 
  286     ~HotTileMgr()
  287     {
  288         for (int x = 0; x < KNOB_NUM_HOT_TILES_X; ++x)
  289         {
  290             for (int y = 0; y < KNOB_NUM_HOT_TILES_Y; ++y)
  291             {
  292                 for (int a = 0; a < SWR_NUM_ATTACHMENTS; ++a)
  293                 {
  294                     FreeHotTileMem(mHotTiles[x][y].Attachment[a].pBuffer);
  295                 }
  296             }
  297         }
  298     }
  299 
  300     void InitializeHotTiles(SWR_CONTEXT*  pContext,
  301                             DRAW_CONTEXT* pDC,
  302                             uint32_t      workerId,
  303                             uint32_t      macroID);
  304 
  305     HOTTILE* GetHotTile(SWR_CONTEXT*                pContext,
  306                         DRAW_CONTEXT*               pDC,
  307                         HANDLE                      hWorkerData,
  308                         uint32_t                    macroID,
  309                         SWR_RENDERTARGET_ATTACHMENT attachment,
  310                         bool                        create,
  311                         uint32_t                    numSamples             = 1,
  312                         uint32_t                    renderTargetArrayIndex = 0);
  313 
  314     HOTTILE* GetHotTileNoLoad(SWR_CONTEXT*                pContext,
  315                               DRAW_CONTEXT*               pDC,
  316                               uint32_t                    macroID,
  317                               SWR_RENDERTARGET_ATTACHMENT attachment,
  318                               bool                        create,
  319                               uint32_t                    numSamples = 1);
  320 
  321     static void ClearColorHotTile(const HOTTILE* pHotTile);
  322     static void ClearDepthHotTile(const HOTTILE* pHotTile);
  323     static void ClearStencilHotTile(const HOTTILE* pHotTile);
  324 
  325 private:
  326     HotTileSet mHotTiles[KNOB_NUM_HOT_TILES_X][KNOB_NUM_HOT_TILES_Y];
  327     uint32_t   mHotTileSize[SWR_NUM_ATTACHMENTS];
  328 
  329     void* AllocHotTileMem(size_t size, uint32_t align, uint32_t numaNode)
  330     {
  331         void* p = nullptr;
  332 #if defined(_WIN32)
  333         HANDLE hProcess = GetCurrentProcess();
  334         p               = VirtualAllocExNuma(
  335             hProcess, nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, numaNode);
  336 #else
  337         p = AlignedMalloc(size, align);
  338 #endif
  339 
  340         return p;
  341     }
  342 
  343     void FreeHotTileMem(void* pBuffer)
  344     {
  345         if (pBuffer)
  346         {
  347 #if defined(_WIN32)
  348             VirtualFree(pBuffer, 0, MEM_RELEASE);
  349 #else
  350             AlignedFree(pBuffer);
  351 #endif
  352         }
  353     }
  354 };