1 /*---------------------------------------------------------------------------*
2
3 Copyright 2010-2011 Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12
13 #include <stdio.h>
14
15 #if defined(WIN32) || defined(WIN64)
16 #include <pc/gx2.h>
17 #endif
18 #include <cafe/os.h>
19 #include <cafe/mem.h>
20 #include <cafe/gx2.h>
21
22 #include <cafe/gx2ut.h>
23
GX2UTGetSurfaceMipSliceSwizzle(const GX2Surface * pSurf,u32 mipLevel,u32 slice)24 u32 GX2UTGetSurfaceMipSliceSwizzle(const GX2Surface* pSurf, u32 mipLevel, u32 slice)
25 {
26 // Constants used by GPU7 (commented out values left for reference)
27 const u32 num_banks = 4;
28 const u32 num_channels = 2;
29 //const u32 group_size = 256;
30 //const u32 row_bytes = 2048;
31 //const u32 bank_swap_bytes = 256;
32 //const u32 sample_split_bytes = 2048;
33
34 // Make sure that swizzling is needed (not needed for small mipmaps)
35 if ( ((pSurf->swizzle >> 16) & 0xFF) <= mipLevel )
36 return 0;
37
38 u32 swizzle = GX2GetSurfaceSwizzle((GX2Surface*)pSurf);
39 u32 channel_swizzle = swizzle & 1; // bit 0
40 u32 bank_swizzle = (swizzle & 6) >> 1; // bit 1-2
41 u32 bank_slice_rotation = 0;
42 u32 channel_slice_rotation = 0;
43 u32 channel = 0; // Normally more complicated but we're only worried
44 // about the first micro-tile
45 u32 bank = 0; // Same as channel.
46 u32 sample_slice_rotation = 0; // sample_slice = 0 so it's fixed
47
48 switch (pSurf->tileMode)
49 {
50 // 3D/3B Thick rotate channels and banks every 4 slices
51 case GX2_TILE_MODE_3D_TILED_THICK:
52 case GX2_TILE_MODE_3B_TILED_THICK:
53 bank_slice_rotation = GX2Max(1, (num_channels/2)-1) * (slice / 4) / num_channels;
54 channel_slice_rotation = GX2Max(1, (num_channels/2)-1) * (slice / 4);
55 break;
56
57 // 3D/3B Thin rotate bank/channel every slice
58 case GX2_TILE_MODE_3D_TILED_THIN1:
59 case GX2_TILE_MODE_3B_TILED_THIN1:
60 bank_slice_rotation = GX2Max(1, (num_channels/2)-1) * slice / num_channels;
61 channel_slice_rotation = GX2Max(1, (num_channels/2)-1) * slice;
62 break;
63
64 // 2D/2B Thick rotate only banks every 4 slices
65 case GX2_TILE_MODE_2D_TILED_THICK:
66 case GX2_TILE_MODE_2B_TILED_THICK:
67 bank_slice_rotation = (((num_banks / 2) - 1) * (slice / 4));
68 break;
69
70 default: // All 2B/2D Thin Formats (rotate bank every slice)
71 // Good
72 bank_slice_rotation = (((num_banks / 2) - 1) * slice);
73 break;
74 }
75
76 bank ^= (bank_swizzle + bank_slice_rotation) & (num_banks - 1);
77 bank ^= sample_slice_rotation;
78 //bank ^= bank_swap_rotation; // This is 0 since we're always at macro
79 // tile (0, 0)
80 channel ^= (channel_swizzle + channel_slice_rotation) & (num_channels - 1);
81
82 swizzle = channel | (bank << 1);
83
84 return swizzle;
85 }
86
87 // Function to select the tiling mode depending on the mipmap level
GX2UTGetSurfaceMipSliceTileMode(const GX2Surface * pSurf,u32 mipLevel)88 GX2TileMode GX2UTGetSurfaceMipSliceTileMode(const GX2Surface* pSurf, u32 mipLevel)
89 {
90 ASSERT(pSurf);
91 ASSERT(mipLevel < pSurf->numMips);
92
93 // Small mipmaps change tiling mode to save memory.
94 if ( ((pSurf->swizzle >> 16) & 0xFF) <= mipLevel )
95 {
96 switch (pSurf->tileMode)
97 {
98 case GX2_TILE_MODE_LINEAR_ALIGNED:
99 return GX2_TILE_MODE_LINEAR_ALIGNED;
100
101 case GX2_TILE_MODE_1D_TILED_THIN1:
102 return GX2_TILE_MODE_1D_TILED_THIN1;
103
104 case GX2_TILE_MODE_1D_TILED_THICK:
105 if (pSurf->dim == GX2_SURFACE_DIM_3D)
106 return GX2_TILE_MODE_1D_TILED_THIN1;
107 else
108 return GX2_TILE_MODE_1D_TILED_THICK;
109
110 case GX2_TILE_MODE_2D_TILED_THIN1:
111 case GX2_TILE_MODE_2D_TILED_THIN2:
112 case GX2_TILE_MODE_2D_TILED_THIN4:
113 case GX2_TILE_MODE_2B_TILED_THIN1:
114 case GX2_TILE_MODE_2B_TILED_THIN2:
115 case GX2_TILE_MODE_2B_TILED_THIN4:
116 case GX2_TILE_MODE_3D_TILED_THIN1:
117 case GX2_TILE_MODE_3B_TILED_THIN1:
118 return GX2_TILE_MODE_1D_TILED_THIN1;
119
120 case GX2_TILE_MODE_2D_TILED_THICK:
121 case GX2_TILE_MODE_2B_TILED_THICK:
122 case GX2_TILE_MODE_3D_TILED_THICK:
123 case GX2_TILE_MODE_3B_TILED_THICK:
124 if (pSurf->dim == GX2_SURFACE_DIM_3D)
125 return GX2_TILE_MODE_1D_TILED_THIN1;
126 else
127 return GX2_TILE_MODE_1D_TILED_THICK;
128 }
129 }
130 else if (pSurf->dim == GX2_SURFACE_DIM_3D)
131 {
132 // For Thick tiling modes, the HW will switch to thin
133 // tiling once the depth decreases below 4 to conserve space
134 switch (pSurf->tileMode)
135 {
136 case GX2_TILE_MODE_2D_TILED_THICK:
137 if ( pSurf->depth >> mipLevel < 4 )
138 return GX2_TILE_MODE_2D_TILED_THIN1;
139 break;
140 case GX2_TILE_MODE_2B_TILED_THICK:
141 if ( pSurf->depth >> mipLevel < 4 )
142 return GX2_TILE_MODE_2B_TILED_THIN1;
143 break;
144 case GX2_TILE_MODE_3D_TILED_THICK:
145 if ( pSurf->depth >> mipLevel < 4 )
146 return GX2_TILE_MODE_3D_TILED_THIN1;
147 break;
148 case GX2_TILE_MODE_3B_TILED_THICK:
149 if ( pSurf->depth >> mipLevel < 4 )
150 return GX2_TILE_MODE_3B_TILED_THIN1;
151 break;
152 }
153 }
154
155 // Default to using the same tiling mode
156 return pSurf->tileMode;
157 }
158
GX2UTGetSurfaceMipSize(const GX2Surface * pSurf,u32 mipLevel)159 u32 GX2UTGetSurfaceMipSize(const GX2Surface* pSurf, u32 mipLevel)
160 {
161 u32 size;
162
163 ASSERT(pSurf);
164 ASSERT(mipLevel < pSurf->numMips);
165
166 switch (mipLevel)
167 {
168 case 0:
169 size = pSurf->imageSize;
170 break;
171 case 1:
172 size = pSurf->mipOffset[1];
173 break;
174 default:
175 if ( mipLevel == pSurf->numMips - 1)
176 {
177 size = pSurf->mipSize - pSurf->mipOffset[mipLevel - 1];
178 }
179 else
180 {
181 size = pSurf->mipOffset[mipLevel] - pSurf->mipOffset[mipLevel-1];
182 }
183 break;
184 }
185
186 return size;
187 }
188
GX2UTGetSurfaceMipSlicePtr(const GX2Surface * pSurf,u32 mipLevel,u32 slice)189 void* GX2UTGetSurfaceMipSlicePtr(const GX2Surface* pSurf, u32 mipLevel, u32 slice)
190 {
191 u8* ptr = NULL;
192
193 ASSERT(pSurf);
194 ASSERT(mipLevel < pSurf->numMips);
195 ASSERT(slice < pSurf->depth);
196
197 switch (mipLevel)
198 {
199 case 0:
200 ptr = (u8*)pSurf->imagePtr;
201 break;
202 case 1:
203 ptr = (u8*)pSurf->mipPtr;
204 break;
205 default:
206 ptr = (u8*)pSurf->mipPtr + pSurf->mipOffset[mipLevel-1];
207 break;
208 }
209
210 // Offset to the start of the slice
211 if ( slice )
212 {
213 u32 levelSize = GX2UTGetSurfaceMipSize(pSurf, mipLevel);
214 u32 depth = pSurf->depth;
215
216 // All mipLevels > 0 round the depth to the nearest power of
217 // 2 when determining the size. This is a HW limitation.
218 if ( mipLevel && (((depth - 1) & depth) != 0) )
219 {
220 depth = GX2UTRoundNearestPow2(depth);
221 }
222 ptr += levelSize * slice / depth;
223 }
224
225 return (void*)ptr;
226 }
227
228
GX2UTSetCommonState()229 void GX2UTSetCommonState()
230 {
231 GX2UTDebugTagIndent(__func__);
232
233 GX2SetShaderMode(GX2_SHADER_MODE_UNIFORM_REGISTER);
234
235 // Set polygon Control Register
236 GX2SetPolygonControl(GX2_FRONT_FACE_CCW, // frontFaceMode
237 GX2_DISABLE, // cullBack
238 GX2_DISABLE, // cullFront
239 GX2_DISABLE, // enablePolygonModes
240 GX2_POLYGON_MODE_TRIANGLE,// polygonModeFront
241 GX2_POLYGON_MODE_TRIANGLE,// polygonModeBack
242 GX2_DISABLE, // polyOffsetFrontEnable
243 GX2_DISABLE, // polyOffsetBackEnable
244 GX2_DISABLE); // pointLineOffsetEnable
245
246 GX2SetPrimitiveRestartIndex(0xffffffff);
247
248 // Set Alpha Test Values
249 GX2SetAlphaTest(GX2_DISABLE, GX2_COMPARE_LESS, 0.0f);
250
251 GX2SetAlphaToMask(GX2_FALSE, GX2_ALPHA_TO_MASK_0);
252
253 GX2SetTargetChannelMasks(
254 GX2_CHANNEL_MASK_RGBA,
255 GX2_CHANNEL_MASK_RGBA,
256 GX2_CHANNEL_MASK_RGBA,
257 GX2_CHANNEL_MASK_RGBA,
258 GX2_CHANNEL_MASK_RGBA,
259 GX2_CHANNEL_MASK_RGBA,
260 GX2_CHANNEL_MASK_RGBA,
261 GX2_CHANNEL_MASK_RGBA);
262
263
264 // Disable Stream out
265 GX2SetStreamOutEnable(GX2_FALSE);
266
267 // Enable the Rasterizer and clipping
268 GX2SetRasterizerClipControl(GX2_ENABLE, GX2_ENABLE);
269
270 // Setup Tessellation
271 GX2SetTessellation(GX2_TESSELLATION_MODE_DISCRETE,
272 GX2_PRIMITIVE_TESSELLATE_TRIANGLES,
273 GX2_INDEX_FORMAT_U32);
274 GX2SetMaxTessellationLevel(1.0f);
275 GX2SetMinTessellationLevel(1.0f);
276
277 GX2UTDebugTagUndent();
278 }
279
GX2UTIsTileModeThick(const GX2Surface * pSurf)280 GX2Boolean GX2UTIsTileModeThick(const GX2Surface* pSurf)
281 {
282 switch (pSurf->tileMode)
283 {
284 case GX2_TILE_MODE_2D_TILED_THICK:
285 case GX2_TILE_MODE_2B_TILED_THICK:
286 case GX2_TILE_MODE_3D_TILED_THICK:
287 case GX2_TILE_MODE_3B_TILED_THICK:
288 return GX2_TRUE;
289 }
290
291 return GX2_FALSE;
292 }
293
294