1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
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:
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
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
25 * @brief Definitions for Macro Tile Manager which provides the facilities
26 * for threads to work on an macro tile.
28 ******************************************************************************/
32 #include <unordered_map>
33 #include "common/formats.h"
36 #include "format_traits.h"
38 //////////////////////////////////////////////////////////////////////////
39 /// MacroTile - work queue for a tile.
40 //////////////////////////////////////////////////////////////////////////
46 //////////////////////////////////////////////////////////////////////////
47 /// @brief Returns number of work items queued for this tile.
48 uint32_t getNumQueued()
50 return mFifo
.getNumQueued();
53 //////////////////////////////////////////////////////////////////////////
54 /// @brief Attempt to lock the work fifo. If already locked then return false.
57 return mFifo
.tryLock();
60 //////////////////////////////////////////////////////////////////////////
61 /// @brief Clear fifo and unlock it.
62 void clear(Arena
& arena
)
67 //////////////////////////////////////////////////////////////////////////
68 /// @brief Peek at work sitting at the front of the fifo.
74 bool enqueue_try_nosync(Arena
& arena
, const BE_WORK
* entry
)
76 return mFifo
.enqueue_try_nosync(arena
, entry
);
79 //////////////////////////////////////////////////////////////////////////
80 /// @brief Move to next work item
83 mFifo
.dequeue_noinc();
86 //////////////////////////////////////////////////////////////////////////
87 /// @brief Destroy fifo
93 ///@todo This will all be private.
94 uint32_t mWorkItemsFE
= 0;
95 uint32_t mWorkItemsBE
= 0;
101 //////////////////////////////////////////////////////////////////////////
102 /// MacroTileMgr - Manages macrotiles for a draw.
103 //////////////////////////////////////////////////////////////////////////
107 MacroTileMgr(Arena
& arena
);
110 for (auto &tile
: mTiles
)
112 tile
.second
.destroy();
117 INLINE
std::vector
<uint32_t>& getDirtyTiles() { return mDirtyTiles
; }
118 INLINE MacroTileQueue
& getMacroTileQueue(uint32_t id
) { return mTiles
[id
]; }
119 void markTileComplete(uint32_t id
);
121 INLINE
bool isWorkComplete()
123 return mWorkItemsProduced
== mWorkItemsConsumed
;
126 void enqueue(uint32_t x
, uint32_t y
, BE_WORK
*pWork
);
128 static INLINE
void getTileIndices(uint32_t tileID
, uint32_t &x
, uint32_t &y
)
131 x
= (tileID
>> 16) & 0xffff;
134 void *operator new(size_t size
);
135 void operator delete (void *p
);
139 std::unordered_map
<uint32_t, MacroTileQueue
> mTiles
;
141 // Any tile that has work queued to it is a dirty tile.
142 std::vector
<uint32_t> mDirtyTiles
;
144 OSALIGNLINE(LONG
) mWorkItemsProduced
{ 0 };
145 OSALIGNLINE(volatile LONG
) mWorkItemsConsumed
{ 0 };
148 //////////////////////////////////////////////////////////////////////////
149 /// DispatchQueue - work queue for dispatch
150 //////////////////////////////////////////////////////////////////////////
156 //////////////////////////////////////////////////////////////////////////
157 /// @brief Setup the producer consumer counts.
158 void initialize(uint32_t totalTasks
, void* pTaskData
)
160 // The available and outstanding counts start with total tasks.
161 // At the start there are N tasks available and outstanding.
162 // When both the available and outstanding counts have reached 0 then all work has completed.
163 // When a worker starts on a threadgroup then it decrements the available count.
164 // When a worker completes a threadgroup then it decrements the outstanding count.
166 mTasksAvailable
= totalTasks
;
167 mTasksOutstanding
= totalTasks
;
169 mpTaskData
= pTaskData
;
172 //////////////////////////////////////////////////////////////////////////
173 /// @brief Returns number of tasks available for this dispatch.
174 uint32_t getNumQueued()
176 return (mTasksAvailable
> 0) ? mTasksAvailable
: 0;
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
)
185 LONG result
= InterlockedDecrement(&mTasksAvailable
);
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.
202 LONG result
= InterlockedDecrement(&mTasksOutstanding
);
203 SWR_ASSERT(result
>= 0, "Should never oversubscribe work");
205 return (result
== 0) ? true : false;
208 //////////////////////////////////////////////////////////////////////////
209 /// @brief Work is complete once both the available/outstanding counts have reached 0.
210 bool isWorkComplete()
212 return ((mTasksAvailable
<= 0) &&
213 (mTasksOutstanding
<= 0));
216 //////////////////////////////////////////////////////////////////////////
217 /// @brief Return pointer to task data.
218 const void* GetTasksData()
223 void *operator new(size_t size
);
224 void operator delete (void *p
);
226 void* mpTaskData
{ nullptr }; // The API thread will set this up and the callback task function will interpet this.
228 OSALIGNLINE(volatile LONG
) mTasksAvailable
{ 0 };
229 OSALIGNLINE(volatile LONG
) mTasksOutstanding
{ 0 };
235 HOTTILE_INVALID
, // tile is in unitialized state and should be loaded with surface contents before rendering
236 HOTTILE_CLEAR
, // tile should be cleared
237 HOTTILE_DIRTY
, // tile has been rendered to
238 HOTTILE_RESOLVED
, // tile has been stored to memory
245 DWORD clearData
[4]; // May need to change based on pfnClearTile implementation. Reorder for alignment?
247 uint32_t renderTargetArrayIndex
; // current render target array index loaded
254 HOTTILE Color
[SWR_NUM_RENDERTARGETS
];
258 HOTTILE Attachment
[SWR_NUM_ATTACHMENTS
];
266 memset(&mHotTiles
[0][0], 0, sizeof(mHotTiles
));
268 // cache hottile size
269 for (uint32_t i
= SWR_ATTACHMENT_COLOR0
; i
<= SWR_ATTACHMENT_COLOR7
; ++i
)
271 mHotTileSize
[i
] = KNOB_MACROTILE_X_DIM
* KNOB_MACROTILE_Y_DIM
* FormatTraits
<KNOB_COLOR_HOT_TILE_FORMAT
>::bpp
/ 8;
273 mHotTileSize
[SWR_ATTACHMENT_DEPTH
] = KNOB_MACROTILE_X_DIM
* KNOB_MACROTILE_Y_DIM
* FormatTraits
<KNOB_DEPTH_HOT_TILE_FORMAT
>::bpp
/ 8;
274 mHotTileSize
[SWR_ATTACHMENT_STENCIL
] = KNOB_MACROTILE_X_DIM
* KNOB_MACROTILE_Y_DIM
* FormatTraits
<KNOB_STENCIL_HOT_TILE_FORMAT
>::bpp
/ 8;
279 for (int x
= 0; x
< KNOB_NUM_HOT_TILES_X
; ++x
)
281 for (int y
= 0; y
< KNOB_NUM_HOT_TILES_Y
; ++y
)
283 for (int a
= 0; a
< SWR_NUM_ATTACHMENTS
; ++a
)
285 if (mHotTiles
[x
][y
].Attachment
[a
].pBuffer
!= NULL
)
287 _aligned_free(mHotTiles
[x
][y
].Attachment
[a
].pBuffer
);
288 mHotTiles
[x
][y
].Attachment
[a
].pBuffer
= NULL
;
295 void InitializeHotTiles(SWR_CONTEXT
* pContext
, DRAW_CONTEXT
* pDC
, uint32_t macroID
);
297 HOTTILE
*GetHotTile(SWR_CONTEXT
* pContext
, DRAW_CONTEXT
* pDC
, uint32_t macroID
, SWR_RENDERTARGET_ATTACHMENT attachment
, bool create
, uint32_t numSamples
= 1,
298 uint32_t renderTargetArrayIndex
= 0);
300 HOTTILE
*GetHotTileNoLoad(SWR_CONTEXT
* pContext
, DRAW_CONTEXT
* pDC
, uint32_t macroID
, SWR_RENDERTARGET_ATTACHMENT attachment
);
302 static void ClearColorHotTile(const HOTTILE
* pHotTile
);
303 static void ClearDepthHotTile(const HOTTILE
* pHotTile
);
304 static void ClearStencilHotTile(const HOTTILE
* pHotTile
);
307 HotTileSet mHotTiles
[KNOB_NUM_HOT_TILES_X
][KNOB_NUM_HOT_TILES_Y
];
308 uint32_t mHotTileSize
[SWR_NUM_ATTACHMENTS
];