1/****************************************************************************
2* Copyright (C) 2014-2015 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 tilingtraits.h
24*
25* @brief Tiling traits.
26*
27******************************************************************************/
28#pragma once
29
30#include "core/state.h"
31#include "common/intrin.h"
32
33template<SWR_TILE_MODE mode, int>
34struct TilingTraits
35{
36    static const SWR_TILE_MODE TileMode{ mode };
37    static UINT GetCu() { SWR_NOT_IMPL; return 0; }
38    static UINT GetCv() { SWR_NOT_IMPL; return 0; }
39    static UINT GetCr() { SWR_NOT_IMPL; return 0; }
40    static UINT GetTileIDShift() { SWR_NOT_IMPL; return 0; }
41
42    /// @todo correct pdep shifts for all rastertile dims.  Unused for now
43    static UINT GetPdepX() { SWR_NOT_IMPL; return 0x37; }
44    static UINT GetPdepY() { SWR_NOT_IMPL; return 0xC8; }
45};
46
47template<int X> struct TilingTraits <SWR_TILE_NONE, X>
48{
49    static const SWR_TILE_MODE TileMode{ SWR_TILE_NONE };
50    static UINT GetCu() { return 0; }
51    static UINT GetCv() { return 0; }
52    static UINT GetCr() { return 0; }
53    static UINT GetTileIDShift() { return 0; }
54    static UINT GetPdepX() { return 0x00; }
55    static UINT GetPdepY() { return 0x00; }
56};
57
58template<> struct TilingTraits <SWR_TILE_SWRZ, 8>
59{
60    static const SWR_TILE_MODE TileMode{ SWR_TILE_SWRZ };
61    static UINT GetCu() { return KNOB_TILE_X_DIM_SHIFT; }
62    static UINT GetCv() { return KNOB_TILE_Y_DIM_SHIFT; }
63    static UINT GetCr() { return 0; }
64    static UINT GetTileIDShift() { return KNOB_TILE_X_DIM_SHIFT + KNOB_TILE_Y_DIM_SHIFT; }
65
66    /// @todo correct pdep shifts for all rastertile dims.  Unused for now
67    static UINT GetPdepX() { SWR_NOT_IMPL; return 0x00; }
68    static UINT GetPdepY() { SWR_NOT_IMPL; return 0x00; }
69};
70
71template<> struct TilingTraits <SWR_TILE_SWRZ, 32>
72{
73    static const SWR_TILE_MODE TileMode{ SWR_TILE_SWRZ };
74    static UINT GetCu() { return KNOB_TILE_X_DIM_SHIFT + 2; }
75    static UINT GetCv() { return KNOB_TILE_Y_DIM_SHIFT; }
76    static UINT GetCr() { return 0; }
77    static UINT GetTileIDShift() { return KNOB_TILE_X_DIM_SHIFT + KNOB_TILE_Y_DIM_SHIFT + 2; }
78
79    static UINT GetPdepX() { return 0x37; }
80    static UINT GetPdepY() { return 0xC8; }
81};
82
83template<> struct TilingTraits <SWR_TILE_SWRZ, 128>
84{
85    static const SWR_TILE_MODE TileMode{ SWR_TILE_SWRZ };
86    static UINT GetCu() { return KNOB_TILE_X_DIM_SHIFT + 4; }
87    static UINT GetCv() { return KNOB_TILE_Y_DIM_SHIFT; }
88    static UINT GetCr() { return 0; }
89    static UINT GetTileIDShift() { return KNOB_TILE_X_DIM_SHIFT + KNOB_TILE_Y_DIM_SHIFT + 4; }
90
91    /// @todo correct pdep shifts for all rastertile dims.  Unused for now
92    static UINT GetPdepX() { SWR_NOT_IMPL; return 0x37; }
93    static UINT GetPdepY() { SWR_NOT_IMPL; return 0xC8; }
94};
95
96// y-major tiling layout unaffected by element size
97template<int X> struct TilingTraits <SWR_TILE_MODE_YMAJOR, X>
98{
99    static const SWR_TILE_MODE TileMode{ SWR_TILE_MODE_YMAJOR };
100    static UINT GetCu() { return 7; }
101    static UINT GetCv() { return 5; }
102    static UINT GetCr() { return 0; }
103    static UINT GetTileIDShift() { return 12; }
104
105    static UINT GetPdepX() { return 0xe0f; }
106    static UINT GetPdepY() { return 0x1f0; }
107};
108
109// x-major tiling layout unaffected by element size
110template<int X> struct TilingTraits <SWR_TILE_MODE_XMAJOR, X>
111{
112    static const SWR_TILE_MODE TileMode{ SWR_TILE_MODE_XMAJOR };
113    static UINT GetCu() { return 9; }
114    static UINT GetCv() { return 3; }
115    static UINT GetCr() { return 0; }
116    static UINT GetTileIDShift() { return 12; }
117
118    static UINT GetPdepX() { return 0x1ff; }
119    static UINT GetPdepY() { return 0xe00; }
120};
121
122template<int X> struct TilingTraits <SWR_TILE_MODE_WMAJOR, X>
123{
124    static const SWR_TILE_MODE TileMode{ SWR_TILE_MODE_WMAJOR };
125    static UINT GetCu() { return 6; }
126    static UINT GetCv() { return 6; }
127    static UINT GetCr() { return 0; }
128    static UINT GetTileIDShift() { return 12; }
129
130    static UINT GetPdepX() { return 0xe15; }
131    static UINT GetPdepY() { return 0x1ea; }
132};
133
134//////////////////////////////////////////////////////////////////////////
135/// @brief Computes the tileID for 2D tiled surfaces
136/// @param pitch - surface pitch in bytes
137/// @param tileX - x offset in tiles
138/// @param tileY - y offset in tiles
139template<typename TTraits>
140INLINE UINT ComputeTileOffset2D(UINT pitch, UINT tileX, UINT tileY)
141{
142    UINT tileID = tileY * (pitch >> TTraits::GetCu()) + tileX;
143    return tileID << TTraits::GetTileIDShift();
144}
145
146//////////////////////////////////////////////////////////////////////////
147/// @brief Computes the tileID for 3D tiled surfaces
148/// @param qpitch - surface qpitch in rows
149/// @param pitch - surface pitch in bytes
150/// @param tileX - x offset in tiles
151/// @param tileY - y offset in tiles
152/// @param tileZ - y offset in tiles
153template<typename TTraits>
154INLINE UINT ComputeTileOffset3D(UINT qpitch, UINT pitch, UINT tileX, UINT tileY, UINT tileZ)
155{
156    UINT tileID = (tileZ * (qpitch >> TTraits::GetCv()) + tileY) * (pitch >> TTraits::GetCu()) + tileX;
157    return tileID << TTraits::GetTileIDShift();
158}
159
160//////////////////////////////////////////////////////////////////////////
161/// @brief Computes the byte offset for 2D tiled surfaces
162/// @param pitch - surface pitch in bytes
163/// @param x - x offset in bytes
164/// @param y - y offset in rows
165template<typename TTraits>
166INLINE UINT ComputeOffset2D(UINT pitch, UINT x, UINT y)
167{
168    UINT tileID = ComputeTileOffset2D<TTraits>(pitch, x >> TTraits::GetCu(), y >> TTraits::GetCv());
169    UINT xSwizzle = pdep_u32(x, TTraits::GetPdepX());
170    UINT ySwizzle = pdep_u32(y, TTraits::GetPdepY());
171    return (tileID | xSwizzle | ySwizzle);
172}
173
174#if KNOB_ARCH <= KNOB_ARCH_AVX
175//////////////////////////////////////////////////////////////////////////
176/// @brief Computes the byte offset for 2D tiled surfaces. Specialization
177///        for tile-y surfaces that uses bit twiddling instead of pdep emulation.
178/// @param pitch - surface pitch in bytes
179/// @param x - x offset in bytes
180/// @param y - y offset in rows
181template<>
182INLINE UINT ComputeOffset2D<TilingTraits<SWR_TILE_MODE_YMAJOR, 32> >(UINT pitch, UINT x, UINT y)
183{
184    typedef TilingTraits<SWR_TILE_MODE_YMAJOR, 32> TTraits;
185
186    UINT tileID = ComputeTileOffset2D<TTraits>(pitch, x >> TTraits::GetCu(), y >> TTraits::GetCv());
187    UINT xSwizzle = ((x << 5) & 0xe00) | (x & 0xf);
188    UINT ySwizzle = (y << 4) & 0x1f0;
189    return (tileID | xSwizzle | ySwizzle);
190}
191#endif
192
193//////////////////////////////////////////////////////////////////////////
194/// @brief Computes the byte offset for 3D tiled surfaces
195/// @param qpitch - depth pitch in rows
196/// @param pitch - surface pitch in bytes
197/// @param x - x offset in bytes
198/// @param y - y offset in rows
199/// @param z - y offset in slices
200template<typename TTraits>
201INLINE UINT ComputeOffset3D(UINT qpitch, UINT pitch, UINT x, UINT y, UINT z)
202{
203    UINT tileID = ComputeTileOffset3D<TTraits>(qpitch, pitch, x >> TTraits::GetCu(), y >> TTraits::GetCv(), z >> TTraits::GetCr());
204    UINT xSwizzle = pdep_u32(x, TTraits::GetPdepX());
205    UINT ySwizzle = pdep_u32(y, TTraits::GetPdepY());
206    return (tileID | xSwizzle | ySwizzle);
207}
208