1 /* 2 * Copyright 2014-2015 Broadcom 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 "util/u_pack_color.h" 25 #include "util/format_srgb.h" 26 27 #include "vc4_context.h" 28 #include "vc4_qir.h" 29 30 static void 31 write_texture_p0(struct vc4_job *job, 32 struct vc4_cl_out **uniforms, 33 struct vc4_texture_stateobj *texstate, 34 uint32_t unit) 35 { 36 struct vc4_sampler_view *sview = 37 vc4_sampler_view(texstate->textures[unit]); 38 struct vc4_resource *rsc = vc4_resource(sview->texture); 39 40 cl_reloc(job, &job->uniforms, uniforms, rsc->bo, sview->texture_p0); 41 } 42 43 static void 44 write_texture_p1(struct vc4_job *job, 45 struct vc4_cl_out **uniforms, 46 struct vc4_texture_stateobj *texstate, 47 uint32_t unit) 48 { 49 struct vc4_sampler_view *sview = 50 vc4_sampler_view(texstate->textures[unit]); 51 struct vc4_sampler_state *sampler = 52 vc4_sampler_state(texstate->samplers[unit]); 53 54 cl_aligned_u32(uniforms, sview->texture_p1 | sampler->texture_p1); 55 } 56 57 static void 58 write_texture_p2(struct vc4_job *job, 59 struct vc4_cl_out **uniforms, 60 struct vc4_texture_stateobj *texstate, 61 uint32_t data) 62 { 63 uint32_t unit = data & 0xffff; 64 struct pipe_sampler_view *texture = texstate->textures[unit]; 65 struct vc4_resource *rsc = vc4_resource(texture->texture); 66 67 cl_aligned_u32(uniforms, 68 VC4_SET_FIELD(VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE, 69 VC4_TEX_P2_PTYPE) | 70 VC4_SET_FIELD(rsc->cube_map_stride >> 12, VC4_TEX_P2_CMST) | 71 VC4_SET_FIELD((data >> 16) & 1, VC4_TEX_P2_BSLOD)); 72 } 73 74 static void 75 write_texture_first_level(struct vc4_job *job, 76 struct vc4_cl_out **uniforms, 77 struct vc4_texture_stateobj *texstate, 78 uint32_t data) 79 { 80 uint32_t unit = data & 0xffff; 81 struct pipe_sampler_view *texture = texstate->textures[unit]; 82 83 cl_aligned_f(uniforms, texture->u.tex.first_level); 84 } 85 86 static void 87 write_texture_msaa_addr(struct vc4_job *job, 88 struct vc4_cl_out **uniforms, 89 struct vc4_texture_stateobj *texstate, 90 uint32_t unit) 91 { 92 struct pipe_sampler_view *texture = texstate->textures[unit]; 93 struct vc4_resource *rsc = vc4_resource(texture->texture); 94 95 cl_aligned_reloc(job, &job->uniforms, uniforms, rsc->bo, 0); 96 } 97 98 99 #define SWIZ(x,y,z,w) { \ 100 PIPE_SWIZZLE_##x, \ 101 PIPE_SWIZZLE_##y, \ 102 PIPE_SWIZZLE_##z, \ 103 PIPE_SWIZZLE_##w \ 104 } 105 106 static void 107 write_texture_border_color(struct vc4_job *job, 108 struct vc4_cl_out **uniforms, 109 struct vc4_texture_stateobj *texstate, 110 uint32_t unit) 111 { 112 struct pipe_sampler_state *sampler = texstate->samplers[unit]; 113 struct pipe_sampler_view *texture = texstate->textures[unit]; 114 struct vc4_resource *rsc = vc4_resource(texture->texture); 115 union util_color uc; 116 117 const struct util_format_description *tex_format_desc = 118 util_format_description(texture->format); 119 120 float border_color[4]; 121 for (int i = 0; i < 4; i++) 122 border_color[i] = sampler->border_color.f[i]; 123 if (util_format_is_srgb(texture->format)) { 124 for (int i = 0; i < 3; i++) 125 border_color[i] = 126 util_format_linear_to_srgb_float(border_color[i]); 127 } 128 129 /* Turn the border color into the layout of channels that it would 130 * have when stored as texture contents. 131 */ 132 float storage_color[4]; 133 util_format_unswizzle_4f(storage_color, 134 border_color, 135 tex_format_desc->swizzle); 136 137 /* Now, pack so that when the vc4_format-sampled texture contents are 138 * replaced with our border color, the vc4_get_format_swizzle() 139 * swizzling will get the right channels. 140 */ 141 if (util_format_is_depth_or_stencil(texture->format)) { 142 uc.ui[0] = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, 143 sampler->border_color.f[0]) << 8; 144 } else { 145 switch (rsc->vc4_format) { 146 default: 147 case VC4_TEXTURE_TYPE_RGBA8888: 148 util_pack_color(storage_color, 149 PIPE_FORMAT_R8G8B8A8_UNORM, &uc); 150 break; 151 case VC4_TEXTURE_TYPE_RGBA4444: 152 case VC4_TEXTURE_TYPE_RGBA5551: 153 util_pack_color(storage_color, 154 PIPE_FORMAT_A8B8G8R8_UNORM, &uc); 155 break; 156 case VC4_TEXTURE_TYPE_RGB565: 157 util_pack_color(storage_color, 158 PIPE_FORMAT_B8G8R8A8_UNORM, &uc); 159 break; 160 case VC4_TEXTURE_TYPE_ALPHA: 161 uc.ui[0] = float_to_ubyte(storage_color[0]) << 24; 162 break; 163 case VC4_TEXTURE_TYPE_LUMALPHA: 164 uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) | 165 (float_to_ubyte(storage_color[0]) << 0)); 166 break; 167 } 168 } 169 170 cl_aligned_u32(uniforms, uc.ui[0]); 171 } 172 173 static uint32_t 174 get_texrect_scale(struct vc4_texture_stateobj *texstate, 175 enum quniform_contents contents, 176 uint32_t data) 177 { 178 struct pipe_sampler_view *texture = texstate->textures[data]; 179 uint32_t dim; 180 181 if (contents == QUNIFORM_TEXRECT_SCALE_X) 182 dim = texture->texture->width0; 183 else 184 dim = texture->texture->height0; 185 186 return fui(1.0f / dim); 187 } 188 189 static struct vc4_bo * 190 vc4_upload_ubo(struct vc4_context *vc4, 191 struct vc4_compiled_shader *shader, 192 const uint32_t *gallium_uniforms) 193 { 194 if (!shader->ubo_size) 195 return NULL; 196 197 struct vc4_bo *ubo = vc4_bo_alloc(vc4->screen, shader->ubo_size, "ubo"); 198 void *data = vc4_bo_map(ubo); 199 for (uint32_t i = 0; i < shader->num_ubo_ranges; i++) { 200 memcpy(data + shader->ubo_ranges[i].dst_offset, 201 ((const void *)gallium_uniforms + 202 shader->ubo_ranges[i].src_offset), 203 shader->ubo_ranges[i].size); 204 } 205 206 return ubo; 207 } 208 209 void 210 vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader, 211 struct vc4_constbuf_stateobj *cb, 212 struct vc4_texture_stateobj *texstate) 213 { 214 struct vc4_shader_uniform_info *uinfo = &shader->uniforms; 215 struct vc4_job *job = vc4->job; 216 const uint32_t *gallium_uniforms = cb->cb[0].user_buffer; 217 struct vc4_bo *ubo = vc4_upload_ubo(vc4, shader, gallium_uniforms); 218 219 cl_ensure_space(&job->uniforms, (uinfo->count + 220 uinfo->num_texture_samples) * 4); 221 222 struct vc4_cl_out *uniforms = 223 cl_start_shader_reloc(&job->uniforms, 224 uinfo->num_texture_samples); 225 226 for (int i = 0; i < uinfo->count; i++) { 227 228 switch (uinfo->contents[i]) { 229 case QUNIFORM_CONSTANT: 230 cl_aligned_u32(&uniforms, uinfo->data[i]); 231 break; 232 case QUNIFORM_UNIFORM: 233 cl_aligned_u32(&uniforms, 234 gallium_uniforms[uinfo->data[i]]); 235 break; 236 case QUNIFORM_VIEWPORT_X_SCALE: 237 cl_aligned_f(&uniforms, vc4->viewport.scale[0] * 16.0f); 238 break; 239 case QUNIFORM_VIEWPORT_Y_SCALE: 240 cl_aligned_f(&uniforms, vc4->viewport.scale[1] * 16.0f); 241 break; 242 243 case QUNIFORM_VIEWPORT_Z_OFFSET: 244 cl_aligned_f(&uniforms, vc4->viewport.translate[2]); 245 break; 246 case QUNIFORM_VIEWPORT_Z_SCALE: 247 cl_aligned_f(&uniforms, vc4->viewport.scale[2]); 248 break; 249 250 case QUNIFORM_USER_CLIP_PLANE: 251 cl_aligned_f(&uniforms, 252 vc4->clip.ucp[uinfo->data[i] / 4][uinfo->data[i] % 4]); 253 break; 254 255 case QUNIFORM_TEXTURE_CONFIG_P0: 256 write_texture_p0(job, &uniforms, texstate, 257 uinfo->data[i]); 258 break; 259 260 case QUNIFORM_TEXTURE_CONFIG_P1: 261 write_texture_p1(job, &uniforms, texstate, 262 uinfo->data[i]); 263 break; 264 265 case QUNIFORM_TEXTURE_CONFIG_P2: 266 write_texture_p2(job, &uniforms, texstate, 267 uinfo->data[i]); 268 break; 269 270 case QUNIFORM_TEXTURE_FIRST_LEVEL: 271 write_texture_first_level(job, &uniforms, texstate, 272 uinfo->data[i]); 273 break; 274 275 case QUNIFORM_UBO_ADDR: 276 cl_aligned_reloc(job, &job->uniforms, &uniforms, ubo, 0); 277 break; 278 279 case QUNIFORM_TEXTURE_MSAA_ADDR: 280 write_texture_msaa_addr(job, &uniforms, 281 texstate, uinfo->data[i]); 282 break; 283 284 case QUNIFORM_TEXTURE_BORDER_COLOR: 285 write_texture_border_color(job, &uniforms, 286 texstate, uinfo->data[i]); 287 break; 288 289 case QUNIFORM_TEXRECT_SCALE_X: 290 case QUNIFORM_TEXRECT_SCALE_Y: 291 cl_aligned_u32(&uniforms, 292 get_texrect_scale(texstate, 293 uinfo->contents[i], 294 uinfo->data[i])); 295 break; 296 297 case QUNIFORM_BLEND_CONST_COLOR_X: 298 case QUNIFORM_BLEND_CONST_COLOR_Y: 299 case QUNIFORM_BLEND_CONST_COLOR_Z: 300 case QUNIFORM_BLEND_CONST_COLOR_W: 301 cl_aligned_f(&uniforms, 302 CLAMP(vc4->blend_color.f.color[uinfo->contents[i] - 303 QUNIFORM_BLEND_CONST_COLOR_X], 304 0, 1)); 305 break; 306 307 case QUNIFORM_BLEND_CONST_COLOR_RGBA: { 308 const uint8_t *format_swiz = 309 vc4_get_format_swizzle(vc4->framebuffer.cbufs[0]->format); 310 uint32_t color = 0; 311 for (int i = 0; i < 4; i++) { 312 if (format_swiz[i] >= 4) 313 continue; 314 315 color |= (vc4->blend_color.ub[format_swiz[i]] << 316 (i * 8)); 317 } 318 cl_aligned_u32(&uniforms, color); 319 break; 320 } 321 322 case QUNIFORM_BLEND_CONST_COLOR_AAAA: { 323 uint8_t a = vc4->blend_color.ub[3]; 324 cl_aligned_u32(&uniforms, ((a) | 325 (a << 8) | 326 (a << 16) | 327 (a << 24))); 328 break; 329 } 330 331 case QUNIFORM_STENCIL: 332 cl_aligned_u32(&uniforms, 333 vc4->zsa->stencil_uniforms[uinfo->data[i]] | 334 (uinfo->data[i] <= 1 ? 335 (vc4->stencil_ref.ref_value[uinfo->data[i]] << 8) : 336 0)); 337 break; 338 339 case QUNIFORM_ALPHA_REF: 340 cl_aligned_f(&uniforms, 341 vc4->zsa->base.alpha.ref_value); 342 break; 343 344 case QUNIFORM_SAMPLE_MASK: 345 cl_aligned_u32(&uniforms, vc4->sample_mask); 346 break; 347 348 case QUNIFORM_UNIFORMS_ADDRESS: 349 /* This will be filled in by the kernel. */ 350 cl_aligned_u32(&uniforms, 0xd0d0d0d0); 351 break; 352 } 353 #if 0 354 uint32_t written_val = *((uint32_t *)uniforms - 1); 355 fprintf(stderr, "%p: %d / 0x%08x (%f)\n", 356 shader, i, written_val, uif(written_val)); 357 #endif 358 } 359 360 cl_end(&job->uniforms, uniforms); 361 362 vc4_bo_unreference(&ubo); 363 } 364 365 void 366 vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader) 367 { 368 uint32_t dirty = 0; 369 370 for (int i = 0; i < shader->uniforms.count; i++) { 371 switch (shader->uniforms.contents[i]) { 372 case QUNIFORM_CONSTANT: 373 case QUNIFORM_UNIFORMS_ADDRESS: 374 break; 375 case QUNIFORM_UNIFORM: 376 case QUNIFORM_UBO_ADDR: 377 dirty |= VC4_DIRTY_CONSTBUF; 378 break; 379 380 case QUNIFORM_VIEWPORT_X_SCALE: 381 case QUNIFORM_VIEWPORT_Y_SCALE: 382 case QUNIFORM_VIEWPORT_Z_OFFSET: 383 case QUNIFORM_VIEWPORT_Z_SCALE: 384 dirty |= VC4_DIRTY_VIEWPORT; 385 break; 386 387 case QUNIFORM_USER_CLIP_PLANE: 388 dirty |= VC4_DIRTY_CLIP; 389 break; 390 391 case QUNIFORM_TEXTURE_CONFIG_P0: 392 case QUNIFORM_TEXTURE_CONFIG_P1: 393 case QUNIFORM_TEXTURE_CONFIG_P2: 394 case QUNIFORM_TEXTURE_BORDER_COLOR: 395 case QUNIFORM_TEXTURE_FIRST_LEVEL: 396 case QUNIFORM_TEXTURE_MSAA_ADDR: 397 case QUNIFORM_TEXRECT_SCALE_X: 398 case QUNIFORM_TEXRECT_SCALE_Y: 399 /* We could flag this on just the stage we're 400 * compiling for, but it's not passed in. 401 */ 402 dirty |= VC4_DIRTY_FRAGTEX | VC4_DIRTY_VERTTEX; 403 break; 404 405 case QUNIFORM_BLEND_CONST_COLOR_X: 406 case QUNIFORM_BLEND_CONST_COLOR_Y: 407 case QUNIFORM_BLEND_CONST_COLOR_Z: 408 case QUNIFORM_BLEND_CONST_COLOR_W: 409 case QUNIFORM_BLEND_CONST_COLOR_RGBA: 410 case QUNIFORM_BLEND_CONST_COLOR_AAAA: 411 dirty |= VC4_DIRTY_BLEND_COLOR; 412 break; 413 414 case QUNIFORM_STENCIL: 415 case QUNIFORM_ALPHA_REF: 416 dirty |= VC4_DIRTY_ZSA; 417 break; 418 419 case QUNIFORM_SAMPLE_MASK: 420 dirty |= VC4_DIRTY_SAMPLE_MASK; 421 break; 422 } 423 } 424 425 shader->uniform_dirty_bits = dirty; 426 } 427