pan_screen.c revision b8e80941
1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2014 Broadcom 5 * Copyright 2018 Alyssa Rosenzweig 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 31#include "util/u_debug.h" 32#include "util/u_memory.h" 33#include "util/u_format.h" 34#include "util/u_format_s3tc.h" 35#include "util/u_video.h" 36#include "util/u_screen.h" 37#include "util/os_time.h" 38#include "pipe/p_defines.h" 39#include "pipe/p_screen.h" 40#include "draw/draw_context.h" 41#include <xf86drm.h> 42 43#include <fcntl.h> 44 45#include "drm-uapi/drm_fourcc.h" 46 47#include "pan_screen.h" 48#include "pan_resource.h" 49#include "pan_public.h" 50#include "pan_util.h" 51 52#include "pan_context.h" 53#include "midgard/midgard_compile.h" 54 55static const struct debug_named_value debug_options[] = { 56 {"msgs", PAN_DBG_MSGS, "Print debug messages"}, 57 DEBUG_NAMED_VALUE_END 58}; 59 60DEBUG_GET_ONCE_FLAGS_OPTION(pan_debug, "PAN_MESA_DEBUG", debug_options, 0) 61 62int pan_debug = 0; 63 64struct panfrost_driver *panfrost_create_drm_driver(int fd); 65 66const char *pan_counters_base = NULL; 67 68static const char * 69panfrost_get_name(struct pipe_screen *screen) 70{ 71 return "panfrost"; 72} 73 74static const char * 75panfrost_get_vendor(struct pipe_screen *screen) 76{ 77 return "panfrost"; 78} 79 80static const char * 81panfrost_get_device_vendor(struct pipe_screen *screen) 82{ 83 return "Arm"; 84} 85 86static int 87panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param) 88{ 89 switch (param) { 90 case PIPE_CAP_NPOT_TEXTURES: 91 case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: 92 case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: 93 return 1; 94 95 case PIPE_CAP_SM3: 96 case PIPE_CAP_POINT_SPRITE: 97 return 1; 98 99 case PIPE_CAP_MAX_RENDER_TARGETS: 100 case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: 101 return 1; 102 103 case PIPE_CAP_OCCLUSION_QUERY: 104 case PIPE_CAP_QUERY_TIME_ELAPSED: 105 case PIPE_CAP_QUERY_PIPELINE_STATISTICS: 106 return 1; /* TODO: Queries */ 107 108 case PIPE_CAP_TEXTURE_MIRROR_CLAMP: 109 case PIPE_CAP_TEXTURE_SWIZZLE: 110 return 1; 111 112 /* TODO: ES3. We expose these caps so we can access higher dEQP 113 * tests; in actuality they are nonfunctional */ 114 case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: 115 return 4; 116 case PIPE_CAP_TGSI_INSTANCEID: 117 case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: 118 return 1; 119 120 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: 121 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 122 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 123 return 13; 124 125 case PIPE_CAP_BLEND_EQUATION_SEPARATE: 126 return 1; 127 128 case PIPE_CAP_INDEP_BLEND_ENABLE: 129 return 1; 130 131 case PIPE_CAP_INDEP_BLEND_FUNC: 132 return 1; 133 134 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 135 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 136 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 137 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 138 return 1; 139 140 case PIPE_CAP_DEPTH_CLIP_DISABLE: 141 return 1; 142 143 case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: 144 case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: 145 return 16 * 4; 146 147 case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: 148 case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: 149 return 1024; 150 151 case PIPE_CAP_MAX_VERTEX_STREAMS: 152 return 1; 153 154 case PIPE_CAP_SHADER_STENCIL_EXPORT: 155 return 1; 156 157 case PIPE_CAP_SEAMLESS_CUBE_MAP: 158 case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: 159 return 1; 160 161 case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: 162 return 256; /* for GL3 */ 163 164 case PIPE_CAP_CONDITIONAL_RENDER: 165 return 1; 166 167 case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: 168 case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: 169 case PIPE_CAP_VERTEX_COLOR_CLAMPED: 170 return 1; 171 172 case PIPE_CAP_GLSL_FEATURE_LEVEL: 173 return 330; 174 175 case PIPE_CAP_USER_VERTEX_BUFFERS: /* TODO */ 176 case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: 177 return 0; 178 179 case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: 180 case PIPE_CAP_DOUBLES: 181 case PIPE_CAP_INT64: 182 case PIPE_CAP_INT64_DIVMOD: 183 return 1; 184 185 case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: 186 return 16; 187 188 case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET: 189 return 0xffff; 190 191 case PIPE_CAP_QUERY_TIMESTAMP: 192 case PIPE_CAP_CUBE_MAP_ARRAY: 193 return 1; 194 195 case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: 196 return 1; 197 198 case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: 199 return 65536; 200 201 case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: 202 return 0; 203 204 case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: 205 return 0; 206 207 case PIPE_CAP_MAX_VIEWPORTS: 208 return PIPE_MAX_VIEWPORTS; 209 210 case PIPE_CAP_ENDIANNESS: 211 return PIPE_ENDIAN_NATIVE; 212 213 case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: 214 return 4; 215 216 case PIPE_CAP_TEXTURE_GATHER_SM5: 217 case PIPE_CAP_TEXTURE_QUERY_LOD: 218 case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: 219 case PIPE_CAP_SAMPLER_VIEW_TARGET: 220 case PIPE_CAP_FAKE_SW_MSAA: 221 return 1; 222 223 case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: 224 return -32; 225 226 case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: 227 return 31; 228 229 case PIPE_CAP_DRAW_INDIRECT: 230 return 1; 231 232 case PIPE_CAP_QUERY_SO_OVERFLOW: 233 return 1; 234 235 case PIPE_CAP_VENDOR_ID: 236 return 0xFFFFFFFF; 237 238 case PIPE_CAP_DEVICE_ID: 239 return 0xFFFFFFFF; 240 241 case PIPE_CAP_ACCELERATED: 242 return 1; 243 244 case PIPE_CAP_VIDEO_MEMORY: { 245 uint64_t system_memory; 246 247 if (!os_get_total_physical_memory(&system_memory)) 248 return 0; 249 250 return (int)(system_memory >> 20); 251 } 252 253 case PIPE_CAP_UMA: 254 return 1; 255 256 case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: 257 case PIPE_CAP_CLIP_HALFZ: 258 case PIPE_CAP_TEXTURE_FLOAT_LINEAR: 259 case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: 260 case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: 261 case PIPE_CAP_CULL_DISTANCE: 262 case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: 263 case PIPE_CAP_TGSI_ARRAY_COMPONENTS: 264 case PIPE_CAP_CLEAR_TEXTURE: 265 return 1; 266 267 case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: 268 return 4; 269 270 case PIPE_CAP_MAX_VARYINGS: 271 return 16; 272 273 default: 274 return u_pipe_screen_get_param_defaults(screen, param); 275 } 276} 277 278static int 279panfrost_get_shader_param(struct pipe_screen *screen, 280 enum pipe_shader_type shader, 281 enum pipe_shader_cap param) 282{ 283 if (shader != PIPE_SHADER_VERTEX && 284 shader != PIPE_SHADER_FRAGMENT) { 285 return 0; 286 } 287 288 /* this is probably not totally correct.. but it's a start: */ 289 switch (param) { 290 case PIPE_SHADER_CAP_SCALAR_ISA: 291 return 0; 292 293 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 294 return 0; 295 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 296 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 297 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 298 return 16384; 299 300 case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: 301 return 1024; 302 303 case PIPE_SHADER_CAP_MAX_INPUTS: 304 return 16; 305 306 case PIPE_SHADER_CAP_MAX_OUTPUTS: 307 return shader == PIPE_SHADER_FRAGMENT ? 1 : 8; 308 309 case PIPE_SHADER_CAP_MAX_TEMPS: 310 return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */ 311 312 case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: 313 return 16 * 1024 * sizeof(float); 314 315 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 316 return 4; 317 318 case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: 319 return 0; 320 321 case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: 322 return 1; 323 case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: 324 return 0; 325 326 case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: 327 return 0; 328 329 case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: 330 return 1; 331 332 case PIPE_SHADER_CAP_SUBROUTINES: 333 return 0; 334 335 case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: 336 return 0; 337 338 case PIPE_SHADER_CAP_INTEGERS: 339 return 1; 340 341 case PIPE_SHADER_CAP_INT64_ATOMICS: 342 case PIPE_SHADER_CAP_FP16: 343 case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: 344 case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: 345 case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED: 346 case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: 347 case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: 348 return 0; 349 350 case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: 351 case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: 352 return 16; /* XXX: How many? */ 353 354 case PIPE_SHADER_CAP_PREFERRED_IR: 355 return PIPE_SHADER_IR_NIR; 356 357 case PIPE_SHADER_CAP_SUPPORTED_IRS: 358 return 0; 359 360 case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: 361 return 32; 362 363 case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: 364 case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: 365 case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: 366 case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: 367 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS: 368 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS: 369 return 0; 370 371 default: 372 fprintf(stderr, "unknown shader param %d\n", param); 373 return 0; 374 } 375 376 return 0; 377} 378 379static float 380panfrost_get_paramf(struct pipe_screen *screen, enum pipe_capf param) 381{ 382 switch (param) { 383 case PIPE_CAPF_MAX_LINE_WIDTH: 384 385 /* fall-through */ 386 case PIPE_CAPF_MAX_LINE_WIDTH_AA: 387 return 255.0; /* arbitrary */ 388 389 case PIPE_CAPF_MAX_POINT_WIDTH: 390 391 /* fall-through */ 392 case PIPE_CAPF_MAX_POINT_WIDTH_AA: 393 return 255.0; /* arbitrary */ 394 395 case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: 396 return 16.0; 397 398 case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: 399 return 16.0; /* arbitrary */ 400 401 default: 402 debug_printf("Unexpected PIPE_CAPF %d query\n", param); 403 return 0.0; 404 } 405} 406 407/** 408 * Query format support for creating a texture, drawing surface, etc. 409 * \param format the format to test 410 * \param type one of PIPE_TEXTURE, PIPE_SURFACE 411 */ 412static boolean 413panfrost_is_format_supported( struct pipe_screen *screen, 414 enum pipe_format format, 415 enum pipe_texture_target target, 416 unsigned sample_count, 417 unsigned storage_sample_count, 418 unsigned bind) 419{ 420 const struct util_format_description *format_desc; 421 422 assert(target == PIPE_BUFFER || 423 target == PIPE_TEXTURE_1D || 424 target == PIPE_TEXTURE_1D_ARRAY || 425 target == PIPE_TEXTURE_2D || 426 target == PIPE_TEXTURE_2D_ARRAY || 427 target == PIPE_TEXTURE_RECT || 428 target == PIPE_TEXTURE_3D || 429 target == PIPE_TEXTURE_CUBE || 430 target == PIPE_TEXTURE_CUBE_ARRAY); 431 432 format_desc = util_format_description(format); 433 434 if (!format_desc) 435 return FALSE; 436 437 if (sample_count > 1) 438 return FALSE; 439 440 /* Format wishlist */ 441 if (format == PIPE_FORMAT_Z24X8_UNORM || format == PIPE_FORMAT_X8Z24_UNORM) 442 return FALSE; 443 444 if (format == PIPE_FORMAT_A1B5G5R5_UNORM || format == PIPE_FORMAT_X1B5G5R5_UNORM) 445 return FALSE; 446 447 if (bind & PIPE_BIND_RENDER_TARGET) { 448 /* TODO: Support all the formats! :) */ 449 bool supported = util_format_is_rgba8_variant(format_desc); 450 supported |= format == PIPE_FORMAT_B5G6R5_UNORM; 451 452 if (!supported) 453 return FALSE; 454 455 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) 456 return FALSE; 457 458 /* 459 * Although possible, it is unnatural to render into compressed or YUV 460 * surfaces. So disable these here to avoid going into weird paths 461 * inside the state trackers. 462 */ 463 if (format_desc->block.width != 1 || 464 format_desc->block.height != 1) 465 return FALSE; 466 } 467 468 if (bind & PIPE_BIND_DEPTH_STENCIL) { 469 if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) 470 return FALSE; 471 } 472 473 if (format_desc->layout == UTIL_FORMAT_LAYOUT_BPTC || 474 format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC || 475 format_desc->layout == UTIL_FORMAT_LAYOUT_ETC) { 476 /* Compressed formats not yet hooked up. */ 477 return FALSE; 478 } 479 480 if ((bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) && 481 ((bind & PIPE_BIND_DISPLAY_TARGET) == 0) && 482 target != PIPE_BUFFER) { 483 const struct util_format_description *desc = 484 util_format_description(format); 485 486 if (desc->nr_channels == 3 && desc->is_array) { 487 /* Don't support any 3-component formats for rendering/texturing 488 * since we don't support the corresponding 8-bit 3 channel UNORM 489 * formats. This allows us to support GL_ARB_copy_image between 490 * GL_RGB8 and GL_RGB8UI, for example. Otherwise, we may be asked to 491 * do a resource copy between PIPE_FORMAT_R8G8B8_UINT and 492 * PIPE_FORMAT_R8G8B8X8_UNORM, for example, which will not work 493 * (different bpp). 494 */ 495 return FALSE; 496 } 497 } 498 499 return TRUE; 500} 501 502 503static void 504panfrost_destroy_screen( struct pipe_screen *screen ) 505{ 506 FREE(screen); 507} 508 509static void 510panfrost_flush_frontbuffer(struct pipe_screen *_screen, 511 struct pipe_resource *resource, 512 unsigned level, unsigned layer, 513 void *context_private, 514 struct pipe_box *sub_box) 515{ 516 /* TODO: Display target integration */ 517} 518 519static uint64_t 520panfrost_get_timestamp(struct pipe_screen *_screen) 521{ 522 return os_time_get_nano(); 523} 524 525static void 526panfrost_fence_reference(struct pipe_screen *pscreen, 527 struct pipe_fence_handle **ptr, 528 struct pipe_fence_handle *fence) 529{ 530 struct panfrost_screen *screen = pan_screen(pscreen); 531 screen->driver->fence_reference(pscreen, ptr, fence); 532} 533 534static boolean 535panfrost_fence_finish(struct pipe_screen *pscreen, 536 struct pipe_context *ctx, 537 struct pipe_fence_handle *fence, 538 uint64_t timeout) 539{ 540 struct panfrost_screen *screen = pan_screen(pscreen); 541 return screen->driver->fence_finish(pscreen, ctx, fence, timeout); 542} 543 544static const void * 545panfrost_screen_get_compiler_options(struct pipe_screen *pscreen, 546 enum pipe_shader_ir ir, 547 enum pipe_shader_type shader) 548{ 549 return &midgard_nir_options; 550} 551 552struct pipe_screen * 553panfrost_create_screen(int fd, struct renderonly *ro) 554{ 555 struct panfrost_screen *screen = CALLOC_STRUCT(panfrost_screen); 556 557 pan_debug = debug_get_option_pan_debug(); 558 559 if (!screen) 560 return NULL; 561 562 if (ro) { 563 screen->ro = renderonly_dup(ro); 564 if (!screen->ro) { 565 fprintf(stderr, "Failed to dup renderonly object\n"); 566 free(screen); 567 return NULL; 568 } 569 } 570 571 screen->driver = panfrost_create_drm_driver(fd); 572 573 /* Dump memory and/or performance counters iff asked for in the environment */ 574 const char *pantrace_base = getenv("PANTRACE_BASE"); 575 pan_counters_base = getenv("PANCOUNTERS_BASE"); 576 577 if (pantrace_base) { 578 pantrace_initialize(pantrace_base); 579 } 580 581 if (pan_counters_base) { 582 screen->driver->allocate_slab(screen, &screen->perf_counters, 64, true, 0, 0, 0); 583 screen->driver->enable_counters(screen); 584 } 585 586 screen->base.destroy = panfrost_destroy_screen; 587 588 screen->base.get_name = panfrost_get_name; 589 screen->base.get_vendor = panfrost_get_vendor; 590 screen->base.get_device_vendor = panfrost_get_device_vendor; 591 screen->base.get_param = panfrost_get_param; 592 screen->base.get_shader_param = panfrost_get_shader_param; 593 screen->base.get_paramf = panfrost_get_paramf; 594 screen->base.get_timestamp = panfrost_get_timestamp; 595 screen->base.is_format_supported = panfrost_is_format_supported; 596 screen->base.context_create = panfrost_create_context; 597 screen->base.flush_frontbuffer = panfrost_flush_frontbuffer; 598 screen->base.get_compiler_options = panfrost_screen_get_compiler_options; 599 screen->base.fence_reference = panfrost_fence_reference; 600 screen->base.fence_finish = panfrost_fence_finish; 601 602 screen->last_fragment_flushed = true; 603 screen->last_job = NULL; 604 605 panfrost_resource_screen_init(screen); 606 607 return &screen->base; 608} 609