Path: blob/21.2-virgl/src/gallium/drivers/v3d/v3d_context.c
4570 views
/*1* Copyright © 2014-2017 Broadcom2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include <xf86drm.h>24#include <err.h>2526#include "pipe/p_defines.h"27#include "util/hash_table.h"28#include "util/ralloc.h"29#include "util/u_inlines.h"30#include "util/u_memory.h"31#include "util/u_blitter.h"32#include "util/u_upload_mgr.h"33#include "util/u_prim.h"34#include "indices/u_primconvert.h"35#include "pipe/p_screen.h"3637#include "v3d_screen.h"38#include "v3d_context.h"39#include "v3d_resource.h"40#include "broadcom/compiler/v3d_compiler.h"4142void43v3d_flush(struct pipe_context *pctx)44{45struct v3d_context *v3d = v3d_context(pctx);4647hash_table_foreach(v3d->jobs, entry) {48struct v3d_job *job = entry->data;49v3d_job_submit(v3d, job);50}51}5253static void54v3d_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,55unsigned flags)56{57struct v3d_context *v3d = v3d_context(pctx);5859v3d_flush(pctx);6061if (fence) {62struct pipe_screen *screen = pctx->screen;63struct v3d_fence *f = v3d_fence_create(v3d);64screen->fence_reference(screen, fence, NULL);65*fence = (struct pipe_fence_handle *)f;66}67}6869static void70v3d_memory_barrier(struct pipe_context *pctx, unsigned int flags)71{72struct v3d_context *v3d = v3d_context(pctx);7374/* We only need to flush for SSBOs and images, because for everything75* else we flush the job automatically when we needed.76*/77const unsigned int flush_flags = PIPE_BARRIER_SHADER_BUFFER |78PIPE_BARRIER_IMAGE;7980if (!(flags & flush_flags))81return;8283/* We only need to flush jobs writing to SSBOs/images. */84perf_debug("Flushing all jobs for glMemoryBarrier(), could do better");85v3d_flush(pctx);86}8788static void89v3d_set_debug_callback(struct pipe_context *pctx,90const struct pipe_debug_callback *cb)91{92struct v3d_context *v3d = v3d_context(pctx);9394if (cb)95v3d->debug = *cb;96else97memset(&v3d->debug, 0, sizeof(v3d->debug));98}99100static void101v3d_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)102{103struct v3d_context *v3d = v3d_context(pctx);104struct v3d_resource *rsc = v3d_resource(prsc);105106rsc->initialized_buffers = 0;107108struct hash_entry *entry = _mesa_hash_table_search(v3d->write_jobs,109prsc);110if (!entry)111return;112113struct v3d_job *job = entry->data;114if (job->key.zsbuf && job->key.zsbuf->texture == prsc)115job->store &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL);116}117118/**119* Flushes the current job to get up-to-date primitive counts written to the120* primitive counts BO, then accumulates the transform feedback primitive count121* in the context and the corresponding vertex counts in the bound stream122* output targets.123*/124void125v3d_update_primitive_counters(struct v3d_context *v3d)126{127struct v3d_job *job = v3d_get_job_for_fbo(v3d);128if (job->draw_calls_queued == 0)129return;130131/* In order to get up-to-date primitive counts we need to submit132* the job for execution so we get the counts written to memory.133* Notice that this will require a sync wait for the buffer write.134*/135uint32_t prims_before = v3d->tf_prims_generated;136v3d_job_submit(v3d, job);137uint32_t prims_after = v3d->tf_prims_generated;138if (prims_before == prims_after)139return;140141enum pipe_prim_type prim_type = u_base_prim_type(v3d->prim_mode);142uint32_t num_verts = u_vertices_for_prims(prim_type,143prims_after - prims_before);144for (int i = 0; i < v3d->streamout.num_targets; i++) {145struct v3d_stream_output_target *so =146v3d_stream_output_target(v3d->streamout.targets[i]);147so->recorded_vertex_count += num_verts;148}149}150151bool152v3d_line_smoothing_enabled(struct v3d_context *v3d)153{154if (!v3d->rasterizer->base.line_smooth)155return false;156157/* According to the OpenGL docs, line smoothing shouldn’t be applied158* when multisampling159*/160if (v3d->job->msaa || v3d->rasterizer->base.multisample)161return false;162163if (v3d->framebuffer.nr_cbufs <= 0)164return false;165166struct pipe_surface *cbuf = v3d->framebuffer.cbufs[0];167if (!cbuf)168return false;169170/* Modifying the alpha for pure integer formats probably171* doesn’t make sense because we don’t know how the application172* uses the alpha value.173*/174if (util_format_is_pure_integer(cbuf->format))175return false;176177return true;178}179180float181v3d_get_real_line_width(struct v3d_context *v3d)182{183float width = v3d->rasterizer->base.line_width;184185if (v3d_line_smoothing_enabled(v3d)) {186/* If line smoothing is enabled then we want to add some extra187* pixels to the width in order to have some semi-transparent188* edges.189*/190width = floorf(M_SQRT2 * width) + 3;191}192193return width;194}195196void197v3d_flag_dirty_sampler_state(struct v3d_context *v3d,198enum pipe_shader_type shader)199{200switch (shader) {201case PIPE_SHADER_VERTEX:202v3d->dirty |= V3D_DIRTY_VERTTEX;203break;204case PIPE_SHADER_GEOMETRY:205v3d->dirty |= V3D_DIRTY_GEOMTEX;206break;207case PIPE_SHADER_FRAGMENT:208v3d->dirty |= V3D_DIRTY_FRAGTEX;209break;210case PIPE_SHADER_COMPUTE:211v3d->dirty |= V3D_DIRTY_COMPTEX;212break;213default:214unreachable("Unsupported shader stage");215}216}217218void219v3d_create_texture_shader_state_bo(struct v3d_context *v3d,220struct v3d_sampler_view *so)221{222if (v3d->screen->devinfo.ver >= 41)223v3d41_create_texture_shader_state_bo(v3d, so);224else225v3d33_create_texture_shader_state_bo(v3d, so);226}227228void229v3d_get_tile_buffer_size(bool is_msaa,230uint32_t nr_cbufs,231struct pipe_surface **cbufs,232struct pipe_surface *bbuf,233uint32_t *tile_width,234uint32_t *tile_height,235uint32_t *max_bpp)236{237static const uint8_t tile_sizes[] = {23864, 64,23964, 32,24032, 32,24132, 16,24216, 16,243};244int tile_size_index = 0;245if (is_msaa)246tile_size_index += 2;247248if (cbufs[3] || cbufs[2])249tile_size_index += 2;250else if (cbufs[1])251tile_size_index++;252253*max_bpp = 0;254for (int i = 0; i < nr_cbufs; i++) {255if (cbufs[i]) {256struct v3d_surface *surf = v3d_surface(cbufs[i]);257*max_bpp = MAX2(*max_bpp, surf->internal_bpp);258}259}260261if (bbuf) {262struct v3d_surface *bsurf = v3d_surface(bbuf);263assert(bbuf->texture->nr_samples <= 1 || is_msaa);264*max_bpp = MAX2(*max_bpp, bsurf->internal_bpp);265}266267tile_size_index += *max_bpp;268269assert(tile_size_index < ARRAY_SIZE(tile_sizes));270*tile_width = tile_sizes[tile_size_index * 2 + 0];271*tile_height = tile_sizes[tile_size_index * 2 + 1];272}273274static void275v3d_context_destroy(struct pipe_context *pctx)276{277struct v3d_context *v3d = v3d_context(pctx);278279v3d_flush(pctx);280281if (v3d->blitter)282util_blitter_destroy(v3d->blitter);283284if (v3d->primconvert)285util_primconvert_destroy(v3d->primconvert);286287if (v3d->uploader)288u_upload_destroy(v3d->uploader);289if (v3d->state_uploader)290u_upload_destroy(v3d->state_uploader);291292if (v3d->prim_counts)293pipe_resource_reference(&v3d->prim_counts, NULL);294295slab_destroy_child(&v3d->transfer_pool);296297pipe_surface_reference(&v3d->framebuffer.cbufs[0], NULL);298pipe_surface_reference(&v3d->framebuffer.zsbuf, NULL);299300if (v3d->sand8_blit_vs)301pctx->delete_vs_state(pctx, v3d->sand8_blit_vs);302if (v3d->sand8_blit_fs_luma)303pctx->delete_fs_state(pctx, v3d->sand8_blit_fs_luma);304if (v3d->sand8_blit_fs_chroma)305pctx->delete_fs_state(pctx, v3d->sand8_blit_fs_chroma);306307v3d_program_fini(pctx);308309ralloc_free(v3d);310}311312static void313v3d_get_sample_position(struct pipe_context *pctx,314unsigned sample_count, unsigned sample_index,315float *xy)316{317struct v3d_context *v3d = v3d_context(pctx);318319if (sample_count <= 1) {320xy[0] = 0.5;321xy[1] = 0.5;322} else {323static const int xoffsets_v33[] = { 1, -3, 3, -1 };324static const int xoffsets_v42[] = { -1, 3, -3, 1 };325const int *xoffsets = (v3d->screen->devinfo.ver >= 42 ?326xoffsets_v42 : xoffsets_v33);327328xy[0] = 0.5 + xoffsets[sample_index] * .125;329xy[1] = .125 + sample_index * .25;330}331}332333struct pipe_context *334v3d_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)335{336struct v3d_screen *screen = v3d_screen(pscreen);337struct v3d_context *v3d;338339/* Prevent dumping of the shaders built during context setup. */340uint32_t saved_shaderdb_flag = V3D_DEBUG & V3D_DEBUG_SHADERDB;341V3D_DEBUG &= ~V3D_DEBUG_SHADERDB;342343v3d = rzalloc(NULL, struct v3d_context);344if (!v3d)345return NULL;346struct pipe_context *pctx = &v3d->base;347348v3d->screen = screen;349350int ret = drmSyncobjCreate(screen->fd, DRM_SYNCOBJ_CREATE_SIGNALED,351&v3d->out_sync);352if (ret) {353ralloc_free(v3d);354return NULL;355}356357pctx->screen = pscreen;358pctx->priv = priv;359pctx->destroy = v3d_context_destroy;360pctx->flush = v3d_pipe_flush;361pctx->memory_barrier = v3d_memory_barrier;362pctx->set_debug_callback = v3d_set_debug_callback;363pctx->invalidate_resource = v3d_invalidate_resource;364pctx->get_sample_position = v3d_get_sample_position;365366if (screen->devinfo.ver >= 41) {367v3d41_draw_init(pctx);368v3d41_state_init(pctx);369} else {370v3d33_draw_init(pctx);371v3d33_state_init(pctx);372}373v3d_program_init(pctx);374v3d_query_init(pctx);375v3d_resource_context_init(pctx);376377v3d_job_init(v3d);378379v3d->fd = screen->fd;380381slab_create_child(&v3d->transfer_pool, &screen->transfer_pool);382383v3d->uploader = u_upload_create_default(&v3d->base);384v3d->base.stream_uploader = v3d->uploader;385v3d->base.const_uploader = v3d->uploader;386v3d->state_uploader = u_upload_create(&v3d->base,3874096,388PIPE_BIND_CONSTANT_BUFFER,389PIPE_USAGE_STREAM, 0);390391v3d->blitter = util_blitter_create(pctx);392if (!v3d->blitter)393goto fail;394v3d->blitter->use_index_buffer = true;395396v3d->primconvert = util_primconvert_create(pctx,397(1 << PIPE_PRIM_QUADS) - 1);398if (!v3d->primconvert)399goto fail;400401V3D_DEBUG |= saved_shaderdb_flag;402403v3d->sample_mask = (1 << V3D_MAX_SAMPLES) - 1;404v3d->active_queries = true;405406return &v3d->base;407408fail:409pctx->destroy(pctx);410return NULL;411}412413414