swr/rasterizer: enable size accumulation in mem stats
[mesa.git] / src / gallium / drivers / swr / rasterizer / jitter / builder_gfx_mem.cpp
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 builder_gfx_mem.cpp
24 *
25 * @brief Definition of the gfx mem builder
26 *
27 * Notes:
28 *
29 ******************************************************************************/
30 #include "jit_pch.hpp"
31 #include "builder.h"
32 #include "common/rdtsc_buckets.h"
33 #include "builder_gfx_mem.h"
34
35 namespace SwrJit
36 {
37 using namespace llvm;
38
39 BuilderGfxMem::BuilderGfxMem(JitManager* pJitMgr) : Builder(pJitMgr)
40 {
41 mpTranslationFuncTy = nullptr;
42 mpfnTranslateGfxAddressForRead = nullptr;
43 mpfnTranslateGfxAddressForWrite = nullptr;
44 mpfnTrackMemAccess = nullptr;
45 mpParamSimDC = nullptr;
46 mpWorkerData = nullptr;
47 }
48
49 void BuilderGfxMem::NotifyPrivateContextSet()
50 {
51 }
52
53 void BuilderGfxMem::AssertGFXMemoryParams(Value* ptr, MEM_CLIENT usage)
54 {
55 SWR_ASSERT(!(ptr->getType() == mInt64Ty && usage == MEM_CLIENT::MEM_CLIENT_INTERNAL),
56 "Internal memory should not be gfxptr_t.");
57 }
58
59 //////////////////////////////////////////////////////////////////////////
60 /// @brief Generate a masked gather operation in LLVM IR. If not
61 /// supported on the underlying platform, emulate it with loads
62 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
63 /// @param pBase - Int8* base VB address pointer value
64 /// @param vIndices - SIMD wide value of VB byte offsets
65 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
66 /// @param scale - value to scale indices by
67 Value* BuilderGfxMem::GATHERPS(Value* vSrc,
68 Value* pBase,
69 Value* vIndices,
70 Value* vMask,
71 uint8_t scale,
72 MEM_CLIENT usage)
73 {
74 // address may be coming in as 64bit int now so get the pointer
75 if (pBase->getType() == mInt64Ty)
76 {
77 pBase = INT_TO_PTR(pBase, PointerType::get(mInt8Ty, 0));
78 }
79
80 Value* vGather = Builder::GATHERPS(vSrc, pBase, vIndices, vMask, scale);
81 return vGather;
82 }
83
84 //////////////////////////////////////////////////////////////////////////
85 /// @brief Generate a masked gather operation in LLVM IR. If not
86 /// supported on the underlying platform, emulate it with loads
87 /// @param vSrc - SIMD wide value that will be loaded if mask is invalid
88 /// @param pBase - Int8* base VB address pointer value
89 /// @param vIndices - SIMD wide value of VB byte offsets
90 /// @param vMask - SIMD wide mask that controls whether to access memory or the src values
91 /// @param scale - value to scale indices by
92 Value* BuilderGfxMem::GATHERDD(Value* vSrc,
93 Value* pBase,
94 Value* vIndices,
95 Value* vMask,
96 uint8_t scale,
97 MEM_CLIENT usage)
98 {
99 // address may be coming in as 64bit int now so get the pointer
100 if (pBase->getType() == mInt64Ty)
101 {
102 pBase = INT_TO_PTR(pBase, PointerType::get(mInt8Ty, 0));
103 }
104
105 Value* vGather = Builder::GATHERDD(vSrc, pBase, vIndices, vMask, scale);
106 return vGather;
107 }
108
109 void BuilderGfxMem::SCATTERPS(
110 Value* pDst, Value* vSrc, Value* vOffsets, Value* vMask, MEM_CLIENT usage)
111 {
112 // address may be coming in as 64bit int now so get the pointer
113 if (pDst->getType() == mInt64Ty)
114 {
115 pDst = INT_TO_PTR(pDst, PointerType::get(mInt8Ty, 0));
116 }
117
118 Builder::SCATTERPS(pDst, BITCAST(vSrc, mSimdFP32Ty), vOffsets, vMask, usage);
119 }
120
121 Value* BuilderGfxMem::OFFSET_TO_NEXT_COMPONENT(Value* base, Constant* offset)
122 {
123 return ADD(base, offset);
124 }
125
126 Value* BuilderGfxMem::GEP(Value* Ptr, Value* Idx, Type* Ty, const Twine& Name)
127 {
128 Ptr = TranslationHelper(Ptr, Ty);
129 return Builder::GEP(Ptr, Idx, nullptr, Name);
130 }
131
132 Value* BuilderGfxMem::GEP(Type* Ty, Value* Ptr, Value* Idx, const Twine& Name)
133 {
134 Ptr = TranslationHelper(Ptr, Ty);
135 return Builder::GEP(Ty, Ptr, Idx, Name);
136 }
137
138 Value* BuilderGfxMem::GEP(Value* Ptr, const std::initializer_list<Value*>& indexList, Type* Ty)
139 {
140 Ptr = TranslationHelper(Ptr, Ty);
141 return Builder::GEP(Ptr, indexList);
142 }
143
144 Value*
145 BuilderGfxMem::GEP(Value* Ptr, const std::initializer_list<uint32_t>& indexList, Type* Ty)
146 {
147 Ptr = TranslationHelper(Ptr, Ty);
148 return Builder::GEP(Ptr, indexList);
149 }
150
151 Value* BuilderGfxMem::TranslationHelper(Value* Ptr, Type* Ty)
152 {
153 SWR_ASSERT(!(Ptr->getType() == mInt64Ty && Ty == nullptr),
154 "Access of GFX pointers must have non-null type specified.");
155
156 // address may be coming in as 64bit int now so get the pointer
157 if (Ptr->getType() == mInt64Ty)
158 {
159 Ptr = INT_TO_PTR(Ptr, Ty);
160 }
161
162 return Ptr;
163 }
164
165 void BuilderGfxMem::TrackerHelper(Value* Ptr, Type* Ty, MEM_CLIENT usage, bool isRead)
166 {
167 #if defined(KNOB_ENABLE_AR)
168 if (!KNOB_TRACK_MEMORY_WORKING_SET)
169 {
170 return;
171 }
172
173 Value* tmpPtr;
174 // convert actual pointers to int64.
175 uint32_t size = 0;
176
177 if (Ptr->getType() == mInt64Ty)
178 {
179 DataLayout dataLayout(JM()->mpCurrentModule);
180 size = (uint32_t)dataLayout.getTypeAllocSize(Ty);
181
182 tmpPtr = Ptr;
183 }
184 else
185 {
186 DataLayout dataLayout(JM()->mpCurrentModule);
187 size = (uint32_t)dataLayout.getTypeAllocSize(Ptr->getType());
188
189 tmpPtr = PTR_TO_INT(Ptr, mInt64Ty);
190 }
191
192 // There are some shader compile setups where there's no translation functions set up.
193 // This would be a situation where the accesses are to internal rasterizer memory and won't
194 // be logged.
195 // TODO: we may wish to revisit this for URB reads/writes, though.
196 if (mpfnTrackMemAccess)
197 {
198 SWR_ASSERT(mpWorkerData != nullptr);
199 CALL(mpfnTrackMemAccess,
200 {mpParamSimDC,
201 mpWorkerData,
202 tmpPtr,
203 C((uint32_t)size),
204 C((uint8_t)isRead),
205 C((uint32_t)usage)});
206 }
207 #endif
208
209 return;
210 }
211
212 LoadInst* BuilderGfxMem::LOAD(Value* Ptr, const char* Name, Type* Ty, MEM_CLIENT usage)
213 {
214 AssertGFXMemoryParams(Ptr, usage);
215 TrackerHelper(Ptr, Ty, usage, true);
216
217 Ptr = TranslationHelper(Ptr, Ty);
218 return Builder::LOAD(Ptr, Name);
219 }
220
221 LoadInst* BuilderGfxMem::LOAD(Value* Ptr, const Twine& Name, Type* Ty, MEM_CLIENT usage)
222 {
223 AssertGFXMemoryParams(Ptr, usage);
224 TrackerHelper(Ptr, Ty, usage, true);
225
226 Ptr = TranslationHelper(Ptr, Ty);
227 return Builder::LOAD(Ptr, Name);
228 }
229
230 LoadInst* BuilderGfxMem::LOAD(
231 Value* Ptr, bool isVolatile, const Twine& Name, Type* Ty, MEM_CLIENT usage)
232 {
233 AssertGFXMemoryParams(Ptr, usage);
234 TrackerHelper(Ptr, Ty, usage, true);
235
236 Ptr = TranslationHelper(Ptr, Ty);
237 return Builder::LOAD(Ptr, isVolatile, Name);
238 }
239
240 LoadInst* BuilderGfxMem::LOAD(Value* BasePtr,
241 const std::initializer_list<uint32_t>& offset,
242 const llvm::Twine& name,
243 Type* Ty,
244 MEM_CLIENT usage)
245 {
246 AssertGFXMemoryParams(BasePtr, usage);
247
248 bool bNeedTranslation = false;
249 if (BasePtr->getType() == mInt64Ty)
250 {
251 SWR_ASSERT(Ty);
252 BasePtr = INT_TO_PTR(BasePtr, Ty, name);
253 bNeedTranslation = true;
254 }
255 std::vector<Value*> valIndices;
256 for (auto i : offset)
257 {
258 valIndices.push_back(C(i));
259 }
260 BasePtr = Builder::GEPA(BasePtr, valIndices, name);
261 if (bNeedTranslation)
262 {
263 BasePtr = PTR_TO_INT(BasePtr, mInt64Ty, name);
264 }
265
266 return LOAD(BasePtr, name, Ty, usage);
267 }
268
269 CallInst* BuilderGfxMem::MASKED_LOAD(Value* Ptr,
270 unsigned Align,
271 Value* Mask,
272 Value* PassThru,
273 const Twine& Name,
274 Type* Ty,
275 MEM_CLIENT usage)
276 {
277 AssertGFXMemoryParams(Ptr, usage);
278 TrackerHelper(Ptr, Ty, usage, true);
279
280 Ptr = TranslationHelper(Ptr, Ty);
281 return Builder::MASKED_LOAD(Ptr, Align, Mask, PassThru, Name, Ty, usage);
282 }
283
284 StoreInst*
285 BuilderGfxMem::STORE(Value* Val, Value* Ptr, bool isVolatile, Type* Ty, MEM_CLIENT usage)
286 {
287 AssertGFXMemoryParams(Ptr, usage);
288 TrackerHelper(Ptr, Ty, usage, false);
289
290 Ptr = TranslationHelper(Ptr, Ty);
291 return Builder::STORE(Val, Ptr, isVolatile, Ty, usage);
292 }
293
294 StoreInst* BuilderGfxMem::STORE(Value* Val,
295 Value* BasePtr,
296 const std::initializer_list<uint32_t>& offset,
297 Type* Ty,
298 MEM_CLIENT usage)
299 {
300 AssertGFXMemoryParams(BasePtr, usage);
301 TrackerHelper(BasePtr, Ty, usage, false);
302
303 BasePtr = TranslationHelper(BasePtr, Ty);
304 return Builder::STORE(Val, BasePtr, offset, Ty, usage);
305 }
306
307 CallInst* BuilderGfxMem::MASKED_STORE(
308 Value* Val, Value* Ptr, unsigned Align, Value* Mask, Type* Ty, MEM_CLIENT usage)
309 {
310 AssertGFXMemoryParams(Ptr, usage);
311
312 TrackerHelper(Ptr, Ty, usage, false);
313
314 Ptr = TranslationHelper(Ptr, Ty);
315 return Builder::MASKED_STORE(Val, Ptr, Align, Mask, Ty, usage);
316 }
317
318 Value* BuilderGfxMem::TranslateGfxAddressForRead(Value* xpGfxAddress,
319 Type* PtrTy,
320 const Twine& Name,
321 MEM_CLIENT /* usage */)
322 {
323 if (PtrTy == nullptr)
324 {
325 PtrTy = mInt8PtrTy;
326 }
327 return INT_TO_PTR(xpGfxAddress, PtrTy, Name);
328 }
329
330 Value* BuilderGfxMem::TranslateGfxAddressForWrite(Value* xpGfxAddress,
331 Type* PtrTy,
332 const Twine& Name,
333 MEM_CLIENT /* usage */)
334 {
335 if (PtrTy == nullptr)
336 {
337 PtrTy = mInt8PtrTy;
338 }
339 return INT_TO_PTR(xpGfxAddress, PtrTy, Name);
340 }
341
342 } // namespace SwrJit