Path: blob/21.2-virgl/src/gallium/drivers/svga/svga_context.c
4570 views
/**********************************************************1* Copyright 2008-2009 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**********************************************************/2425#include "svga_cmd.h"2627#include "pipe/p_defines.h"28#include "util/u_inlines.h"29#include "pipe/p_screen.h"30#include "util/u_memory.h"31#include "util/u_bitmask.h"32#include "util/u_upload_mgr.h"3334#include "svga_context.h"35#include "svga_screen.h"36#include "svga_surface.h"37#include "svga_resource_texture.h"38#include "svga_resource_buffer.h"39#include "svga_resource.h"40#include "svga_winsys.h"41#include "svga_swtnl.h"42#include "svga_draw.h"43#include "svga_debug.h"44#include "svga_state.h"45#include "svga_winsys.h"46#include "svga_streamout.h"4748#define CONST0_UPLOAD_DEFAULT_SIZE 655364950DEBUG_GET_ONCE_BOOL_OPTION(no_swtnl, "SVGA_NO_SWTNL", FALSE)51DEBUG_GET_ONCE_BOOL_OPTION(force_swtnl, "SVGA_FORCE_SWTNL", FALSE);52DEBUG_GET_ONCE_BOOL_OPTION(use_min_mipmap, "SVGA_USE_MIN_MIPMAP", FALSE);53DEBUG_GET_ONCE_BOOL_OPTION(no_line_width, "SVGA_NO_LINE_WIDTH", FALSE);54DEBUG_GET_ONCE_BOOL_OPTION(force_hw_line_stipple, "SVGA_FORCE_HW_LINE_STIPPLE", FALSE);555657static void58svga_destroy(struct pipe_context *pipe)59{60struct svga_context *svga = svga_context(pipe);61unsigned shader, i;6263/* free any alternate rasterizer states used for point sprite */64for (i = 0; i < ARRAY_SIZE(svga->rasterizer_no_cull); i++) {65if (svga->rasterizer_no_cull[i]) {66pipe->delete_rasterizer_state(pipe, svga->rasterizer_no_cull[i]);67}68}6970/* free depthstencil_disable state */71if (svga->depthstencil_disable) {72pipe->delete_depth_stencil_alpha_state(pipe, svga->depthstencil_disable);73}7475/* free HW constant buffers */76for (shader = 0; shader < ARRAY_SIZE(svga->state.hw_draw.constbuf); shader++) {77for (i = 0; i < ARRAY_SIZE(svga->state.hw_draw.constbuf[0]); i++) {78pipe_resource_reference(&svga->state.hw_draw.constbuf[shader][i], NULL);79}80}8182pipe->delete_blend_state(pipe, svga->noop_blend);8384/* destroy stream output statistics queries */85svga_destroy_stream_output_queries(svga);8687/* free query gb object */88if (svga->gb_query) {89pipe->destroy_query(pipe, NULL);90svga->gb_query = NULL;91}9293util_blitter_destroy(svga->blitter);9495svga_cleanup_sampler_state(svga);96svga_cleanup_framebuffer(svga);97svga_cleanup_tss_binding(svga);98svga_cleanup_vertex_state(svga);99svga_cleanup_tcs_state(svga);100101svga_destroy_swtnl(svga);102svga_hwtnl_destroy(svga->hwtnl);103104svga->swc->destroy(svga->swc);105106util_bitmask_destroy(svga->blend_object_id_bm);107util_bitmask_destroy(svga->ds_object_id_bm);108util_bitmask_destroy(svga->input_element_object_id_bm);109util_bitmask_destroy(svga->rast_object_id_bm);110util_bitmask_destroy(svga->sampler_object_id_bm);111util_bitmask_destroy(svga->sampler_view_id_bm);112util_bitmask_destroy(svga->shader_id_bm);113util_bitmask_destroy(svga->surface_view_id_bm);114util_bitmask_destroy(svga->stream_output_id_bm);115util_bitmask_destroy(svga->query_id_bm);116u_upload_destroy(svga->const0_upload);117u_upload_destroy(svga->pipe.stream_uploader);118u_upload_destroy(svga->pipe.const_uploader);119svga_texture_transfer_map_upload_destroy(svga);120121/* free user's constant buffers */122for (shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {123for (i = 0; i < ARRAY_SIZE(svga->curr.constbufs[shader]); ++i) {124pipe_resource_reference(&svga->curr.constbufs[shader][i].buffer, NULL);125}126}127128FREE(svga);129}130131132struct pipe_context *133svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)134{135struct svga_screen *svgascreen = svga_screen(screen);136struct svga_context *svga = NULL;137enum pipe_error ret;138139SVGA_STATS_TIME_PUSH(svgascreen->sws, SVGA_STATS_TIME_CREATECONTEXT);140141svga = CALLOC_STRUCT(svga_context);142if (!svga)143goto done;144145list_inithead(&svga->dirty_buffers);146147svga->pipe.screen = screen;148svga->pipe.priv = priv;149svga->pipe.destroy = svga_destroy;150svga->pipe.stream_uploader = u_upload_create(&svga->pipe, 1024 * 1024,151PIPE_BIND_VERTEX_BUFFER |152PIPE_BIND_INDEX_BUFFER,153PIPE_USAGE_STREAM, 0);154if (!svga->pipe.stream_uploader)155goto cleanup;156157u_upload_disable_persistent(svga->pipe.stream_uploader);158159svga->pipe.const_uploader = u_upload_create(&svga->pipe, 128 * 1024,160PIPE_BIND_CONSTANT_BUFFER,161PIPE_USAGE_STREAM, 0);162if (!svga->pipe.const_uploader)163goto cleanup;164165u_upload_disable_persistent(svga->pipe.const_uploader);166167svga->swc = svgascreen->sws->context_create(svgascreen->sws);168if (!svga->swc)169goto cleanup;170171svga_init_resource_functions(svga);172svga_init_blend_functions(svga);173svga_init_blit_functions(svga);174svga_init_depth_stencil_functions(svga);175svga_init_draw_functions(svga);176svga_init_flush_functions(svga);177svga_init_misc_functions(svga);178svga_init_rasterizer_functions(svga);179svga_init_sampler_functions(svga);180svga_init_fs_functions(svga);181svga_init_vs_functions(svga);182svga_init_gs_functions(svga);183svga_init_ts_functions(svga);184svga_init_vertex_functions(svga);185svga_init_constbuffer_functions(svga);186svga_init_query_functions(svga);187svga_init_surface_functions(svga);188svga_init_stream_output_functions(svga);189svga_init_clear_functions(svga);190svga_init_tracked_state(svga);191192/* init misc state */193svga->curr.sample_mask = ~0;194195/* debug */196svga->debug.no_swtnl = debug_get_option_no_swtnl();197svga->debug.force_swtnl = debug_get_option_force_swtnl();198svga->debug.use_min_mipmap = debug_get_option_use_min_mipmap();199svga->debug.no_line_width = debug_get_option_no_line_width();200svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple();201202if (!(svga->blend_object_id_bm = util_bitmask_create()))203goto cleanup;204205if (!(svga->ds_object_id_bm = util_bitmask_create()))206goto cleanup;207208if (!(svga->input_element_object_id_bm = util_bitmask_create()))209goto cleanup;210211if (!(svga->rast_object_id_bm = util_bitmask_create()))212goto cleanup;213214if (!(svga->sampler_object_id_bm = util_bitmask_create()))215goto cleanup;216217if (!(svga->sampler_view_id_bm = util_bitmask_create()))218goto cleanup;219220if (!(svga->shader_id_bm = util_bitmask_create()))221goto cleanup;222223if (!(svga->surface_view_id_bm = util_bitmask_create()))224goto cleanup;225226if (!(svga->stream_output_id_bm = util_bitmask_create()))227goto cleanup;228229if (!(svga->query_id_bm = util_bitmask_create()))230goto cleanup;231232svga->hwtnl = svga_hwtnl_create(svga);233if (svga->hwtnl == NULL)234goto cleanup;235236if (!svga_init_swtnl(svga))237goto cleanup;238239ret = svga_emit_initial_state(svga);240if (ret != PIPE_OK)241goto cleanup;242243svga->const0_upload = u_upload_create(&svga->pipe,244CONST0_UPLOAD_DEFAULT_SIZE,245PIPE_BIND_CONSTANT_BUFFER |246PIPE_BIND_CUSTOM,247PIPE_USAGE_STREAM, 0);248if (!svga->const0_upload)249goto cleanup;250251u_upload_disable_persistent(svga->const0_upload);252253if (!svga_texture_transfer_map_upload_create(svga))254goto cleanup;255256/* Avoid shortcircuiting state with initial value of zero.257*/258memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear));259memset(&svga->state.hw_clear.framebuffer, 0x0,260sizeof(svga->state.hw_clear.framebuffer));261memset(&svga->state.hw_clear.rtv, 0, sizeof(svga->state.hw_clear.rtv));262svga->state.hw_clear.num_rendertargets = 0;263svga->state.hw_clear.dsv = NULL;264265memset(&svga->state.hw_draw, 0xcd, sizeof(svga->state.hw_draw));266memset(&svga->state.hw_draw.views, 0x0, sizeof(svga->state.hw_draw.views));267memset(&svga->state.hw_draw.num_samplers, 0,268sizeof(svga->state.hw_draw.num_samplers));269memset(&svga->state.hw_draw.num_sampler_views, 0,270sizeof(svga->state.hw_draw.num_sampler_views));271memset(svga->state.hw_draw.sampler_views, 0,272sizeof(svga->state.hw_draw.sampler_views));273svga->state.hw_draw.num_views = 0;274svga->state.hw_draw.num_backed_views = 0;275svga->state.hw_draw.rasterizer_discard = FALSE;276277/* Initialize the shader pointers */278svga->state.hw_draw.vs = NULL;279svga->state.hw_draw.gs = NULL;280svga->state.hw_draw.fs = NULL;281svga->state.hw_draw.tcs = NULL;282svga->state.hw_draw.tes = NULL;283284/* Initialize the currently bound buffer resources */285memset(svga->state.hw_draw.constbuf, 0,286sizeof(svga->state.hw_draw.constbuf));287memset(svga->state.hw_draw.default_constbuf_size, 0,288sizeof(svga->state.hw_draw.default_constbuf_size));289memset(svga->state.hw_draw.enabled_constbufs, 0,290sizeof(svga->state.hw_draw.enabled_constbufs));291svga->state.hw_draw.ib = NULL;292svga->state.hw_draw.num_vbuffers = 0;293memset(svga->state.hw_draw.vbuffers, 0,294sizeof(svga->state.hw_draw.vbuffers));295svga->state.hw_draw.const0_buffer = NULL;296svga->state.hw_draw.const0_handle = NULL;297298/* Create a no-operation blend state which we will bind whenever the299* requested blend state is impossible (e.g. due to having an integer300* render target attached).301*302* XXX: We will probably actually need 16 of these, one for each possible303* RGBA color mask (4 bits). Then, we would bind the one with a color mask304* matching the blend state it is replacing.305*/306{307struct pipe_blend_state noop_tmpl = {0};308unsigned i;309310for (i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {311// Set the color mask to all-ones. Later this may change.312noop_tmpl.rt[i].colormask = PIPE_MASK_RGBA;313}314svga->noop_blend = svga->pipe.create_blend_state(&svga->pipe, &noop_tmpl);315}316317svga->dirty = SVGA_NEW_ALL;318svga->pred.query_id = SVGA3D_INVALID_ID;319svga->disable_rasterizer = FALSE;320321/**322* Create stream output statistics queries used in the workaround for auto323* draw with stream instancing.324*/325svga_create_stream_output_queries(svga);326327goto done;328329cleanup:330svga_destroy_swtnl(svga);331332if (svga->const0_upload)333u_upload_destroy(svga->const0_upload);334if (svga->pipe.const_uploader)335u_upload_destroy(svga->pipe.const_uploader);336if (svga->pipe.stream_uploader)337u_upload_destroy(svga->pipe.stream_uploader);338svga_texture_transfer_map_upload_destroy(svga);339if (svga->hwtnl)340svga_hwtnl_destroy(svga->hwtnl);341if (svga->swc)342svga->swc->destroy(svga->swc);343util_bitmask_destroy(svga->blend_object_id_bm);344util_bitmask_destroy(svga->ds_object_id_bm);345util_bitmask_destroy(svga->input_element_object_id_bm);346util_bitmask_destroy(svga->rast_object_id_bm);347util_bitmask_destroy(svga->sampler_object_id_bm);348util_bitmask_destroy(svga->sampler_view_id_bm);349util_bitmask_destroy(svga->shader_id_bm);350util_bitmask_destroy(svga->surface_view_id_bm);351util_bitmask_destroy(svga->stream_output_id_bm);352util_bitmask_destroy(svga->query_id_bm);353FREE(svga);354svga = NULL;355356done:357SVGA_STATS_TIME_POP(svgascreen->sws);358return svga ? &svga->pipe:NULL;359}360361362void363svga_context_flush(struct svga_context *svga,364struct pipe_fence_handle **pfence)365{366struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);367struct pipe_fence_handle *fence = NULL;368uint64_t t0;369370SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CONTEXTFLUSH);371372svga->curr.nr_fbs = 0;373374/* Unmap the 0th/default constant buffer. The u_upload_unmap() function375* will call pipe_context::transfer_flush_region() to indicate the376* region of the buffer which was modified (and needs to be uploaded).377*/378if (svga->state.hw_draw.const0_handle) {379assert(svga->state.hw_draw.const0_buffer);380u_upload_unmap(svga->const0_upload);381pipe_resource_reference(&svga->state.hw_draw.const0_buffer, NULL);382svga->state.hw_draw.const0_handle = NULL;383}384385/* Ensure that texture dma uploads are processed386* before submitting commands.387*/388svga_context_flush_buffers(svga);389390svga->hud.command_buffer_size +=391svga->swc->get_command_buffer_size(svga->swc);392393/* Flush pending commands to hardware:394*/395t0 = svga_get_time(svga);396svga->swc->flush(svga->swc, &fence);397svga->hud.flush_time += (svga_get_time(svga) - t0);398399svga->hud.num_flushes++;400401svga_screen_cache_flush(svgascreen, svga, fence);402403SVGA3D_ResetLastCommand(svga->swc);404405/* To force the re-emission of rendertargets and texture sampler bindings on406* the next command buffer.407*/408svga->rebind.flags.rendertargets = TRUE;409svga->rebind.flags.texture_samplers = TRUE;410411if (svga_have_gb_objects(svga)) {412413svga->rebind.flags.constbufs = TRUE;414svga->rebind.flags.vs = TRUE;415svga->rebind.flags.fs = TRUE;416svga->rebind.flags.gs = TRUE;417418if (svga_have_sm5(svga)) {419svga->rebind.flags.tcs = TRUE;420svga->rebind.flags.tes = TRUE;421}422423if (svga_need_to_rebind_resources(svga)) {424svga->rebind.flags.query = TRUE;425}426}427428if (SVGA_DEBUG & DEBUG_SYNC) {429if (fence)430svga->pipe.screen->fence_finish(svga->pipe.screen, NULL, fence,431PIPE_TIMEOUT_INFINITE);432}433434if (pfence)435svgascreen->sws->fence_reference(svgascreen->sws, pfence, fence);436437svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);438439SVGA_STATS_TIME_POP(svga_sws(svga));440}441442443/**444* Flush pending commands and wait for completion with a fence.445*/446void447svga_context_finish(struct svga_context *svga)448{449struct pipe_screen *screen = svga->pipe.screen;450struct pipe_fence_handle *fence = NULL;451452SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CONTEXTFINISH);453454svga_context_flush(svga, &fence);455screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);456screen->fence_reference(screen, &fence, NULL);457458SVGA_STATS_TIME_POP(svga_sws(svga));459}460461462/**463* Emit pending drawing commands to the command buffer.464* If the command buffer overflows, we flush it and retry.465* \sa svga_hwtnl_flush()466*/467void468svga_hwtnl_flush_retry(struct svga_context *svga)469{470enum pipe_error ret = PIPE_OK;471472SVGA_RETRY_OOM(svga, ret, svga_hwtnl_flush(svga->hwtnl));473assert(ret == PIPE_OK);474}475476477/**478* Flush the primitive queue if this buffer is referred.479*480* Otherwise DMA commands on the referred buffer will be emitted too late.481*/482void483svga_hwtnl_flush_buffer(struct svga_context *svga,484struct pipe_resource *buffer)485{486if (svga_hwtnl_is_buffer_referred(svga->hwtnl, buffer)) {487svga_hwtnl_flush_retry(svga);488}489}490491492/**493* Emit all operations pending on host surfaces.494*/495void496svga_surfaces_flush(struct svga_context *svga)497{498SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_SURFACEFLUSH);499500/* Emit buffered drawing commands.501*/502svga_hwtnl_flush_retry(svga);503504/* Emit back-copy from render target views to textures.505*/506svga_propagate_rendertargets(svga);507508SVGA_STATS_TIME_POP(svga_sws(svga));509}510511512struct svga_winsys_context *513svga_winsys_context(struct pipe_context *pipe)514{515return svga_context(pipe)->swc;516}517518519