1 // =============================================================================
2 // === GPUQREngine/Source/BucketList_FillWorkQueue.cpp =========================
3 // =============================================================================
4 //
5 // FillWorkQueue is responsible for filling the work queue with items and
6 // resolving generic TaskType entries on the bundles into concrete tasks
7 // to be performed by the GPU.
8 //
9 // This function should not be called for a particular front if we are at
10 // risk of exceeding the work queue.  The caller is responsible for this.
11 // The maximum number of tasks that can be placed in the queue is equal
12 // to (# row tiles) * (# col tiles) / applyGranularity, for any one front.
13 //
14 // =============================================================================
15 
16 #include "GPUQREngine_BucketList.hpp"
17 
18 
19 // FillWorkQueue is responsible for filling the work queue with items and
20 // resolving generic TaskType entries on the bundles into concrete tasks
21 // to be performed by the GPU.
FillWorkQueue(TaskDescriptor * queue,Int * queueIndex)22 Int BucketList::FillWorkQueue
23 (
24     TaskDescriptor *queue,  // The list of work items for the GPU
25     Int *queueIndex         // The current index into the queue
26 )
27 {
28     // Copy-in the current index
29     Int qindex = *queueIndex;
30 
31     // Create and typecast object members to local variables.
32     int fm          = (int) front->fm;
33     int fn          = (int) front->fn;
34     int numColTiles = (int) this->numColTiles;
35 
36     // For all bundles the bucket list is currently tracking:
37     for (int i = 0; i < numBundles; i++)
38     {
39         LLBundle& bundle = Bundles[i];
40         TaskType type = bundle.CurrentTask;
41         int nativeBucket = (int) bundle.NativeBucket;
42 
43         // Configure for block task construction.
44         int start = nativeBucket;
45 
46         // If the task type is a factorize:
47         switch(type)
48         {
49             case TASKTYPE_GenericFactorize:
50             {
51                 // General task configuration.
52                 TaskDescriptor task;
53                 bundle.gpuPack(&task);
54                 task.F = gpuF;
55                 task.fn = fn;
56                 task.fm = fm;
57 
58                 // Set launch characteristics.
59                 int vtOwner = nativeBucket;
60                 task.extra[4] = TILESIZE * vtOwner;
61 
62                 // Resolve the generic type to a specific type.
63 
64                 // See if we need to consider edge cases.
65                 int lastColumn = (TILESIZE * vtOwner) + 31;
66                 bool isInternal = IsInternal(bundle, lastColumn);
67 
68                 switch(bundle.Count)
69                 {
70                     case 3:
71                         task.Type = (isInternal ? TASKTYPE_FactorizeVT_3x1
72                                                 : TASKTYPE_FactorizeVT_3x1e);
73                         break;
74                     case 2:
75                         task.Type = (isInternal ? TASKTYPE_FactorizeVT_2x1
76                                                 : TASKTYPE_FactorizeVT_2x1e);
77                         break;
78                     case 1:
79                         task.Type = (isInternal ? TASKTYPE_FactorizeVT_1x1
80                                                 : TASKTYPE_FactorizeVT_1x1e);
81                         break;
82                 }
83 
84                 // Add the task to the queue.
85                 queue[qindex++] = task;
86 
87                 break;
88             }
89 
90             #ifdef GPUQRENGINE_PIPELINING
91             case TASKTYPE_GenericApplyFactorize:
92             {
93                 // General task configuration.
94                 TaskDescriptor task;
95                 bundle.gpuPack(&task);
96                 task.F = gpuF;
97                 task.fn = fn;
98                 task.fm = fm;
99 
100                 // Set launch characteristics.
101                 int vtOwner = nativeBucket - 1;
102                 int from    = nativeBucket;
103                 int to      = MIN(nativeBucket + 1, numColTiles);
104                 task.extra[4] = TILESIZE * vtOwner;
105                 task.extra[5] = TILESIZE * from;
106                 task.extra[6] = TILESIZE * to;
107 
108                 // Resolve the generic type to a specific type.
109                 int factorizeCount = bundle.Count;
110                 switch(bundle.ApplyCount)
111                 {
112                     case 3:
113                         switch(factorizeCount)
114                         {
115                             case 3:
116                                 task.Type = TASKTYPE_Apply3_Factorize3;
117                                 break;
118                             case 2:
119                                 task.Type = TASKTYPE_Apply3_Factorize2;
120                                 break;
121                             // case 1: never happens
122                         }
123                         break;
124                     case 2:
125                         switch(factorizeCount)
126                         {
127                             case 3:
128                                 task.Type = TASKTYPE_Apply2_Factorize3;
129                                 break;
130                             case 2:
131                                 task.Type = TASKTYPE_Apply2_Factorize2;
132                                 break;
133                             case 1:
134                                 task.Type = TASKTYPE_Apply2_Factorize1;
135                                 break;
136                         }
137                         break;
138                     // case 1: never happens.  We never have an apply-factorize
139                     // with one tile. A one-tile apply is considered a phantom
140                     // bundle. We avoid the bogus rearrange.
141                 }
142 
143                 // Add the task to the queue.
144                 queue[qindex++] = task;
145 
146                 // Configure parameters to build the rest of the applies.
147                 start++;
148                 type = TASKTYPE_GenericApply;
149 
150                 // INTENTIONALLY FALL THROUGH TO BUILD THE APPLIES
151             }
152             #endif
153 
154             case TASKTYPE_GenericApply:
155             {
156                 for( ; start < numBuckets; start += ApplyGranularity)
157                 {
158                     // General task configuration.
159                     TaskDescriptor task;
160                     bundle.gpuPack(&task);
161                     task.F = gpuF;
162                     task.fn = fn;
163                     task.fm = fm;
164 
165                     // Set launch characteristics.
166                     int vtOwner = nativeBucket - 1;
167                     int from    = start;
168                     int to      = MIN(start + ApplyGranularity, numColTiles);
169                     task.extra[4] = TILESIZE * vtOwner;
170                     task.extra[5] = TILESIZE * from;
171                     task.extra[6] = TILESIZE * to;
172 
173                     // Resolve the generic type to a specific type.
174                     switch(bundle.ApplyCount)
175                     {
176                         case 3: task.Type = TASKTYPE_Apply3; break;
177                         case 2: task.Type = TASKTYPE_Apply2; break;
178                         case 1: task.Type = TASKTYPE_Apply1; break;
179                     }
180 
181                     // Add the task to the queue.
182                     queue[qindex++] = task;
183                 }
184 
185                 break;
186             }
187             default: break; // DEAD: no default case is ever used.
188         }
189     }
190 
191     // Compute the number of tasks we just built.
192     Int numTasks = qindex - *queueIndex;
193 
194     // Copy-out the current index
195     *queueIndex = qindex;
196 
197     return numTasks;
198 }
199