diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_screen.c')
-rw-r--r-- | src/gallium/drivers/freedreno/freedreno_screen.c | 423 |
1 files changed, 307 insertions, 116 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 080d67918c8..4461f796320 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -62,6 +62,7 @@ #include "common/freedreno_uuid.h" #include "a2xx/ir2.h" +#include "ir3/ir3_descriptor.h" #include "ir3/ir3_gallium.h" #include "ir3/ir3_nir.h" @@ -73,11 +74,11 @@ static const struct debug_named_value fd_debug_options[] = { {"ddraw", FD_DBG_DDRAW, "Mark all state dirty after draw"}, {"noscis", FD_DBG_NOSCIS, "Disable scissor optimization"}, {"direct", FD_DBG_DIRECT, "Force inline (SS_DIRECT) state loads"}, - {"nobypass", FD_DBG_NOBYPASS, "Disable GMEM bypass"}, + {"gmem", FD_DBG_GMEM, "Use gmem rendering when it is permitted"}, {"perf", FD_DBG_PERF, "Enable performance warnings"}, {"nobin", FD_DBG_NOBIN, "Disable hw binning"}, - {"nogmem", FD_DBG_NOGMEM, "Disable GMEM rendering (bypass only)"}, - {"serialc", FD_DBG_SERIALC,"Disable asynchronous shader compile"}, + {"sysmem", FD_DBG_SYSMEM, "Use sysmem only rendering (no tiling)"}, + {"serialc", FD_DBG_SERIALC, "Disable asynchronous shader compile"}, {"shaderdb", FD_DBG_SHADERDB, "Enable shaderdb output"}, {"flush", FD_DBG_FLUSH, "Force flush after every draw"}, {"deqp", FD_DBG_DEQP, "Enable dEQP hacks"}, @@ -96,6 +97,7 @@ static const struct debug_named_value fd_debug_options[] = { {"layout", FD_DBG_LAYOUT, "Dump resource layouts"}, {"nofp16", FD_DBG_NOFP16, "Disable mediump precision lowering"}, {"nohw", FD_DBG_NOHW, "Disable submitting commands to the HW"}, + {"nosbin", FD_DBG_NOSBIN, "Execute GMEM bins in raster order instead of 'S' pattern"}, DEBUG_NAMED_VALUE_END }; /* clang-format on */ @@ -123,6 +125,14 @@ fd_screen_get_device_vendor(struct pipe_screen *pscreen) return "Qualcomm"; } +static void +fd_get_sample_pixel_grid(struct pipe_screen *pscreen, unsigned sample_count, + unsigned *out_width, unsigned *out_height) +{ + *out_width = 1; + *out_height = 1; +} + static uint64_t fd_screen_get_timestamp(struct pipe_screen *pscreen) { @@ -131,10 +141,9 @@ fd_screen_get_timestamp(struct pipe_screen *pscreen) if (screen->has_timestamp) { uint64_t n; fd_pipe_get_param(screen->pipe, FD_TIMESTAMP, &n); - debug_assert(screen->max_freq > 0); - return n * 1000000000 / screen->max_freq; + return ticks_to_ns(n); } else { - int64_t cpu_time = os_time_get() * 1000; + int64_t cpu_time = os_time_get_nano(); return cpu_time + screen->cpu_gpu_time_delta; } } @@ -144,6 +153,12 @@ fd_screen_destroy(struct pipe_screen *pscreen) { struct fd_screen *screen = fd_screen(pscreen); + if (screen->aux_ctx) + screen->aux_ctx->destroy(screen->aux_ctx); + + if (screen->tess_bo) + fd_bo_del(screen->tess_bo); + if (screen->pipe) fd_pipe_del(screen->pipe); @@ -155,6 +170,7 @@ fd_screen_destroy(struct pipe_screen *pscreen) if (screen->ro) screen->ro->destroy(screen->ro); + fd_bc_fini(&screen->batch_cache); fd_gmem_screen_fini(pscreen); slab_destroy_parent(&screen->transfer_pool); @@ -172,6 +188,36 @@ fd_screen_destroy(struct pipe_screen *pscreen) free(screen); } +static uint64_t +get_memory_size(struct fd_screen *screen) +{ + uint64_t system_memory; + + if (!os_get_total_physical_memory(&system_memory)) + return 0; + if (fd_device_version(screen->dev) >= FD_VERSION_VA_SIZE) { + uint64_t va_size; + if (!fd_pipe_get_param(screen->pipe, FD_VA_SIZE, &va_size)) { + system_memory = MIN2(system_memory, va_size); + } + } + + return system_memory; +} + +static void +fd_query_memory_info(struct pipe_screen *pscreen, + struct pipe_memory_info *info) +{ + unsigned mem = get_memory_size(fd_screen(pscreen)) >> 10; + + memset(info, 0, sizeof(*info)); + + info->total_device_memory = mem; + info->avail_device_memory = mem; +} + + /* TODO either move caps to a2xx/a3xx specific code, or maybe have some tables for things that differ if the delta is not too much.. @@ -187,35 +233,38 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: case PIPE_CAP_ANISOTROPIC_FILTER: - case PIPE_CAP_POINT_SPRITE: case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_TEXTURE_SWIZZLE: - case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: - case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_STRING_MARKER: case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_INVALIDATE_BUFFER: - case PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND: case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS: - case PIPE_CAP_NIR_COMPACT_ARRAYS: + case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE: + case PIPE_CAP_GL_SPIRV: + case PIPE_CAP_FBFETCH_COHERENT: + case PIPE_CAP_HAS_CONST_BW: return 1; case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: + case PIPE_CAP_MULTI_DRAW_INDIRECT: + case PIPE_CAP_DRAW_PARAMETERS: + case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: + case PIPE_CAP_DEPTH_BOUNDS_TEST: return is_a6xx(screen); case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: - return !is_a2xx(screen); + return is_a2xx(screen); - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + case PIPE_CAP_FS_COORD_PIXEL_CENTER_INTEGER: return is_a2xx(screen); - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + case PIPE_CAP_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return !is_a2xx(screen); case PIPE_CAP_PACKED_UNIFORMS: @@ -225,13 +274,10 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: return screen->has_robustness; - case PIPE_CAP_VERTEXID_NOBASE: - return is_a3xx(screen) || is_a4xx(screen); - case PIPE_CAP_COMPUTE: return has_compute(screen); - case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: + case PIPE_CAP_TEXTURE_TRANSFER_MODES: case PIPE_CAP_PCI_GROUP: case PIPE_CAP_PCI_BUS: case PIPE_CAP_PCI_DEVICE: @@ -244,10 +290,9 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD: case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES: - case PIPE_CAP_VERTEX_SHADER_SATURATE: case PIPE_CAP_PRIMITIVE_RESTART: case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX: - case PIPE_CAP_TGSI_INSTANCEID: + case PIPE_CAP_VS_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: @@ -264,6 +309,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return !fd_screen_get_param(pscreen, PIPE_CAP_TEXTURE_MULTISAMPLE); case PIPE_CAP_TEXTURE_MULTISAMPLE: + case PIPE_CAP_IMAGE_STORE_FORMATTED: + case PIPE_CAP_IMAGE_LOAD_FORMATTED: return is_a5xx(screen) || is_a6xx(screen); case PIPE_CAP_SURFACE_SAMPLE_COUNT: @@ -272,9 +319,18 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_DEPTH_CLIP_DISABLE: return is_a3xx(screen) || is_a4xx(screen) || is_a6xx(screen); + case PIPE_CAP_POST_DEPTH_COVERAGE: case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE: + case PIPE_CAP_DEMOTE_TO_HELPER_INVOCATION: return is_a6xx(screen); + case PIPE_CAP_SAMPLER_REDUCTION_MINMAX: + case PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB: + return is_a6xx(screen) && screen->info->a6xx.has_sampler_minmax; + + case PIPE_CAP_PROGRAMMABLE_SAMPLE_LOCATIONS: + return is_a6xx(screen) && screen->info->a6xx.has_sample_locations; + case PIPE_CAP_POLYGON_OFFSET_CLAMP: return is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen); @@ -284,28 +340,28 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: if (is_a3xx(screen)) return 16; - if (is_a4xx(screen)) - return 32; - if (is_a5xx(screen) || is_a6xx(screen)) + if (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)) return 64; return 0; - case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: + case PIPE_CAP_MAX_TEXEL_BUFFER_ELEMENTS_UINT: /* We could possibly emulate more by pretending 2d/rect textures and * splitting high bits of index into 2nd dimension.. */ if (is_a3xx(screen)) - return 8192; - if (is_a4xx(screen)) - return 16384; + return A3XX_MAX_TEXEL_BUFFER_ELEMENTS_UINT; /* Note that the Vulkan blob on a540 and 640 report a * maxTexelBufferElements of just 65536 (the GLES3.2 and Vulkan * minimum). */ - if (is_a5xx(screen) || is_a6xx(screen)) - return 1 << 27; + if (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)) + return A4XX_MAX_TEXEL_BUFFER_ELEMENTS_UINT; + return 0; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO; + case PIPE_CAP_TEXTURE_FLOAT_LINEAR: case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_SAMPLER_VIEW_TARGET: @@ -318,26 +374,27 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) * Since draw_indirect is needed sooner (gles31 and gl40 vs * gl42), hide base_instance on a5xx. :-/ */ - return is_a4xx(screen); + return is_a4xx(screen) || is_a6xx(screen); case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 64; + case PIPE_CAP_INT64: + case PIPE_CAP_DOUBLES: + return is_ir3(screen); + case PIPE_CAP_GLSL_FEATURE_LEVEL: case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY: if (is_a6xx(screen)) - return 330; + return 460; else if (is_ir3(screen)) return 140; else return 120; case PIPE_CAP_ESSL_FEATURE_LEVEL: - /* we can probably enable 320 for a5xx too, but need to test: */ - if (is_a6xx(screen)) + if (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)) return 320; - if (is_a5xx(screen)) - return 310; if (is_ir3(screen)) return 300; return 120; @@ -347,6 +404,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 64; if (is_a5xx(screen)) return 4; + if (is_a4xx(screen)) + return 4; return 0; case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: @@ -362,7 +421,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_FBFETCH: if (fd_device_version(screen->dev) >= FD_VERSION_GMEM_BASE && is_a6xx(screen)) - return 1; + return screen->max_rts; return 0; case PIPE_CAP_SAMPLE_SHADING: if (is_a6xx(screen)) @@ -391,7 +450,13 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_NIR_IMAGES_AS_DEREF: return 0; + case PIPE_CAP_VS_LAYER_VIEWPORT: + case PIPE_CAP_TES_LAYER_VIEWPORT: + return is_a6xx(screen); + case PIPE_CAP_MAX_VIEWPORTS: + if (is_a6xx(screen)) + return 16; return 1; case PIPE_CAP_MAX_VARYINGS: @@ -408,14 +473,13 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 64 * 1024 * 1024; case PIPE_CAP_SHAREABLE_SHADERS: - case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY: if (is_ir3(screen)) return 1; return 0; /* Geometry shaders.. */ case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: - return 512; + return 256; case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: return 2048; case PIPE_CAP_MAX_GS_INVOCATIONS: @@ -428,6 +492,14 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return is_a2xx(screen); case PIPE_CAP_CLIP_PLANES: + /* Gens that support GS, have GS lowered into a quasi-VS which confuses + * the frontend clip-plane lowering. So we handle this in the backend + * + */ + if (pscreen->get_shader_param(pscreen, PIPE_SHADER_GEOMETRY, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS)) + return 1; + /* On a3xx, there is HW support for GL user clip planes that * occasionally has to fall back to shader key-based lowering to clip * distances in the VS, and we don't support clip distances so that is @@ -441,24 +513,35 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) * On a5xx-a6xx, we have the HW clip distances hooked up, so we just let * mesa/st lower desktop GL's clip planes to clip distances in the last * vertex shader stage. + * + * NOTE: but see comment above about geometry shaders */ - return !is_a5xx(screen) && !is_a6xx(screen); + return !is_a5xx(screen); /* Stream output. */ + case PIPE_CAP_MAX_VERTEX_STREAMS: + if (is_a6xx(screen)) /* has SO + GS */ + return PIPE_MAX_SO_BUFFERS; + return 0; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: if (is_ir3(screen)) return PIPE_MAX_SO_BUFFERS; return 0; case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: - case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: + case PIPE_CAP_FS_POSITION_IS_SYSVAL: case PIPE_CAP_TGSI_TEXCOORD: + case PIPE_CAP_SHADER_ARRAY_COMPONENTS: + case PIPE_CAP_TEXTURE_QUERY_SAMPLES: + case PIPE_CAP_FS_FINE_DERIVATIVE: if (is_ir3(screen)) return 1; return 0; - case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: + case PIPE_CAP_SHADER_GROUP_VOTE: + return is_a6xx(screen); + case PIPE_CAP_FS_FACE_IS_INTEGER_SYSVAL: return 1; - case PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL: + case PIPE_CAP_FS_POINT_IS_SYSVAL: return is_a2xx(screen); case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: @@ -477,12 +560,16 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 15; else return 14; + case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 11; + if (is_a3xx(screen)) + return 11; + return 12; case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: - return (is_a3xx(screen) || is_a4xx(screen) || is_a5xx(screen) || - is_a6xx(screen)) + if (is_a6xx(screen)) + return 2048; + return (is_a3xx(screen) || is_a4xx(screen) || is_a5xx(screen)) ? 256 : 0; @@ -501,6 +588,12 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) /* only a4xx, requires new enough kernel so we know max_freq: */ return (screen->max_freq > 0) && (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)); + case PIPE_CAP_TIMER_RESOLUTION: + return ticks_to_ns(1); + case PIPE_CAP_QUERY_BUFFER_OBJECT: + case PIPE_CAP_QUERY_SO_OVERFLOW: + case PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE: + return is_a6xx(screen); case PIPE_CAP_VENDOR_ID: return 0x5143; @@ -508,9 +601,13 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 0xFFFFFFFF; case PIPE_CAP_ACCELERATED: return 1; + case PIPE_CAP_VIDEO_MEMORY: - DBG("FINISHME: The value returned is incorrect\n"); - return 10; + return (int)(get_memory_size(screen) >> 20); + + case PIPE_CAP_QUERY_MEMORY_INFO: /* Enables GL_ATI_meminfo */ + return get_memory_size(screen) != 0; + case PIPE_CAP_UMA: return 1; case PIPE_CAP_MEMOBJ: @@ -525,6 +622,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return is_a6xx(screen); case PIPE_CAP_TWO_SIDED_COLOR: return 0; + case PIPE_CAP_THROTTLE: + return screen->driconf.enable_throttling; default: return u_pipe_screen_get_param_defaults(pscreen, param); } @@ -534,6 +633,14 @@ static float fd_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) { switch (param) { + case PIPE_CAPF_MIN_LINE_WIDTH: + case PIPE_CAPF_MIN_LINE_WIDTH_AA: + case PIPE_CAPF_MIN_POINT_SIZE: + case PIPE_CAPF_MIN_POINT_SIZE_AA: + return 1; + case PIPE_CAPF_POINT_SIZE_GRANULARITY: + case PIPE_CAPF_LINE_WIDTH_GRANULARITY: + return 0.1f; case PIPE_CAPF_MAX_LINE_WIDTH: case PIPE_CAPF_MAX_LINE_WIDTH_AA: /* NOTE: actual value is 127.0f, but this is working around a deqp @@ -546,8 +653,8 @@ fd_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) if (FD_DBG(DEQP)) return 48.0f; return 127.0f; - case PIPE_CAPF_MAX_POINT_WIDTH: - case PIPE_CAPF_MAX_POINT_WIDTH_AA: + case PIPE_CAPF_MAX_POINT_SIZE: + case PIPE_CAPF_MAX_POINT_SIZE_AA: return 4092.0f; case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: return 16.0f; @@ -583,6 +690,9 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, if (has_compute(screen)) break; return 0; + case PIPE_SHADER_TASK: + case PIPE_SHADER_MESH: + return 0; default: mesa_loge("unknown shader type %d", shader); return 0; @@ -600,12 +710,13 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, case PIPE_SHADER_CAP_MAX_INPUTS: if (shader == PIPE_SHADER_GEOMETRY && is_a6xx(screen)) return 16; - return is_a6xx(screen) ? 32 : 16; + return is_a6xx(screen) ? + (screen->info->a6xx.vs_max_inputs_count) : 16; case PIPE_SHADER_CAP_MAX_OUTPUTS: return is_a6xx(screen) ? 32 : 16; case PIPE_SHADER_CAP_MAX_TEMPS: return 64; /* Max native temporaries. */ - case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: + case PIPE_SHADER_CAP_MAX_CONST_BUFFER0_SIZE: /* NOTE: seems to be limit for a3xx is actually 512 but * split between VS and FS. Use lower limit of 256 to * avoid getting into impossible situations: @@ -617,7 +728,7 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, sizeof(float[4]); case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return is_ir3(screen) ? 16 : 1; - case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: + case PIPE_SHADER_CAP_CONT_SUPPORTED: return 1; case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: @@ -626,14 +737,8 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, /* a2xx compiler doesn't handle indirect: */ return is_ir3(screen) ? 1 : 0; case PIPE_SHADER_CAP_SUBROUTINES: - case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: - case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: - case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED: - case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS: - case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD: - case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS: case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS: return 0; case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: @@ -654,15 +759,24 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: return 16; - case PIPE_SHADER_CAP_PREFERRED_IR: - return PIPE_SHADER_IR_NIR; case PIPE_SHADER_CAP_SUPPORTED_IRS: - return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI); - case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: - return 32; + return (1 << PIPE_SHADER_IR_NIR) | + COND(has_compute(screen) && (shader == PIPE_SHADER_COMPUTE), + (1 << PIPE_SHADER_IR_NIR_SERIALIZED)) | + /* tgsi_to_nir doesn't support all stages: */ + COND((shader == PIPE_SHADER_VERTEX) || + (shader == PIPE_SHADER_FRAGMENT) || + (shader == PIPE_SHADER_COMPUTE), + (1 << PIPE_SHADER_IR_TGSI)); case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: - if (is_a5xx(screen) || is_a6xx(screen)) { + if (is_a6xx(screen)) { + if (param == PIPE_SHADER_CAP_MAX_SHADER_BUFFERS) { + return IR3_BINDLESS_SSBO_COUNT; + } else { + return IR3_BINDLESS_IMAGE_COUNT; + } + } else if (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)) { /* a5xx (and a4xx for that matter) has one state-block * for compute-shader SSBO's and another that is shared * by VS/HS/DS/GS/FS.. so to simplify things for now @@ -712,6 +826,8 @@ fd_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, if (!has_compute(screen)) return 0; + struct ir3_compiler *compiler = screen->compiler; + #define RET(x) \ do { \ if (ret) \ @@ -721,11 +837,8 @@ fd_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, switch (param) { case PIPE_COMPUTE_CAP_ADDRESS_BITS: - // don't expose 64b pointer support yet, until ir3 supports 64b - // math, otherwise spir64 target is used and we get 64b pointer - // calculations that we can't do yet - // if (is_a5xx(screen)) - // RET((uint32_t []){ 64 }); + if (screen->gen >= 5) + RET((uint32_t[]){64}); RET((uint32_t[]){32}); case PIPE_COMPUTE_CAP_IR_TARGET: @@ -749,7 +862,7 @@ fd_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, RET((uint64_t[]){screen->ram_size}); case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE: - RET((uint64_t[]){32768}); + RET((uint64_t[]){screen->info->cs_shared_mem_size}); case PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE: case PIPE_COMPUTE_CAP_MAX_INPUT_SIZE: @@ -767,11 +880,14 @@ fd_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED: RET((uint32_t[]){1}); - case PIPE_COMPUTE_CAP_SUBGROUP_SIZE: + case PIPE_COMPUTE_CAP_SUBGROUP_SIZES: RET((uint32_t[]){32}); // TODO + case PIPE_COMPUTE_CAP_MAX_SUBGROUPS: + RET((uint32_t[]){0}); // TODO + case PIPE_COMPUTE_CAP_MAX_VARIABLE_THREADS_PER_BLOCK: - RET((uint64_t[]){1024}); // TODO + RET((uint64_t[]){ compiler->max_variable_workgroup_size }); } return 0; @@ -779,7 +895,7 @@ fd_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type, static const void * fd_get_compiler_options(struct pipe_screen *pscreen, enum pipe_shader_ir ir, - unsigned shader) + enum pipe_shader_type shader) { struct fd_screen *screen = fd_screen(pscreen); @@ -817,40 +933,59 @@ fd_screen_bo_get_handle(struct pipe_screen *pscreen, struct fd_bo *bo, if (screen->ro) { return renderonly_get_handle(scanout, whandle); } else { - whandle->handle = fd_bo_handle(bo); + uint32_t handle = fd_bo_handle(bo); + if (!handle) + return false; + whandle->handle = handle; return true; } } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { - whandle->handle = fd_bo_dmabuf(bo); + int fd = fd_bo_dmabuf(bo); + if (fd < 0) + return false; + whandle->handle = fd; return true; } else { return false; } } +static bool +is_format_supported(struct pipe_screen *pscreen, + enum pipe_format format, + uint64_t modifier) +{ + struct fd_screen *screen = fd_screen(pscreen); + if (screen->is_format_supported) + return screen->is_format_supported(pscreen, format, modifier); + return modifier == DRM_FORMAT_MOD_LINEAR; +} + static void fd_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count) { - struct fd_screen *screen = fd_screen(pscreen); - int i, num = 0; + const uint64_t all_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_QCOM_COMPRESSED, + DRM_FORMAT_MOD_QCOM_TILED3, + }; - max = MIN2(max, screen->num_supported_modifiers); + int num = 0; - if (!max) { - max = screen->num_supported_modifiers; - external_only = NULL; - modifiers = NULL; - } + for (int i = 0; i < ARRAY_SIZE(all_modifiers); i++) { + if (!is_format_supported(pscreen, format, all_modifiers[i])) + continue; - for (i = 0; i < max; i++) { - if (modifiers) - modifiers[num] = screen->supported_modifiers[i]; + if (num < max) { + if (modifiers) + modifiers[num] = all_modifiers[i]; - if (external_only) - external_only[num] = 0; + if (external_only) + external_only[num] = false; + } num++; } @@ -864,19 +999,7 @@ fd_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, enum pipe_format format, bool *external_only) { - struct fd_screen *screen = fd_screen(pscreen); - int i; - - for (i = 0; i < screen->num_supported_modifiers; i++) { - if (modifier == screen->supported_modifiers[i]) { - if (external_only) - *external_only = false; - - return true; - } - } - - return false; + return is_format_supported(pscreen, format, modifier); } struct fd_bo * @@ -909,7 +1032,7 @@ static void _fd_fence_ref(struct pipe_screen *pscreen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *pfence) { - fd_fence_ref(ptr, pfence); + fd_pipe_fence_ref(ptr, pfence); } static void @@ -926,10 +1049,22 @@ fd_screen_get_driver_uuid(struct pipe_screen *pscreen, char *uuid) fd_get_driver_uuid(uuid); } +static int +fd_screen_get_fd(struct pipe_screen *pscreen) +{ + struct fd_screen *screen = fd_screen(pscreen); + return fd_device_fd(screen->dev); +} + struct pipe_screen * -fd_screen_create(struct fd_device *dev, struct renderonly *ro, - const struct pipe_screen_config *config) +fd_screen_create(int fd, + const struct pipe_screen_config *config, + struct renderonly *ro) { + struct fd_device *dev = fd_device_new_dup(fd); + if (!dev) + return NULL; + struct fd_screen *screen = CALLOC_STRUCT(fd_screen); struct pipe_screen *pscreen; uint64_t val; @@ -946,11 +1081,12 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, fd_perfetto_init(); #endif + util_gpuvis_init(); + pscreen = &screen->base; screen->dev = dev; screen->ro = ro; - screen->refcnt = 1; // maybe this should be in context? screen->pipe = fd_pipe_new(screen->dev, FD_PIPE_3D); @@ -963,7 +1099,7 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, DBG("could not get GMEM size"); goto fail; } - screen->gmemsize_bytes = env_var_as_unsigned("FD_MESA_GMEM", val); + screen->gmemsize_bytes = debug_get_num_option("FD_MESA_GMEM", val); if (fd_device_version(dev) >= FD_VERSION_GMEM_BASE) { fd_pipe_get_param(screen->pipe, FD_GMEM_BASE, &screen->gmem_base); @@ -977,10 +1113,11 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, screen->max_freq = 0; } else { screen->max_freq = val; - if (fd_pipe_get_param(screen->pipe, FD_TIMESTAMP, &val) == 0) - screen->has_timestamp = true; } + if (fd_pipe_get_param(screen->pipe, FD_TIMESTAMP, &val) == 0) + screen->has_timestamp = true; + screen->dev_id = fd_pipe_dev_id(screen->pipe); if (fd_pipe_get_param(screen->pipe, FD_GPU_ID, &val)) { @@ -1002,12 +1139,27 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, screen->chip_id = val; screen->gen = fd_dev_gen(screen->dev_id); - if (fd_pipe_get_param(screen->pipe, FD_NR_RINGS, &val)) { + if (fd_pipe_get_param(screen->pipe, FD_NR_PRIORITIES, &val)) { DBG("could not get # of rings"); screen->priority_mask = 0; } else { /* # of rings equates to number of unique priority values: */ screen->priority_mask = (1 << val) - 1; + + /* Lowest numerical value (ie. zero) is highest priority: */ + screen->prio_high = 0; + + /* Highest numerical value is lowest priority: */ + screen->prio_low = val - 1; + + /* Pick midpoint for normal priority.. note that whatever the + * range of possible priorities, since we divide by 2 the + * result will either be an integer or an integer plus 0.5, + * in which case it will round down to an integer, so int + * division will give us an appropriate result in either + * case: + */ + screen->prio_norm = val / 2; } if (fd_device_version(dev) >= FD_VERSION_ROBUSTNESS) @@ -1019,6 +1171,13 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, driParseConfigFiles(config->options, config->options_info, 0, "msm", NULL, fd_dev_name(screen->dev_id), NULL, 0, NULL, 0); + screen->driconf.conservative_lrz = + !driQueryOptionb(config->options, "disable_conservative_lrz"); + screen->driconf.enable_throttling = + !driQueryOptionb(config->options, "disable_throttling"); + screen->driconf.dual_color_blend_by_location = + driQueryOptionb(config->options, "dual_color_blend_by_location"); + struct sysinfo si; sysinfo(&si); screen->ram_size = si.totalram; @@ -1028,13 +1187,14 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, DBG(" Chip-id: 0x%016"PRIx64, screen->chip_id); DBG(" GMEM size: 0x%08x", screen->gmemsize_bytes); - const struct fd_dev_info *info = fd_dev_info(screen->dev_id); - if (!info) { + const struct fd_dev_info info = fd_dev_info(screen->dev_id); + if (!info.chip) { mesa_loge("unsupported GPU: a%03d", screen->gpu_id); goto fail; } - screen->info = info; + screen->dev_info = info; + screen->info = &screen->dev_info; /* explicitly checking for GPU revisions that are known to work. This * may be overly conservative for a3xx, where spoofing the gpu_id with @@ -1071,7 +1231,7 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, /* fdN_screen_init() should set this: */ assert(screen->primtypes); screen->primtypes_mask = 0; - for (unsigned i = 0; i <= PIPE_PRIM_MAX; i++) + for (unsigned i = 0; i <= MESA_PRIM_COUNT; i++) if (screen->primtypes[i]) screen->primtypes_mask |= (1 << i); @@ -1087,6 +1247,8 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, if (fd_device_version(dev) >= FD_VERSION_UNLIMITED_CMDS) screen->reorder = !FD_DBG(INORDER); + fd_bc_init(&screen->batch_cache); + list_inithead(&screen->context_list); util_idalloc_mt_init_tc(&screen->buffer_ids); @@ -1094,6 +1256,8 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, (void)simple_mtx_init(&screen->lock, mtx_plain); pscreen->destroy = fd_screen_destroy; + pscreen->get_screen_fd = fd_screen_get_fd; + pscreen->query_memory_info = fd_query_memory_info; pscreen->get_param = fd_screen_get_param; pscreen->get_paramf = fd_screen_get_paramf; pscreen->get_shader_param = fd_screen_get_shader_param; @@ -1109,11 +1273,13 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, pscreen->get_vendor = fd_screen_get_vendor; pscreen->get_device_vendor = fd_screen_get_device_vendor; + pscreen->get_sample_pixel_grid = fd_get_sample_pixel_grid; + pscreen->get_timestamp = fd_screen_get_timestamp; pscreen->fence_reference = _fd_fence_ref; - pscreen->fence_finish = fd_fence_finish; - pscreen->fence_get_fd = fd_fence_get_fd; + pscreen->fence_finish = fd_pipe_fence_finish; + pscreen->fence_get_fd = fd_pipe_fence_get_fd; pscreen->query_dmabuf_modifiers = fd_screen_query_dmabuf_modifiers; pscreen->is_dmabuf_modifier_supported = @@ -1124,9 +1290,34 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, slab_create_parent(&screen->transfer_pool, sizeof(struct fd_transfer), 16); + simple_mtx_init(&screen->aux_ctx_lock, mtx_plain); + return pscreen; fail: fd_screen_destroy(pscreen); return NULL; } + +struct fd_context * +fd_screen_aux_context_get(struct pipe_screen *pscreen) +{ + struct fd_screen *screen = fd_screen(pscreen); + + simple_mtx_lock(&screen->aux_ctx_lock); + + if (!screen->aux_ctx) { + screen->aux_ctx = pscreen->context_create(pscreen, NULL, 0); + } + + return fd_context(screen->aux_ctx); +} + +void +fd_screen_aux_context_put(struct pipe_screen *pscreen) +{ + struct fd_screen *screen = fd_screen(pscreen); + + screen->aux_ctx->flush(screen->aux_ctx, NULL, 0); + simple_mtx_unlock(&screen->aux_ctx_lock); +} |