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 30static void 31write_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->base.texture); 39 40 cl_reloc(job, &job->uniforms, uniforms, rsc->bo, sview->texture_p0); 41} 42 43static void 44write_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 57static void 58write_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 74static void 75write_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 86static void 87write_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 106static void 107write_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 util_pack_color(storage_color, 153 PIPE_FORMAT_A8B8G8R8_UNORM, &uc); 154 break; 155 case VC4_TEXTURE_TYPE_RGB565: 156 util_pack_color(storage_color, 157 PIPE_FORMAT_B8G8R8A8_UNORM, &uc); 158 break; 159 case VC4_TEXTURE_TYPE_ALPHA: 160 uc.ui[0] = float_to_ubyte(storage_color[0]) << 24; 161 break; 162 case VC4_TEXTURE_TYPE_LUMALPHA: 163 uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) | 164 (float_to_ubyte(storage_color[0]) << 0)); 165 break; 166 } 167 } 168 169 cl_aligned_u32(uniforms, uc.ui[0]); 170} 171 172static uint32_t 173get_texrect_scale(struct vc4_texture_stateobj *texstate, 174 enum quniform_contents contents, 175 uint32_t data) 176{ 177 struct pipe_sampler_view *texture = texstate->textures[data]; 178 uint32_t dim; 179 180 if (contents == QUNIFORM_TEXRECT_SCALE_X) 181 dim = texture->texture->width0; 182 else 183 dim = texture->texture->height0; 184 185 return fui(1.0f / dim); 186} 187 188static struct vc4_bo * 189vc4_upload_ubo(struct vc4_context *vc4, 190 struct vc4_compiled_shader *shader, 191 const uint32_t *gallium_uniforms) 192{ 193 if (!shader->ubo_size) 194 return NULL; 195 196 struct vc4_bo *ubo = vc4_bo_alloc(vc4->screen, shader->ubo_size, "ubo"); 197 void *data = vc4_bo_map(ubo); 198 for (uint32_t i = 0; i < shader->num_ubo_ranges; i++) { 199 memcpy(data + shader->ubo_ranges[i].dst_offset, 200 ((const void *)gallium_uniforms + 201 shader->ubo_ranges[i].src_offset), 202 shader->ubo_ranges[i].size); 203 } 204 205 return ubo; 206} 207 208void 209vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader, 210 struct vc4_constbuf_stateobj *cb, 211 struct vc4_texture_stateobj *texstate) 212{ 213 struct vc4_shader_uniform_info *uinfo = &shader->uniforms; 214 struct vc4_job *job = vc4->job; 215 const uint32_t *gallium_uniforms = cb->cb[0].user_buffer; 216 struct vc4_bo *ubo = vc4_upload_ubo(vc4, shader, gallium_uniforms); 217 218 cl_ensure_space(&job->uniforms, (uinfo->count + 219 uinfo->num_texture_samples) * 4); 220 221 struct vc4_cl_out *uniforms = 222 cl_start_shader_reloc(&job->uniforms, 223 uinfo->num_texture_samples); 224 225 for (int i = 0; i < uinfo->count; i++) { 226 227 switch (uinfo->contents[i]) { 228 case QUNIFORM_CONSTANT: 229 cl_aligned_u32(&uniforms, uinfo->data[i]); 230 break; 231 case QUNIFORM_UNIFORM: 232 cl_aligned_u32(&uniforms, 233 gallium_uniforms[uinfo->data[i]]); 234 break; 235 case QUNIFORM_VIEWPORT_X_SCALE: 236 cl_aligned_f(&uniforms, vc4->viewport.scale[0] * 16.0f); 237 break; 238 case QUNIFORM_VIEWPORT_Y_SCALE: 239 cl_aligned_f(&uniforms, vc4->viewport.scale[1] * 16.0f); 240 break; 241 242 case QUNIFORM_VIEWPORT_Z_OFFSET: 243 cl_aligned_f(&uniforms, vc4->viewport.translate[2]); 244 break; 245 case QUNIFORM_VIEWPORT_Z_SCALE: 246 cl_aligned_f(&uniforms, vc4->viewport.scale[2]); 247 break; 248 249 case QUNIFORM_USER_CLIP_PLANE: 250 cl_aligned_f(&uniforms, 251 vc4->clip.ucp[uinfo->data[i] / 4][uinfo->data[i] % 4]); 252 break; 253 254 case QUNIFORM_TEXTURE_CONFIG_P0: 255 write_texture_p0(job, &uniforms, texstate, 256 uinfo->data[i]); 257 break; 258 259 case QUNIFORM_TEXTURE_CONFIG_P1: 260 write_texture_p1(job, &uniforms, texstate, 261 uinfo->data[i]); 262 break; 263 264 case QUNIFORM_TEXTURE_CONFIG_P2: 265 write_texture_p2(job, &uniforms, texstate, 266 uinfo->data[i]); 267 break; 268 269 case QUNIFORM_TEXTURE_FIRST_LEVEL: 270 write_texture_first_level(job, &uniforms, texstate, 271 uinfo->data[i]); 272 break; 273 274 case QUNIFORM_UBO_ADDR: 275 cl_aligned_reloc(job, &job->uniforms, &uniforms, ubo, 0); 276 break; 277 278 case QUNIFORM_TEXTURE_MSAA_ADDR: 279 write_texture_msaa_addr(job, &uniforms, 280 texstate, uinfo->data[i]); 281 break; 282 283 case QUNIFORM_TEXTURE_BORDER_COLOR: 284 write_texture_border_color(job, &uniforms, 285 texstate, uinfo->data[i]); 286 break; 287 288 case QUNIFORM_TEXRECT_SCALE_X: 289 case QUNIFORM_TEXRECT_SCALE_Y: 290 cl_aligned_u32(&uniforms, 291 get_texrect_scale(texstate, 292 uinfo->contents[i], 293 uinfo->data[i])); 294 break; 295 296 case QUNIFORM_BLEND_CONST_COLOR_X: 297 case QUNIFORM_BLEND_CONST_COLOR_Y: 298 case QUNIFORM_BLEND_CONST_COLOR_Z: 299 case QUNIFORM_BLEND_CONST_COLOR_W: 300 cl_aligned_f(&uniforms, 301 CLAMP(vc4->blend_color.f.color[uinfo->contents[i] - 302 QUNIFORM_BLEND_CONST_COLOR_X], 303 0, 1)); 304 break; 305 306 case QUNIFORM_BLEND_CONST_COLOR_RGBA: { 307 const uint8_t *format_swiz = 308 vc4_get_format_swizzle(vc4->framebuffer.cbufs[0]->format); 309 uint32_t color = 0; 310 for (int i = 0; i < 4; i++) { 311 if (format_swiz[i] >= 4) 312 continue; 313 314 color |= (vc4->blend_color.ub[format_swiz[i]] << 315 (i * 8)); 316 } 317 cl_aligned_u32(&uniforms, color); 318 break; 319 } 320 321 case QUNIFORM_BLEND_CONST_COLOR_AAAA: { 322 uint8_t a = vc4->blend_color.ub[3]; 323 cl_aligned_u32(&uniforms, ((a) | 324 (a << 8) | 325 (a << 16) | 326 (a << 24))); 327 break; 328 } 329 330 case QUNIFORM_STENCIL: 331 cl_aligned_u32(&uniforms, 332 vc4->zsa->stencil_uniforms[uinfo->data[i]] | 333 (uinfo->data[i] <= 1 ? 334 (vc4->stencil_ref.ref_value[uinfo->data[i]] << 8) : 335 0)); 336 break; 337 338 case QUNIFORM_ALPHA_REF: 339 cl_aligned_f(&uniforms, 340 vc4->zsa->base.alpha.ref_value); 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#if 0 353 uint32_t written_val = *((uint32_t *)uniforms - 1); 354 fprintf(stderr, "%p: %d / 0x%08x (%f)\n", 355 shader, i, written_val, uif(written_val)); 356#endif 357 } 358 359 cl_end(&job->uniforms, uniforms); 360 361 vc4_bo_unreference(&ubo); 362} 363 364void 365vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader) 366{ 367 uint32_t dirty = 0; 368 369 for (int i = 0; i < shader->uniforms.count; i++) { 370 switch (shader->uniforms.contents[i]) { 371 case QUNIFORM_CONSTANT: 372 case QUNIFORM_UNIFORMS_ADDRESS: 373 break; 374 case QUNIFORM_UNIFORM: 375 case QUNIFORM_UBO_ADDR: 376 dirty |= VC4_DIRTY_CONSTBUF; 377 break; 378 379 case QUNIFORM_VIEWPORT_X_SCALE: 380 case QUNIFORM_VIEWPORT_Y_SCALE: 381 case QUNIFORM_VIEWPORT_Z_OFFSET: 382 case QUNIFORM_VIEWPORT_Z_SCALE: 383 dirty |= VC4_DIRTY_VIEWPORT; 384 break; 385 386 case QUNIFORM_USER_CLIP_PLANE: 387 dirty |= VC4_DIRTY_CLIP; 388 break; 389 390 case QUNIFORM_TEXTURE_CONFIG_P0: 391 case QUNIFORM_TEXTURE_CONFIG_P1: 392 case QUNIFORM_TEXTURE_CONFIG_P2: 393 case QUNIFORM_TEXTURE_BORDER_COLOR: 394 case QUNIFORM_TEXTURE_FIRST_LEVEL: 395 case QUNIFORM_TEXTURE_MSAA_ADDR: 396 case QUNIFORM_TEXRECT_SCALE_X: 397 case QUNIFORM_TEXRECT_SCALE_Y: 398 /* We could flag this on just the stage we're 399 * compiling for, but it's not passed in. 400 */ 401 dirty |= VC4_DIRTY_FRAGTEX | VC4_DIRTY_VERTTEX; 402 break; 403 404 case QUNIFORM_BLEND_CONST_COLOR_X: 405 case QUNIFORM_BLEND_CONST_COLOR_Y: 406 case QUNIFORM_BLEND_CONST_COLOR_Z: 407 case QUNIFORM_BLEND_CONST_COLOR_W: 408 case QUNIFORM_BLEND_CONST_COLOR_RGBA: 409 case QUNIFORM_BLEND_CONST_COLOR_AAAA: 410 dirty |= VC4_DIRTY_BLEND_COLOR; 411 break; 412 413 case QUNIFORM_STENCIL: 414 case QUNIFORM_ALPHA_REF: 415 dirty |= VC4_DIRTY_ZSA; 416 break; 417 418 case QUNIFORM_SAMPLE_MASK: 419 dirty |= VC4_DIRTY_SAMPLE_MASK; 420 break; 421 } 422 } 423 424 shader->uniform_dirty_bits = dirty; 425} 426