summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/freedreno/freedreno_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_screen.c')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_screen.c423
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);
+}