1/* 2 * Copyright (c) 2011 Intel Corporation 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 24#include <stdlib.h> 25#include <math.h> 26 27#include "util/macros.h" 28#include "main/macros.h" 29#include "compiler/shader_enums.h" 30 31#include "gen_l3_config.h" 32 33/** 34 * The following diagram shows how we partition the URB: 35 * 36 * 16kb or 32kb Rest of the URB space 37 * __________-__________ _________________-_________________ 38 * / \ / \ 39 * +-------------------------------------------------------------+ 40 * | VS/HS/DS/GS/FS Push | VS/HS/DS/GS URB | 41 * | Constants | Entries | 42 * +-------------------------------------------------------------+ 43 * 44 * Push constants must be stored at the beginning of the URB space, 45 * while URB entries can be stored anywhere. We choose to lay them 46 * out in pipeline order (VS -> HS -> DS -> GS). 47 */ 48 49/** 50 * Decide how to partition the URB among the various stages. 51 * 52 * \param[in] push_constant_bytes - space allocate for push constants. 53 * \param[in] urb_size_bytes - total size of the URB (from L3 config). 54 * \param[in] tess_present - are tessellation shaders active? 55 * \param[in] gs_present - are geometry shaders active? 56 * \param[in] entry_size - the URB entry size (from the shader compiler) 57 * \param[out] entries - the number of URB entries for each stage 58 * \param[out] start - the starting offset for each stage 59 */ 60void 61gen_get_urb_config(const struct gen_device_info *devinfo, 62 unsigned push_constant_bytes, unsigned urb_size_bytes, 63 bool tess_present, bool gs_present, 64 const unsigned entry_size[4], 65 unsigned entries[4], unsigned start[4]) 66{ 67 const bool active[4] = { true, tess_present, tess_present, gs_present }; 68 69 /* URB allocations must be done in 8k chunks. */ 70 const unsigned chunk_size_bytes = 8192; 71 72 const unsigned push_constant_chunks = 73 push_constant_bytes / chunk_size_bytes; 74 const unsigned urb_chunks = urb_size_bytes / chunk_size_bytes; 75 76 /* From p35 of the Ivy Bridge PRM (section 1.7.1: 3DSTATE_URB_GS): 77 * 78 * VS Number of URB Entries must be divisible by 8 if the VS URB Entry 79 * Allocation Size is less than 9 512-bit URB entries. 80 * 81 * Similar text exists for HS, DS and GS. 82 */ 83 unsigned granularity[4]; 84 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 85 granularity[i] = (entry_size[i] < 9) ? 8 : 1; 86 } 87 88 unsigned min_entries[4] = { 89 /* VS has a lower limit on the number of URB entries. 90 * 91 * From the Broadwell PRM, 3DSTATE_URB_VS instruction: 92 * "When tessellation is enabled, the VS Number of URB Entries must be 93 * greater than or equal to 192." 94 */ 95 [MESA_SHADER_VERTEX] = tess_present && devinfo->gen == 8 ? 96 192 : devinfo->urb.min_entries[MESA_SHADER_VERTEX], 97 98 /* There are two constraints on the minimum amount of URB space we can 99 * allocate: 100 * 101 * (1) We need room for at least 2 URB entries, since we always operate 102 * the GS in DUAL_OBJECT mode. 103 * 104 * (2) We can't allocate less than nr_gs_entries_granularity. 105 */ 106 [MESA_SHADER_GEOMETRY] = gs_present ? 2 : 0, 107 108 [MESA_SHADER_TESS_CTRL] = tess_present ? 1 : 0, 109 110 [MESA_SHADER_TESS_EVAL] = tess_present ? 111 devinfo->urb.min_entries[MESA_SHADER_TESS_EVAL] : 0, 112 }; 113 114 /* Min VS Entries isn't a multiple of 8 on Cherryview/Broxton; round up. 115 * Round them all up. 116 */ 117 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 118 min_entries[i] = ALIGN(min_entries[i], granularity[i]); 119 } 120 121 unsigned entry_size_bytes[4]; 122 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 123 entry_size_bytes[i] = 64 * entry_size[i]; 124 } 125 126 /* Initially, assign each stage the minimum amount of URB space it needs, 127 * and make a note of how much additional space it "wants" (the amount of 128 * additional space it could actually make use of). 129 */ 130 unsigned chunks[4]; 131 unsigned wants[4]; 132 unsigned total_needs = push_constant_chunks; 133 unsigned total_wants = 0; 134 135 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 136 if (active[i]) { 137 chunks[i] = DIV_ROUND_UP(min_entries[i] * entry_size_bytes[i], 138 chunk_size_bytes); 139 140 wants[i] = 141 DIV_ROUND_UP(devinfo->urb.max_entries[i] * entry_size_bytes[i], 142 chunk_size_bytes) - chunks[i]; 143 } else { 144 chunks[i] = 0; 145 wants[i] = 0; 146 } 147 148 total_needs += chunks[i]; 149 total_wants += wants[i]; 150 } 151 152 assert(total_needs <= urb_chunks); 153 154 /* Mete out remaining space (if any) in proportion to "wants". */ 155 unsigned remaining_space = MIN2(urb_chunks - total_needs, total_wants); 156 157 if (remaining_space > 0) { 158 for (int i = MESA_SHADER_VERTEX; 159 total_wants > 0 && i <= MESA_SHADER_TESS_EVAL; i++) { 160 unsigned additional = (unsigned) 161 roundf(wants[i] * (((float) remaining_space) / total_wants)); 162 chunks[i] += additional; 163 remaining_space -= additional; 164 total_wants -= wants[i]; 165 } 166 167 chunks[MESA_SHADER_GEOMETRY] += remaining_space; 168 } 169 170 /* Sanity check that we haven't over-allocated. */ 171 unsigned total_chunks = push_constant_chunks; 172 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 173 total_chunks += chunks[i]; 174 } 175 assert(total_chunks <= urb_chunks); 176 177 /* Finally, compute the number of entries that can fit in the space 178 * allocated to each stage. 179 */ 180 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 181 entries[i] = chunks[i] * chunk_size_bytes / entry_size_bytes[i]; 182 183 /* Since we rounded up when computing wants[], this may be slightly 184 * more than the maximum allowed amount, so correct for that. 185 */ 186 entries[i] = MIN2(entries[i], devinfo->urb.max_entries[i]); 187 188 /* Ensure that we program a multiple of the granularity. */ 189 entries[i] = ROUND_DOWN_TO(entries[i], granularity[i]); 190 191 /* Finally, sanity check to make sure we have at least the minimum 192 * number of entries needed for each stage. 193 */ 194 assert(entries[i] >= min_entries[i]); 195 } 196 197 /* Lay out the URB in pipeline order: push constants, VS, HS, DS, GS. */ 198 int next = push_constant_chunks; 199 for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) { 200 if (entries[i]) { 201 start[i] = next; 202 next += chunks[i]; 203 } else { 204 /* Just put disabled stages at the beginning. */ 205 start[i] = 0; 206 } 207 } 208} 209