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