static bool tex_create_hiz(struct ilo_texture *tex) { const struct pipe_resource *templ = &tex->base; struct ilo_screen *is = ilo_screen(tex->base.screen); unsigned lv; tex->aux_bo = intel_winsys_alloc_bo(is->winsys, "hiz texture", INTEL_TILING_Y, tex->layout.aux_stride, tex->layout.aux_height, false); if (!tex->aux_bo) return false; for (lv = 0; lv <= templ->last_level; lv++) { if (tex->layout.aux_enables & (1 << lv)) { const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ? u_minify(templ->depth0, lv) : templ->array_size; unsigned flags = ILO_TEXTURE_HIZ; /* this will trigger a HiZ resolve */ if (tex->imported) flags |= ILO_TEXTURE_CPU_WRITE; ilo_texture_set_slice_flags(tex, lv, 0, num_slices, flags, flags); } } return true; }
static bool tex_init_layout(struct ilo_texture *tex) { struct ilo_screen *is = ilo_screen(tex->base.screen); const struct pipe_resource *templ = &tex->base; struct ilo_layout *layout = &tex->layout; ilo_layout_init(layout, &is->dev, templ); if (layout->bo_height > ilo_max_resource_size / layout->bo_stride) return false; if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) { /* require on-the-fly tiling/untiling or format conversion */ if (layout->separate_stencil || layout->format == PIPE_FORMAT_S8_UINT || layout->format != templ->format) return false; } if (!tex_alloc_slices(tex)) return false; return true; }
static uint64_t ilo_get_timestamp(struct pipe_screen *screen) { struct ilo_screen *is = ilo_screen(screen); union { uint64_t val; uint32_t dw[2]; } timestamp; intel_winsys_read_reg(is->winsys, TIMESTAMP, ×tamp.val); /* * From the Ivy Bridge PRM, volume 1 part 3, page 107: * * "Note: This timestamp register reflects the value of the PCU TSC. * The PCU TSC counts 10ns increments; this timestamp reflects bits * 38:3 of the TSC (i.e. 80ns granularity, rolling over every 1.5 * hours)." * * However, it seems dw[0] is garbage and dw[1] contains the lower 32 bits * of the timestamp. We will have to live with a timestamp that rolls over * every ~343 seconds. * * See also brw_get_timestamp(). */ return (uint64_t) timestamp.dw[1] * 80; }
static void tex_layout_init(struct tex_layout *layout, struct pipe_screen *screen, const struct pipe_resource *templ, struct ilo_texture_slice **slices) { struct ilo_screen *is = ilo_screen(screen); memset(layout, 0, sizeof(*layout)); layout->dev = &is->dev; layout->templ = templ; /* note that there are dependencies between these functions */ tex_layout_init_hiz(layout); tex_layout_init_format(layout); tex_layout_init_tiling(layout); tex_layout_init_spacing(layout); tex_layout_init_levels(layout); tex_layout_init_alignments(layout); tex_layout_init_qpitch(layout); if (slices) { int lv; for (lv = 0; lv <= templ->last_level; lv++) layout->levels[lv].slices = slices[lv]; } }
static void ilo_screen_destroy(struct pipe_screen *screen) { struct ilo_screen *is = ilo_screen(screen); /* as it seems, winsys is owned by the screen */ intel_winsys_destroy(is->winsys); FREE(is); }
static struct pipe_resource * buf_create(struct pipe_screen *screen, const struct pipe_resource *templ) { const struct ilo_screen *is = ilo_screen(screen); struct ilo_buffer *buf; buf = CALLOC_STRUCT(ilo_buffer); if (!buf) return NULL; buf->base = *templ; buf->base.screen = screen; pipe_reference_init(&buf->base.reference, 1); buf->bo_size = templ->width0; /* * From the Sandy Bridge PRM, volume 1 part 1, page 118: * * "For buffers, which have no inherent "height," padding requirements * are different. A buffer must be padded to the next multiple of 256 * array elements, with an additional 16 bytes added beyond that to * account for the L1 cache line." */ if (templ->bind & PIPE_BIND_SAMPLER_VIEW) buf->bo_size = align(buf->bo_size, 256) + 16; if ((templ->bind & PIPE_BIND_VERTEX_BUFFER) && ilo_dev_gen(&is->dev) < ILO_GEN(7.5)) { /* * As noted in ilo_translate_format(), we treat some 3-component formats * as 4-component formats to work around hardware limitations. Imagine * the case where the vertex buffer holds a single * PIPE_FORMAT_R16G16B16_FLOAT vertex, and buf->bo_size is 6. The * hardware would fail to fetch it at boundary check because the vertex * buffer is expected to hold a PIPE_FORMAT_R16G16B16A16_FLOAT vertex * and that takes at least 8 bytes. * * For the workaround to work, we should add 2 to the bo size. But that * would waste a page when the bo size is already page aligned. Let's * round it to page size for now and revisit this when needed. */ buf->bo_size = align(buf->bo_size, 4096); } if (buf->bo_size < templ->width0 || buf->bo_size > ilo_max_resource_size || !buf_create_bo(buf)) { FREE(buf); return NULL; } return &buf->base; }
static bool tex_get_handle(struct ilo_texture *tex, struct winsys_handle *handle) { struct ilo_screen *is = ilo_screen(tex->base.screen); int err; err = intel_winsys_export_handle(is->winsys, tex->bo, tex->layout.tiling, tex->layout.bo_stride, tex->layout.bo_height, handle); return !err; }
static bool buf_create_bo(struct ilo_buffer *buf) { struct ilo_screen *is = ilo_screen(buf->base.screen); const char *name = resource_get_bo_name(&buf->base); const bool cpu_init = resource_get_cpu_init(&buf->base); buf->bo = intel_winsys_alloc_buffer(is->winsys, name, buf->bo_size, cpu_init); return (buf->bo != NULL); }
static bool tex_create_bo(struct ilo_texture *tex) { struct ilo_screen *is = ilo_screen(tex->base.screen); const char *name = resource_get_bo_name(&tex->base); const bool cpu_init = resource_get_cpu_init(&tex->base); tex->bo = intel_winsys_alloc_bo(is->winsys, name, tex->layout.tiling, tex->layout.bo_stride, tex->layout.bo_height, cpu_init); return (tex->bo != NULL); }
static bool tex_create_bo(struct ilo_texture *tex) { struct ilo_screen *is = ilo_screen(tex->base.screen); const char *name = resource_get_bo_name(&tex->base); const enum intel_domain_flag initial_domain = resource_get_bo_initial_domain(&tex->base); tex->bo = intel_winsys_alloc_bo(is->winsys, name, tex->layout.tiling, tex->layout.bo_stride, tex->layout.bo_height, initial_domain); return (tex->bo != NULL); }
static bool buf_create_bo(struct ilo_buffer *buf) { struct ilo_screen *is = ilo_screen(buf->base.screen); const char *name = resource_get_bo_name(&buf->base); const enum intel_domain_flag initial_domain = resource_get_bo_initial_domain(&buf->base); buf->bo = intel_winsys_alloc_buffer(is->winsys, name, buf->bo_size, initial_domain); return (buf->bo != NULL); }
static boolean ilo_can_create_resource(struct pipe_screen *screen, const struct pipe_resource *templ) { struct ilo_layout layout; if (templ->target == PIPE_BUFFER) return (templ->width0 <= ilo_max_resource_size); memset(&layout, 0, sizeof(layout)); ilo_layout_init(&layout, &ilo_screen(screen)->dev, templ); return (layout.bo_height <= ilo_max_resource_size / layout.bo_stride); }
static bool tex_create_mcs(struct ilo_texture *tex) { struct ilo_screen *is = ilo_screen(tex->base.screen); assert(tex->layout.aux_enables == (1 << (tex->base.last_level + 1)) - 1); tex->aux_bo = intel_winsys_alloc_bo(is->winsys, "mcs texture", INTEL_TILING_Y, tex->layout.aux_stride, tex->layout.aux_height, false); if (!tex->aux_bo) return false; return true; }
static bool tex_import_handle(struct ilo_texture *tex, const struct winsys_handle *handle) { struct ilo_screen *is = ilo_screen(tex->base.screen); const char *name = resource_get_bo_name(&tex->base); enum intel_tiling_mode tiling; unsigned long pitch; tex->bo = intel_winsys_import_handle(is->winsys, name, handle, tex->layout.bo_height, &tiling, &pitch); if (!tex->bo) return false; if (!ilo_layout_update_for_imported_bo(&tex->layout, tiling, pitch)) { ilo_err("imported handle has incompatible tiling/pitch\n"); intel_bo_unreference(tex->bo); tex->bo = NULL; return false; } return true; }
static bool tex_alloc_bos(struct ilo_texture *tex, const struct winsys_handle *handle) { struct ilo_screen *is = ilo_screen(tex->base.screen); if (handle) { if (!tex_import_handle(tex, handle)) return false; } else { if (!tex_create_bo(tex)) return false; } /* allocate separate stencil resource */ if (tex->layout.separate_stencil && !tex_create_separate_stencil(tex)) return false; switch (tex->layout.aux) { case ILO_LAYOUT_AUX_HIZ: if (!tex_create_hiz(tex)) { /* Separate Stencil Buffer requires HiZ to be enabled */ if (ilo_dev_gen(&is->dev) == ILO_GEN(6) && tex->layout.separate_stencil) return false; } break; case ILO_LAYOUT_AUX_MCS: if (!tex_create_mcs(tex)) return false; break; default: break; } return true; }
static bool buf_create_bo(struct ilo_buffer *buf) { struct ilo_screen *is = ilo_screen(buf->base.screen); const char *name; struct intel_bo *bo; switch (buf->base.bind) { case PIPE_BIND_VERTEX_BUFFER: name = "vertex buffer"; break; case PIPE_BIND_INDEX_BUFFER: name = "index buffer"; break; case PIPE_BIND_CONSTANT_BUFFER: name = "constant buffer"; break; case PIPE_BIND_STREAM_OUTPUT: name = "stream output"; break; default: name = "unknown buffer"; break; } bo = intel_winsys_alloc_buffer(is->winsys, name, buf->bo_size, buf->bo_flags); if (!bo) return false; if (buf->bo) intel_bo_unreference(buf->bo); buf->bo = bo; return true; }
static bool tex_create_bo(struct ilo_texture *tex, const struct winsys_handle *handle) { struct ilo_screen *is = ilo_screen(tex->base.screen); const char *name; struct intel_bo *bo; enum intel_tiling_mode tiling; unsigned long pitch; switch (tex->base.target) { case PIPE_TEXTURE_1D: name = "1D texture"; break; case PIPE_TEXTURE_2D: name = "2D texture"; break; case PIPE_TEXTURE_3D: name = "3D texture"; break; case PIPE_TEXTURE_CUBE: name = "cube texture"; break; case PIPE_TEXTURE_RECT: name = "rectangle texture"; break; case PIPE_TEXTURE_1D_ARRAY: name = "1D array texture"; break; case PIPE_TEXTURE_2D_ARRAY: name = "2D array texture"; break; case PIPE_TEXTURE_CUBE_ARRAY: name = "cube array texture"; break; default: name ="unknown texture"; break; } if (handle) { bo = intel_winsys_import_handle(is->winsys, name, handle, tex->bo_width, tex->bo_height, tex->bo_cpp, &tiling, &pitch); } else { bo = intel_winsys_alloc_texture(is->winsys, name, tex->bo_width, tex->bo_height, tex->bo_cpp, tex->tiling, tex->bo_flags, &pitch); tiling = tex->tiling; } if (!bo) return false; if (tex->bo) intel_bo_unreference(tex->bo); tex->bo = bo; tex->tiling = tiling; tex->bo_stride = pitch; return true; }
static struct pipe_context * ilo_context_create(struct pipe_screen *screen, void *priv) { struct ilo_screen *is = ilo_screen(screen); struct ilo_context *ilo; ilo = CALLOC_STRUCT(ilo_context); if (!ilo) return NULL; ilo->winsys = is->winsys; ilo->dev = &is->dev; /* * initialize first, otherwise it may not be safe to call * ilo_context_destroy() on errors */ util_slab_create(&ilo->transfer_mempool, sizeof(struct ilo_transfer), 64, UTIL_SLAB_SINGLETHREADED); /* 8192 DWords */ ilo->cp = ilo_cp_create(ilo->winsys, 8192, is->dev.has_llc); ilo->shader_cache = ilo_shader_cache_create(); if (ilo->cp) ilo->hw3d = ilo_3d_create(ilo->cp, ilo->dev); if (!ilo->cp || !ilo->shader_cache || !ilo->hw3d) { ilo_context_destroy(&ilo->base); return NULL; } ilo_cp_set_flush_callback(ilo->cp, ilo_context_cp_flushed, (void *) ilo); ilo->base.screen = screen; ilo->base.priv = priv; ilo->base.destroy = ilo_context_destroy; ilo->base.flush = ilo_flush; ilo_init_3d_functions(ilo); ilo_init_query_functions(ilo); ilo_init_state_functions(ilo); ilo_init_blit_functions(ilo); ilo_init_transfer_functions(ilo); ilo_init_video_functions(ilo); ilo_init_gpgpu_functions(ilo); ilo_init_states(ilo); /* * These must be called last as u_upload/u_blitter are clients of the pipe * context. */ ilo->uploader = u_upload_create(&ilo->base, 1024 * 1024, 16, PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_INDEX_BUFFER); if (!ilo->uploader) { ilo_context_destroy(&ilo->base); return NULL; } ilo->blitter = ilo_blitter_create(ilo); if (!ilo->blitter) { ilo_context_destroy(&ilo->base); return NULL; } return &ilo->base; }
static const char * ilo_get_name(struct pipe_screen *screen) { struct ilo_screen *is = ilo_screen(screen); const char *chipset; /* stolen from classic i965 */ switch (is->dev.devid) { case PCI_CHIP_SANDYBRIDGE_GT1: case PCI_CHIP_SANDYBRIDGE_GT2: case PCI_CHIP_SANDYBRIDGE_GT2_PLUS: chipset = "Intel(R) Sandybridge Desktop"; break; case PCI_CHIP_SANDYBRIDGE_M_GT1: case PCI_CHIP_SANDYBRIDGE_M_GT2: case PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS: chipset = "Intel(R) Sandybridge Mobile"; break; case PCI_CHIP_SANDYBRIDGE_S: chipset = "Intel(R) Sandybridge Server"; break; case PCI_CHIP_IVYBRIDGE_GT1: case PCI_CHIP_IVYBRIDGE_GT2: chipset = "Intel(R) Ivybridge Desktop"; break; case PCI_CHIP_IVYBRIDGE_M_GT1: case PCI_CHIP_IVYBRIDGE_M_GT2: chipset = "Intel(R) Ivybridge Mobile"; break; case PCI_CHIP_IVYBRIDGE_S_GT1: case PCI_CHIP_IVYBRIDGE_S_GT2: chipset = "Intel(R) Ivybridge Server"; break; case PCI_CHIP_BAYTRAIL_M_1: case PCI_CHIP_BAYTRAIL_M_2: case PCI_CHIP_BAYTRAIL_M_3: case PCI_CHIP_BAYTRAIL_M_4: case PCI_CHIP_BAYTRAIL_D: chipset = "Intel(R) Bay Trail"; break; case PCI_CHIP_HASWELL_GT1: case PCI_CHIP_HASWELL_GT2: case PCI_CHIP_HASWELL_GT3: case PCI_CHIP_HASWELL_SDV_GT1: case PCI_CHIP_HASWELL_SDV_GT2: case PCI_CHIP_HASWELL_SDV_GT3: case PCI_CHIP_HASWELL_ULT_GT1: case PCI_CHIP_HASWELL_ULT_GT2: case PCI_CHIP_HASWELL_ULT_GT3: case PCI_CHIP_HASWELL_CRW_GT1: case PCI_CHIP_HASWELL_CRW_GT2: case PCI_CHIP_HASWELL_CRW_GT3: chipset = "Intel(R) Haswell Desktop"; break; case PCI_CHIP_HASWELL_M_GT1: case PCI_CHIP_HASWELL_M_GT2: case PCI_CHIP_HASWELL_M_GT3: case PCI_CHIP_HASWELL_SDV_M_GT1: case PCI_CHIP_HASWELL_SDV_M_GT2: case PCI_CHIP_HASWELL_SDV_M_GT3: case PCI_CHIP_HASWELL_ULT_M_GT1: case PCI_CHIP_HASWELL_ULT_M_GT2: case PCI_CHIP_HASWELL_ULT_M_GT3: case PCI_CHIP_HASWELL_CRW_M_GT1: case PCI_CHIP_HASWELL_CRW_M_GT2: case PCI_CHIP_HASWELL_CRW_M_GT3: chipset = "Intel(R) Haswell Mobile"; break; case PCI_CHIP_HASWELL_S_GT1: case PCI_CHIP_HASWELL_S_GT2: case PCI_CHIP_HASWELL_S_GT3: case PCI_CHIP_HASWELL_SDV_S_GT1: case PCI_CHIP_HASWELL_SDV_S_GT2: case PCI_CHIP_HASWELL_SDV_S_GT3: case PCI_CHIP_HASWELL_ULT_S_GT1: case PCI_CHIP_HASWELL_ULT_S_GT2: case PCI_CHIP_HASWELL_ULT_S_GT3: case PCI_CHIP_HASWELL_CRW_S_GT1: case PCI_CHIP_HASWELL_CRW_S_GT2: case PCI_CHIP_HASWELL_CRW_S_GT3: chipset = "Intel(R) Haswell Server"; break; default: chipset = "Unknown Intel Chipset"; break; } return chipset; }
static int ilo_get_param(struct pipe_screen *screen, enum pipe_cap param) { struct ilo_screen *is = ilo_screen(screen); switch (param) { case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_TWO_SIDED_STENCIL: return true; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: return 0; /* TODO */ case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_POINT_SPRITE: return true; case PIPE_CAP_MAX_RENDER_TARGETS: return ILO_MAX_DRAW_BUFFERS; case PIPE_CAP_OCCLUSION_QUERY: case PIPE_CAP_QUERY_TIME_ELAPSED: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_TEXTURE_SWIZZLE: /* must be supported for shadow map */ return true; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: /* * As defined in SURFACE_STATE, we have * * Max WxHxD for 2D and CUBE Max WxHxD for 3D * GEN6 8192x8192x512 2048x2048x2048 * GEN7 16384x16384x2048 2048x2048x2048 * * However, when the texutre size is large, things become unstable. We * require the maximum texture size to be 2^30 bytes in * screen->can_create_resource(). Since the maximum pixel size is 2^4 * bytes (PIPE_FORMAT_R32G32B32A32_FLOAT), textures should not have more * than 2^26 pixels. * * For 3D textures, we have to set the maximum number of levels to 9, * which has at most 2^24 pixels. For 2D textures, we set it to 14, * which has at most 2^26 pixels. And for cube textures, we has to set * it to 12. */ return 14; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 9; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 12; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return false; case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_SM3: return true; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: if (is->dev.gen >= ILO_GEN(7) && !is->dev.has_gen7_sol_reset) return 0; return ILO_MAX_SO_BUFFERS; case PIPE_CAP_PRIMITIVE_RESTART: return true; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return ILO_MAX_SAMPLERS * 2; case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: return true; case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: return (is->dev.gen >= ILO_GEN(7)) ? 2048 : 512; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 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_PIXEL_CENTER_INTEGER: case PIPE_CAP_DEPTH_CLIP_DISABLE: return true; case PIPE_CAP_SHADER_STENCIL_EXPORT: return false; case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: return true; case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: return false; case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: return true; case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_SCALED_RESOLVE: return true; case PIPE_CAP_MIN_TEXEL_OFFSET: return -8; case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_BARRIER: return true; case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: return ILO_MAX_SO_BINDINGS / ILO_MAX_SO_BUFFERS; case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: return ILO_MAX_SO_BINDINGS; case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: if (is->dev.gen >= ILO_GEN(7)) return is->dev.has_gen7_sol_reset; else return false; /* TODO */ case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: return false; case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: return true; case PIPE_CAP_VERTEX_COLOR_CLAMPED: return false; case PIPE_CAP_GLSL_FEATURE_LEVEL: return 140; case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_USER_VERTEX_BUFFERS: return false; 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 false; case PIPE_CAP_COMPUTE: return false; /* TODO */ case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_USER_CONSTANT_BUFFERS: return true; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: /* imposed by OWord (Dual) Block Read */ return 16; case PIPE_CAP_START_INSTANCE: case PIPE_CAP_QUERY_TIMESTAMP: return true; case PIPE_CAP_TEXTURE_MULTISAMPLE: return false; /* TODO */ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return 0; case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: return true; case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: return 1; case PIPE_CAP_TGSI_TEXCOORD: return false; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return true; case PIPE_CAP_QUERY_PIPELINE_STATISTICS: return false; /* TODO */ case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: /* a BRW_SURFACE_BUFFER can have up to 2^27 elements */ return 1 << 27; case PIPE_CAP_MAX_VIEWPORTS: return ILO_MAX_VIEWPORTS; case PIPE_CAP_ENDIANNESS: return PIPE_ENDIAN_LITTLE; default: return 0; } }
static struct pipe_context * ilo_context_create(struct pipe_screen *screen, void *priv, unsigned flags) { struct ilo_screen *is = ilo_screen(screen); struct ilo_context *ilo; ilo = CALLOC_STRUCT(ilo_context); if (!ilo) return NULL; ilo->winsys = is->dev.winsys; ilo->dev = &is->dev; /* * initialize first, otherwise it may not be safe to call * ilo_context_destroy() on errors */ slab_create(&ilo->transfer_mempool, sizeof(struct ilo_transfer), 64); ilo->shader_cache = ilo_shader_cache_create(); ilo->cp = ilo_cp_create(ilo->dev, ilo->winsys, ilo->shader_cache); if (ilo->cp) ilo->render = ilo_render_create(&ilo->cp->builder); if (!ilo->cp || !ilo->shader_cache || !ilo->render) { ilo_context_destroy(&ilo->base); return NULL; } ilo_cp_set_submit_callback(ilo->cp, ilo_context_cp_submitted, (void *) ilo); ilo->base.screen = screen; ilo->base.priv = priv; ilo->base.destroy = ilo_context_destroy; ilo->base.flush = ilo_flush; ilo->base.render_condition = ilo_render_condition; ilo_init_draw_functions(ilo); ilo_init_query_functions(ilo); ilo_init_state_functions(ilo); ilo_init_blit_functions(ilo); ilo_init_transfer_functions(ilo); ilo_init_video_functions(ilo); ilo_init_gpgpu_functions(ilo); ilo_init_draw(ilo); ilo_state_vector_init(ilo->dev, &ilo->state_vector); /* * These must be called last as u_upload/u_blitter are clients of the pipe * context. */ ilo->uploader = u_upload_create(&ilo->base, 1024 * 1024, PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM); if (!ilo->uploader) { ilo_context_destroy(&ilo->base); return NULL; } ilo->blitter = ilo_blitter_create(ilo); if (!ilo->blitter) { ilo_context_destroy(&ilo->base); return NULL; } return &ilo->base; }
static bool tex_create_hiz(struct ilo_texture *tex, const struct tex_layout *layout) { struct ilo_screen *is = ilo_screen(tex->base.screen); const struct pipe_resource *templ = layout->templ; const int hz_align_j = 8; unsigned hz_width, hz_height, lv; unsigned long pitch; /* * See the Sandy Bridge PRM, volume 2 part 1, page 312, and the Ivy Bridge * PRM, volume 2 part 1, page 312-313. * * It seems HiZ buffer is aligned to 8x8, with every two rows packed into a * memory row. */ hz_width = align(layout->levels[0].w, 16); if (templ->target == PIPE_TEXTURE_3D) { hz_height = 0; for (lv = 0; lv <= templ->last_level; lv++) { const unsigned h = align(layout->levels[lv].h, hz_align_j); hz_height += h * layout->levels[lv].d; } hz_height /= 2; } else { const unsigned h0 = align(layout->levels[0].h, hz_align_j); unsigned hz_qpitch = h0; if (layout->array_spacing_full) { const unsigned h1 = align(layout->levels[1].h, hz_align_j); const unsigned htail = ((layout->dev->gen >= ILO_GEN(7)) ? 12 : 11) * hz_align_j; hz_qpitch += h1 + htail; } hz_height = hz_qpitch * templ->array_size / 2; if (layout->dev->gen >= ILO_GEN(7)) hz_height = align(hz_height, 8); } tex->hiz.bo = intel_winsys_alloc_texture(is->winsys, "hiz texture", hz_width, hz_height, 1, INTEL_TILING_Y, INTEL_ALLOC_FOR_RENDER, &pitch); if (!tex->hiz.bo) return false; tex->hiz.bo_stride = pitch; /* * From the Sandy Bridge PRM, volume 2 part 1, page 313-314: * * "A rectangle primitive representing the clear area is delivered. The * primitive must adhere to the following restrictions on size: * * - If Number of Multisamples is NUMSAMPLES_1, the rectangle must be * aligned to an 8x4 pixel block relative to the upper left corner * of the depth buffer, and contain an integer number of these pixel * blocks, and all 8x4 pixels must be lit. * * - If Number of Multisamples is NUMSAMPLES_4, the rectangle must be * aligned to a 4x2 pixel block (8x4 sample block) relative to the * upper left corner of the depth buffer, and contain an integer * number of these pixel blocks, and all samples of the 4x2 pixels * must be lit * * - If Number of Multisamples is NUMSAMPLES_8, the rectangle must be * aligned to a 2x2 pixel block (8x4 sample block) relative to the * upper left corner of the depth buffer, and contain an integer * number of these pixel blocks, and all samples of the 2x2 pixels * must be list." * * "The following is required when performing a depth buffer resolve: * * - A rectangle primitive of the same size as the previous depth * buffer clear operation must be delivered, and depth buffer state * cannot have changed since the previous depth buffer clear * operation." * * Experiments on Haswell show that depth buffer resolves have the same * alignment requirements, and aligning the RECTLIST primitive and * 3DSTATE_DRAWING_RECTANGLE alone are not enough. The mipmap size must be * aligned. */ for (lv = 0; lv <= templ->last_level; lv++) { unsigned align_w = 8, align_h = 4; switch (templ->nr_samples) { case 0: case 1: break; case 2: align_w /= 2; break; case 4: align_w /= 2; align_h /= 2; break; case 8: default: align_w /= 4; align_h /= 2; break; } if (u_minify(templ->width0, lv) % align_w == 0 && u_minify(templ->height0, lv) % align_h == 0) { const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ? u_minify(templ->depth0, lv) : templ->array_size; ilo_texture_set_slice_flags(tex, lv, 0, num_slices, ILO_TEXTURE_HIZ, ILO_TEXTURE_HIZ); } } return true; }