static unsigned nvfx_miptree_layout(struct nvfx_miptree *mt) { struct pipe_resource* pt = &mt->base.base; uint offset = 0; if(!nvfx_screen(pt->screen)->is_nv4x) { assert(pt->target == PIPE_TEXTURE_RECT || (util_is_power_of_two(pt->width0) && util_is_power_of_two(pt->height0))); } for (unsigned l = 0; l <= pt->last_level; l++) { unsigned size; mt->level_offset[l] = offset; if(mt->linear_pitch) size = mt->linear_pitch; else size = util_format_get_stride(pt->format, u_minify(pt->width0, l)); size = util_format_get_2d_size(pt->format, size, u_minify(pt->height0, l)); if(pt->target == PIPE_TEXTURE_3D) size *= u_minify(pt->depth0, l); offset += size; } offset = align(offset, 128); mt->face_size = offset; if(mt->base.base.target == PIPE_TEXTURE_CUBE) offset += 5 * mt->face_size; return offset; }
static void nvfx_miptree_choose_format(struct nvfx_miptree *mt) { struct pipe_resource *pt = &mt->base.base; unsigned uniform_pitch = 0; static int no_swizzle = -1; if(no_swizzle < 0) no_swizzle = debug_get_bool_option("NV40_NO_SWIZZLE", FALSE); /* this will break things on nv30 */ if (!util_is_power_of_two(pt->width0) || !util_is_power_of_two(pt->height0) || !util_is_power_of_two(pt->depth0) || (!nvfx_screen(pt->screen)->is_nv4x && pt->target == PIPE_TEXTURE_RECT) ) uniform_pitch = 1; if ( (pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET)) || (pt->usage & PIPE_USAGE_DYNAMIC) || (pt->usage & PIPE_USAGE_STAGING) || util_format_is_compressed(pt->format) || no_swizzle ) mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; /* non compressed formats with uniform pitch must be linear, and vice versa */ if(!util_format_is_s3tc(pt->format) && (uniform_pitch || mt->base.base.flags & NVFX_RESOURCE_FLAG_LINEAR)) { mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; uniform_pitch = 1; } if(uniform_pitch) { mt->linear_pitch = util_format_get_stride(pt->format, pt->width0); // TODO: this is only a constraint for rendering and not sampling, apparently // we may also want this unconditionally if(pt->bind & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT)) mt->linear_pitch = align(mt->linear_pitch, 64); } else mt->linear_pitch = 0; }
static void nvfx_screen_destroy(struct pipe_screen *pscreen) { struct nvfx_screen *screen = nvfx_screen(pscreen); nouveau_resource_destroy(&screen->vp_exec_heap); nouveau_resource_destroy(&screen->vp_data_heap); nouveau_resource_destroy(&screen->query_heap); nouveau_notifier_free(&screen->query); nouveau_notifier_free(&screen->sync); nouveau_grobj_free(&screen->eng3d); nvfx_screen_surface_takedown(pscreen); nouveau_screen_fini(&screen->base); FREE(pscreen); }
static float nvfx_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: case PIPE_CAP_MAX_LINE_WIDTH_AA: return 10.0; case PIPE_CAP_MAX_POINT_WIDTH: case PIPE_CAP_MAX_POINT_WIDTH_AA: return 64.0; case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: return screen->use_nv4x ? 16.0 : 8.0; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: return 15.0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0.0; } }
static int nvfx_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum pipe_shader_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); switch(shader) { case PIPE_SHADER_FRAGMENT: switch(param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: return 4096; case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: /* FIXME: is it the dynamic (nv30:0/nv40:24) or the static value (nv30:0/nv40:4) ? */ return screen->use_nv4x ? 4 : 0; case PIPE_SHADER_CAP_MAX_INPUTS: return screen->use_nv4x ? 12 : 10; case PIPE_SHADER_CAP_MAX_CONSTS: return screen->use_nv4x ? 224 : 32; case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return 1; case PIPE_SHADER_CAP_MAX_TEMPS: return 32; case PIPE_SHADER_CAP_MAX_ADDRS: return screen->use_nv4x ? 1 : 0; case PIPE_SHADER_CAP_MAX_PREDS: return 0; /* we could expose these, but nothing uses them */ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 0; default: break; } break; case PIPE_SHADER_VERTEX: switch(param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: return screen->use_nv4x ? 512 : 256; case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: return screen->use_nv4x ? 512 : 0; case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: /* FIXME: is it the dynamic (nv30:24/nv40:24) or the static value (nv30:1/nv40:4) ? */ return screen->use_nv4x ? 4 : 1; case PIPE_SHADER_CAP_MAX_INPUTS: return 16; case PIPE_SHADER_CAP_MAX_CONSTS: /* - 6 is for clip planes; Gallium should be fixed to put * them in the vertex shader itself, so we don't need to reserve these */ return (screen->use_nv4x ? 468 : 256) - 6; case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return 1; case PIPE_SHADER_CAP_MAX_TEMPS: return screen->use_nv4x ? 32 : 13; case PIPE_SHADER_CAP_MAX_ADDRS: return 2; case PIPE_SHADER_CAP_MAX_PREDS: return 0; /* we could expose these, but nothing uses them */ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 1; default: break; } break; default: break; } return 0; }
static int nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: return 16; case PIPE_CAP_NPOT_TEXTURES: return screen->advertise_npot; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_GLSL: return 1; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_MAX_RENDER_TARGETS: return screen->use_nv4x ? 4 : 2; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_TIMER_QUERY: return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 13; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 10; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return !!screen->use_nv4x; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; /* We have 4 on nv40 - but unsupported currently */ case PIPE_CAP_BLEND_EQUATION_SEPARATE: return screen->advertise_blend_equation_separate; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return 16; case PIPE_CAP_INDEP_BLEND_ENABLE: /* TODO: on nv40 we have separate color masks */ /* TODO: nv40 mrt blending is probably broken */ return 0; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: return 0; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; case PIPE_CAP_DEPTH_CLAMP: return 0; // TODO: implement depth clamp default: NOUVEAU_ERR("Warning: unknown PIPE_CAP %d\n", param); return 0; } }
static boolean nvfx_screen_is_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, unsigned bind, unsigned geom_flags) { struct nvfx_screen *screen = nvfx_screen(pscreen); if (sample_count > 1) return FALSE; if (bind & PIPE_BIND_RENDER_TARGET) { switch (format) { case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: case PIPE_FORMAT_B5G6R5_UNORM: break; case PIPE_FORMAT_R16G16B16A16_FLOAT: if(!screen->advertise_fp16) return FALSE; break; case PIPE_FORMAT_R32G32B32A32_FLOAT: if(!screen->advertise_fp32) return FALSE; break; default: return FALSE; } } if (bind & PIPE_BIND_DEPTH_STENCIL) { switch (format) { case PIPE_FORMAT_S8_USCALED_Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_Z16_UNORM: break; default: return FALSE; } } if (bind & PIPE_BIND_SAMPLER_VIEW) { struct nvfx_texture_format* tf = &nvfx_texture_formats[format]; if(util_format_is_s3tc(format) && !util_format_s3tc_enabled) return FALSE; if(format == PIPE_FORMAT_R16G16B16A16_FLOAT && !screen->advertise_fp16) return FALSE; if(format == PIPE_FORMAT_R32G32B32A32_FLOAT && !screen->advertise_fp32) return FALSE; if(screen->use_nv4x) { if(tf->fmt[4] < 0) return FALSE; } else { if(tf->fmt[0] < 0) return FALSE; } } // note that we do actually support everything through translate if (bind & PIPE_BIND_VERTEX_BUFFER) { unsigned type = nvfx_vertex_formats[format]; if(!type) return FALSE; } if (bind & PIPE_BIND_INDEX_BUFFER) { // 8-bit indices supported, but not in hardware index buffer if(format != PIPE_FORMAT_R16_USCALED && format != PIPE_FORMAT_R32_USCALED) return FALSE; } if(bind & PIPE_BIND_STREAM_OUTPUT) return FALSE; return TRUE; }
static int nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { struct nvfx_screen *screen = nvfx_screen(pscreen); switch (param) { case PIPE_CAP_NPOT_TEXTURES: return screen->advertise_npot; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_SM3: /* TODO: >= nv4x support Shader Model 3.0 */ return 0; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_MAX_RENDER_TARGETS: return screen->use_nv4x ? 4 : 1; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_TIMER_QUERY: return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 13; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 10; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return !!screen->use_nv4x; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return screen->advertise_blend_equation_separate; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return 16; case PIPE_CAP_INDEP_BLEND_ENABLE: /* TODO: on nv40 we have separate color masks */ /* TODO: nv40 mrt blending is probably broken */ return 0; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: return 0; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; case PIPE_CAP_DEPTH_CLIP_DISABLE: return 0; // TODO: implement depth clamp case PIPE_CAP_PRIMITIVE_RESTART: return 0; // TODO: implement primitive restart case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_MIN_TEXEL_OFFSET: case PIPE_CAP_MAX_TEXEL_OFFSET: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_BARRIER: return 0; case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: return 0; default: NOUVEAU_ERR("Warning: unknown PIPE_CAP %d\n", param); return 0; } }