Path: blob/21.2-virgl/src/gallium/drivers/swr/swr_state.cpp
4570 views
/****************************************************************************1* Copyright (C) 2015 Intel Corporation. All Rights Reserved.2*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 <llvm/Config/llvm-config.h>2425#if LLVM_VERSION_MAJOR < 726// llvm redefines DEBUG27#pragma push_macro("DEBUG")28#undef DEBUG29#endif3031#include <rasterizer/core/state.h>32#include "JitManager.h"3334#if LLVM_VERSION_MAJOR < 735#pragma pop_macro("DEBUG")36#endif3738#include "common/os.h"39#include "jit_api.h"40#include "gen_state_llvm.h"41#include "core/multisample.h"42#include "core/state_funcs.h"4344#include "gallivm/lp_bld_tgsi.h"45#include "util/format/u_format.h"4647#include "util/u_memory.h"48#include "util/u_inlines.h"49#include "util/u_helpers.h"50#include "util/u_framebuffer.h"51#include "util/u_viewport.h"52#include "util/u_prim.h"5354#include "swr_state.h"55#include "swr_context.h"56#include "gen_surf_state_llvm.h"57#include "gen_swr_context_llvm.h"58#include "swr_screen.h"59#include "swr_resource.h"60#include "swr_tex_sample.h"61#include "swr_scratch.h"62#include "swr_shader.h"63#include "swr_fence.h"6465/* These should be pulled out into separate files as necessary66* Just initializing everything here to get going. */6768static void *69swr_create_blend_state(struct pipe_context *pipe,70const struct pipe_blend_state *blend)71{72struct swr_blend_state *state = CALLOC_STRUCT(swr_blend_state);73assert(state != nullptr);7475memcpy(&state->pipe, blend, sizeof(*blend));7677struct pipe_blend_state *pipe_blend = &state->pipe;7879for (int target = 0;80target < std::min(SWR_NUM_RENDERTARGETS, PIPE_MAX_COLOR_BUFS);81target++) {8283struct pipe_rt_blend_state *rt_blend = &pipe_blend->rt[target];84SWR_RENDER_TARGET_BLEND_STATE &blendState =85state->blendState.renderTarget[target];86RENDER_TARGET_BLEND_COMPILE_STATE &compileState =87state->compileState[target];8889if (target != 0 && !pipe_blend->independent_blend_enable) {90memcpy(&compileState,91&state->compileState[0],92sizeof(RENDER_TARGET_BLEND_COMPILE_STATE));93continue;94}9596compileState.blendEnable = rt_blend->blend_enable;97if (compileState.blendEnable) {98compileState.sourceAlphaBlendFactor =99swr_convert_blend_factor(rt_blend->alpha_src_factor);100compileState.destAlphaBlendFactor =101swr_convert_blend_factor(rt_blend->alpha_dst_factor);102compileState.sourceBlendFactor =103swr_convert_blend_factor(rt_blend->rgb_src_factor);104compileState.destBlendFactor =105swr_convert_blend_factor(rt_blend->rgb_dst_factor);106107compileState.colorBlendFunc =108swr_convert_blend_func(rt_blend->rgb_func);109compileState.alphaBlendFunc =110swr_convert_blend_func(rt_blend->alpha_func);111}112compileState.logicOpEnable = state->pipe.logicop_enable;113if (compileState.logicOpEnable) {114compileState.logicOpFunc =115swr_convert_logic_op(state->pipe.logicop_func);116}117118blendState.writeDisableRed =119(rt_blend->colormask & PIPE_MASK_R) ? 0 : 1;120blendState.writeDisableGreen =121(rt_blend->colormask & PIPE_MASK_G) ? 0 : 1;122blendState.writeDisableBlue =123(rt_blend->colormask & PIPE_MASK_B) ? 0 : 1;124blendState.writeDisableAlpha =125(rt_blend->colormask & PIPE_MASK_A) ? 0 : 1;126127if (rt_blend->colormask == 0)128compileState.blendEnable = false;129}130131return state;132}133134static void135swr_bind_blend_state(struct pipe_context *pipe, void *blend)136{137struct swr_context *ctx = swr_context(pipe);138139if (ctx->blend == blend)140return;141142ctx->blend = (swr_blend_state *)blend;143144ctx->dirty |= SWR_NEW_BLEND;145}146147static void148swr_delete_blend_state(struct pipe_context *pipe, void *blend)149{150FREE(blend);151}152153static void154swr_set_blend_color(struct pipe_context *pipe,155const struct pipe_blend_color *color)156{157struct swr_context *ctx = swr_context(pipe);158159ctx->blend_color = *color;160161ctx->dirty |= SWR_NEW_BLEND;162}163164static void165swr_set_stencil_ref(struct pipe_context *pipe,166const struct pipe_stencil_ref ref)167{168struct swr_context *ctx = swr_context(pipe);169170ctx->stencil_ref = ref;171172ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA;173}174175static void *176swr_create_depth_stencil_state(177struct pipe_context *pipe,178const struct pipe_depth_stencil_alpha_state *depth_stencil)179{180struct pipe_depth_stencil_alpha_state *state;181182state = (pipe_depth_stencil_alpha_state *)mem_dup(depth_stencil,183sizeof *depth_stencil);184185return state;186}187188static void189swr_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)190{191struct swr_context *ctx = swr_context(pipe);192193if (ctx->depth_stencil == (pipe_depth_stencil_alpha_state *)depth_stencil)194return;195196ctx->depth_stencil = (pipe_depth_stencil_alpha_state *)depth_stencil;197198ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA;199}200201static void202swr_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)203{204FREE(depth);205}206207208static void *209swr_create_rasterizer_state(struct pipe_context *pipe,210const struct pipe_rasterizer_state *rast)211{212struct pipe_rasterizer_state *state;213state = (pipe_rasterizer_state *)mem_dup(rast, sizeof *rast);214215return state;216}217218static void219swr_bind_rasterizer_state(struct pipe_context *pipe, void *handle)220{221struct swr_context *ctx = swr_context(pipe);222const struct pipe_rasterizer_state *rasterizer =223(const struct pipe_rasterizer_state *)handle;224225if (ctx->rasterizer == (pipe_rasterizer_state *)rasterizer)226return;227228ctx->rasterizer = (pipe_rasterizer_state *)rasterizer;229230ctx->dirty |= SWR_NEW_RASTERIZER;231}232233static void234swr_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer)235{236FREE(rasterizer);237}238239240static void *241swr_create_sampler_state(struct pipe_context *pipe,242const struct pipe_sampler_state *sampler)243{244struct pipe_sampler_state *state =245(pipe_sampler_state *)mem_dup(sampler, sizeof *sampler);246247return state;248}249250static void251swr_bind_sampler_states(struct pipe_context *pipe,252enum pipe_shader_type shader,253unsigned start,254unsigned num,255void **samplers)256{257struct swr_context *ctx = swr_context(pipe);258unsigned i;259260assert(shader < PIPE_SHADER_TYPES);261assert(start + num <= ARRAY_SIZE(ctx->samplers[shader]));262263/* set the new samplers */264ctx->num_samplers[shader] = num;265for (i = 0; i < num; i++) {266ctx->samplers[shader][start + i] = (pipe_sampler_state *)samplers[i];267}268269ctx->dirty |= SWR_NEW_SAMPLER;270}271272static void273swr_delete_sampler_state(struct pipe_context *pipe, void *sampler)274{275FREE(sampler);276}277278279static struct pipe_sampler_view *280swr_create_sampler_view(struct pipe_context *pipe,281struct pipe_resource *texture,282const struct pipe_sampler_view *templ)283{284struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);285286if (view) {287*view = *templ;288view->reference.count = 1;289view->texture = NULL;290pipe_resource_reference(&view->texture, texture);291view->context = pipe;292}293294return view;295}296297static void298swr_set_sampler_views(struct pipe_context *pipe,299enum pipe_shader_type shader,300unsigned start,301unsigned num,302unsigned unbind_num_trailing_slots,303struct pipe_sampler_view **views)304{305struct swr_context *ctx = swr_context(pipe);306uint i;307308assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);309310assert(shader < PIPE_SHADER_TYPES);311assert(start + num <= ARRAY_SIZE(ctx->sampler_views[shader]));312313/* set the new sampler views */314ctx->num_sampler_views[shader] = num;315for (i = 0; i < num; i++) {316pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i],317views[i]);318}319for (; i < num + unbind_num_trailing_slots; i++) {320pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i],321NULL);322}323324ctx->dirty |= SWR_NEW_SAMPLER_VIEW;325}326327static void328swr_sampler_view_destroy(struct pipe_context *pipe,329struct pipe_sampler_view *view)330{331pipe_resource_reference(&view->texture, NULL);332FREE(view);333}334335static void *336swr_create_vs_state(struct pipe_context *pipe,337const struct pipe_shader_state *vs)338{339struct swr_vertex_shader *swr_vs = new swr_vertex_shader;340if (!swr_vs)341return NULL;342343swr_vs->pipe.tokens = tgsi_dup_tokens(vs->tokens);344swr_vs->pipe.stream_output = vs->stream_output;345346lp_build_tgsi_info(vs->tokens, &swr_vs->info);347348swr_vs->soState = {0};349350if (swr_vs->pipe.stream_output.num_outputs) {351pipe_stream_output_info *stream_output = &swr_vs->pipe.stream_output;352353swr_vs->soState.soEnable = true;354// soState.rasterizerDisable set on state dirty355// soState.streamToRasterizer not used356357for (uint32_t i = 0; i < stream_output->num_outputs; i++) {358unsigned attrib_slot = stream_output->output[i].register_index;359attrib_slot = swr_so_adjust_attrib(attrib_slot, swr_vs);360swr_vs->soState.streamMasks[stream_output->output[i].stream] |=361(1 << attrib_slot);362}363for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) {364swr_vs->soState.streamNumEntries[i] =365_mm_popcnt_u32(swr_vs->soState.streamMasks[i]);366}367}368369return swr_vs;370}371372static void373swr_bind_vs_state(struct pipe_context *pipe, void *vs)374{375struct swr_context *ctx = swr_context(pipe);376377if (ctx->vs == vs)378return;379380ctx->vs = (swr_vertex_shader *)vs;381ctx->dirty |= SWR_NEW_VS;382}383384static void385swr_delete_vs_state(struct pipe_context *pipe, void *vs)386{387struct swr_vertex_shader *swr_vs = (swr_vertex_shader *)vs;388FREE((void *)swr_vs->pipe.tokens);389struct swr_screen *screen = swr_screen(pipe->screen);390391/* Defer deletion of vs state */392swr_fence_work_delete_vs(screen->flush_fence, swr_vs);393}394395static void *396swr_create_fs_state(struct pipe_context *pipe,397const struct pipe_shader_state *fs)398{399struct swr_fragment_shader *swr_fs = new swr_fragment_shader;400if (!swr_fs)401return NULL;402403swr_fs->pipe.tokens = tgsi_dup_tokens(fs->tokens);404405lp_build_tgsi_info(fs->tokens, &swr_fs->info);406407return swr_fs;408}409410411static void412swr_bind_fs_state(struct pipe_context *pipe, void *fs)413{414struct swr_context *ctx = swr_context(pipe);415416if (ctx->fs == fs)417return;418419ctx->fs = (swr_fragment_shader *)fs;420ctx->dirty |= SWR_NEW_FS;421}422423static void424swr_delete_fs_state(struct pipe_context *pipe, void *fs)425{426struct swr_fragment_shader *swr_fs = (swr_fragment_shader *)fs;427FREE((void *)swr_fs->pipe.tokens);428struct swr_screen *screen = swr_screen(pipe->screen);429430/* Defer deleton of fs state */431swr_fence_work_delete_fs(screen->flush_fence, swr_fs);432}433434static void *435swr_create_gs_state(struct pipe_context *pipe,436const struct pipe_shader_state *gs)437{438struct swr_geometry_shader *swr_gs = new swr_geometry_shader;439if (!swr_gs)440return NULL;441442swr_gs->pipe.tokens = tgsi_dup_tokens(gs->tokens);443lp_build_tgsi_info(gs->tokens, &swr_gs->info);444return swr_gs;445}446447static void448swr_bind_gs_state(struct pipe_context *pipe, void *gs)449{450struct swr_context *ctx = swr_context(pipe);451452if (ctx->gs == gs)453return;454455ctx->gs = (swr_geometry_shader *)gs;456ctx->dirty |= SWR_NEW_GS;457}458459static void460swr_delete_gs_state(struct pipe_context *pipe, void *gs)461{462struct swr_geometry_shader *swr_gs = (swr_geometry_shader *)gs;463FREE((void *)swr_gs->pipe.tokens);464struct swr_screen *screen = swr_screen(pipe->screen);465466/* Defer deleton of fs state */467swr_fence_work_delete_gs(screen->flush_fence, swr_gs);468}469470static void *471swr_create_tcs_state(struct pipe_context *pipe,472const struct pipe_shader_state *tcs)473{474struct swr_tess_control_shader *swr_tcs = new swr_tess_control_shader;475if (!swr_tcs)476return NULL;477478swr_tcs->pipe.tokens = tgsi_dup_tokens(tcs->tokens);479lp_build_tgsi_info(tcs->tokens, &swr_tcs->info);480return swr_tcs;481}482483static void484swr_bind_tcs_state(struct pipe_context *pipe, void *tcs)485{486struct swr_context *ctx = swr_context(pipe);487488if (ctx->tcs == tcs)489return;490491ctx->tcs = (swr_tess_control_shader *)tcs;492ctx->dirty |= SWR_NEW_TCS;493ctx->dirty |= SWR_NEW_TS;494}495496static void497swr_delete_tcs_state(struct pipe_context *pipe, void *tcs)498{499struct swr_tess_control_shader *swr_tcs = (swr_tess_control_shader *)tcs;500FREE((void *)swr_tcs->pipe.tokens);501struct swr_screen *screen = swr_screen(pipe->screen);502503/* Defer deleton of tcs state */504swr_fence_work_delete_tcs(screen->flush_fence, swr_tcs);505}506507static void *508swr_create_tes_state(struct pipe_context *pipe,509const struct pipe_shader_state *tes)510{511struct swr_tess_evaluation_shader *swr_tes = new swr_tess_evaluation_shader;512if (!swr_tes)513return NULL;514515swr_tes->pipe.tokens = tgsi_dup_tokens(tes->tokens);516lp_build_tgsi_info(tes->tokens, &swr_tes->info);517return swr_tes;518}519520static void521swr_bind_tes_state(struct pipe_context *pipe, void *tes)522{523struct swr_context *ctx = swr_context(pipe);524525if (ctx->tes == tes)526return;527528// Save current tessellator state first529if (ctx->tes != nullptr) {530ctx->tes->ts_state = ctx->tsState;531}532533ctx->tes = (swr_tess_evaluation_shader *)tes;534535ctx->dirty |= SWR_NEW_TES;536ctx->dirty |= SWR_NEW_TS;537}538539static void540swr_delete_tes_state(struct pipe_context *pipe, void *tes)541{542struct swr_tess_evaluation_shader *swr_tes = (swr_tess_evaluation_shader *)tes;543FREE((void *)swr_tes->pipe.tokens);544struct swr_screen *screen = swr_screen(pipe->screen);545546/* Defer deleton of tes state */547swr_fence_work_delete_tes(screen->flush_fence, swr_tes);548}549550static void551swr_set_constant_buffer(struct pipe_context *pipe,552enum pipe_shader_type shader,553uint index, bool take_ownership,554const struct pipe_constant_buffer *cb)555{556struct swr_context *ctx = swr_context(pipe);557struct pipe_resource *constants = cb ? cb->buffer : NULL;558559assert(shader < PIPE_SHADER_TYPES);560assert(index < ARRAY_SIZE(ctx->constants[shader]));561562/* note: reference counting */563util_copy_constant_buffer(&ctx->constants[shader][index], cb, take_ownership);564565if (shader == PIPE_SHADER_VERTEX) {566ctx->dirty |= SWR_NEW_VSCONSTANTS;567} else if (shader == PIPE_SHADER_FRAGMENT) {568ctx->dirty |= SWR_NEW_FSCONSTANTS;569} else if (shader == PIPE_SHADER_GEOMETRY) {570ctx->dirty |= SWR_NEW_GSCONSTANTS;571} else if (shader == PIPE_SHADER_TESS_CTRL) {572ctx->dirty |= SWR_NEW_TCSCONSTANTS;573} else if (shader == PIPE_SHADER_TESS_EVAL) {574ctx->dirty |= SWR_NEW_TESCONSTANTS;575}576if (cb && cb->user_buffer) {577pipe_resource_reference(&constants, NULL);578}579}580581582static void *583swr_create_vertex_elements_state(struct pipe_context *pipe,584unsigned num_elements,585const struct pipe_vertex_element *attribs)586{587struct swr_vertex_element_state *velems;588assert(num_elements <= PIPE_MAX_ATTRIBS);589velems = new swr_vertex_element_state;590if (velems) {591memset((void*)&velems->fsState, 0, sizeof(velems->fsState));592velems->fsState.bVertexIDOffsetEnable = true;593velems->fsState.numAttribs = num_elements;594for (unsigned i = 0; i < num_elements; i++) {595// XXX: we should do this keyed on the VS usage info596597const struct util_format_description *desc =598util_format_description(attribs[i].src_format);599600velems->fsState.layout[i].AlignedByteOffset = attribs[i].src_offset;601velems->fsState.layout[i].Format =602mesa_to_swr_format(attribs[i].src_format);603velems->fsState.layout[i].StreamIndex =604attribs[i].vertex_buffer_index;605velems->fsState.layout[i].InstanceEnable =606attribs[i].instance_divisor != 0;607velems->fsState.layout[i].ComponentControl0 =608desc->channel[0].type != UTIL_FORMAT_TYPE_VOID609? ComponentControl::StoreSrc610: ComponentControl::Store0;611velems->fsState.layout[i].ComponentControl1 =612desc->channel[1].type != UTIL_FORMAT_TYPE_VOID613? ComponentControl::StoreSrc614: ComponentControl::Store0;615velems->fsState.layout[i].ComponentControl2 =616desc->channel[2].type != UTIL_FORMAT_TYPE_VOID617? ComponentControl::StoreSrc618: ComponentControl::Store0;619velems->fsState.layout[i].ComponentControl3 =620desc->channel[3].type != UTIL_FORMAT_TYPE_VOID621? ComponentControl::StoreSrc622: ComponentControl::Store1Fp;623velems->fsState.layout[i].ComponentPacking = ComponentEnable::XYZW;624velems->fsState.layout[i].InstanceAdvancementState =625attribs[i].instance_divisor;626627/* Calculate the pitch of each stream */628const SWR_FORMAT_INFO &swr_desc = GetFormatInfo(629mesa_to_swr_format(attribs[i].src_format));630velems->stream_pitch[attribs[i].vertex_buffer_index] += swr_desc.Bpp;631632if (attribs[i].instance_divisor != 0) {633velems->instanced_bufs |= 1U << attribs[i].vertex_buffer_index;634uint32_t *min_instance_div =635&velems->min_instance_div[attribs[i].vertex_buffer_index];636if (!*min_instance_div ||637attribs[i].instance_divisor < *min_instance_div)638*min_instance_div = attribs[i].instance_divisor;639}640}641}642643return velems;644}645646static void647swr_bind_vertex_elements_state(struct pipe_context *pipe, void *velems)648{649struct swr_context *ctx = swr_context(pipe);650struct swr_vertex_element_state *swr_velems =651(struct swr_vertex_element_state *)velems;652653ctx->velems = swr_velems;654ctx->dirty |= SWR_NEW_VERTEX;655}656657static void658swr_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)659{660struct swr_vertex_element_state *swr_velems =661(struct swr_vertex_element_state *) velems;662/* XXX Need to destroy fetch shader? */663delete swr_velems;664}665666667static void668swr_set_vertex_buffers(struct pipe_context *pipe,669unsigned start_slot,670unsigned num_elements,671unsigned unbind_num_trailing_slots,672bool take_ownership,673const struct pipe_vertex_buffer *buffers)674{675struct swr_context *ctx = swr_context(pipe);676677assert(num_elements <= PIPE_MAX_ATTRIBS);678679util_set_vertex_buffers_count(ctx->vertex_buffer,680&ctx->num_vertex_buffers,681buffers,682start_slot,683num_elements,684unbind_num_trailing_slots,685take_ownership);686687ctx->dirty |= SWR_NEW_VERTEX;688}689690691static void692swr_set_polygon_stipple(struct pipe_context *pipe,693const struct pipe_poly_stipple *stipple)694{695struct swr_context *ctx = swr_context(pipe);696697ctx->poly_stipple.pipe = *stipple; /* struct copy */698ctx->dirty |= SWR_NEW_STIPPLE;699}700701static void702swr_set_clip_state(struct pipe_context *pipe,703const struct pipe_clip_state *clip)704{705struct swr_context *ctx = swr_context(pipe);706707ctx->clip = *clip;708/* XXX Unimplemented, but prevents crash */709710ctx->dirty |= SWR_NEW_CLIP;711}712713714static void715swr_set_scissor_states(struct pipe_context *pipe,716unsigned start_slot,717unsigned num_scissors,718const struct pipe_scissor_state *scissors)719{720struct swr_context *ctx = swr_context(pipe);721722memcpy(ctx->scissors + start_slot, scissors,723sizeof(struct pipe_scissor_state) * num_scissors);724725for (unsigned i = 0; i < num_scissors; i++) {726auto idx = start_slot + i;727ctx->swr_scissors[idx].xmin = scissors[idx].minx;728ctx->swr_scissors[idx].xmax = scissors[idx].maxx;729ctx->swr_scissors[idx].ymin = scissors[idx].miny;730ctx->swr_scissors[idx].ymax = scissors[idx].maxy;731}732ctx->dirty |= SWR_NEW_SCISSOR;733}734735static void736swr_set_viewport_states(struct pipe_context *pipe,737unsigned start_slot,738unsigned num_viewports,739const struct pipe_viewport_state *vpt)740{741struct swr_context *ctx = swr_context(pipe);742743memcpy(ctx->viewports + start_slot, vpt, sizeof(struct pipe_viewport_state) * num_viewports);744ctx->dirty |= SWR_NEW_VIEWPORT;745}746747748static void749swr_set_framebuffer_state(struct pipe_context *pipe,750const struct pipe_framebuffer_state *fb)751{752struct swr_context *ctx = swr_context(pipe);753754bool changed = !util_framebuffer_state_equal(&ctx->framebuffer, fb);755756assert(fb->width <= KNOB_GUARDBAND_WIDTH);757assert(fb->height <= KNOB_GUARDBAND_HEIGHT);758759if (changed) {760util_copy_framebuffer_state(&ctx->framebuffer, fb);761762/* 0 and 1 both indicate no msaa. Core doesn't understand 0 samples */763ctx->framebuffer.samples = std::max((ubyte)1, ctx->framebuffer.samples);764765ctx->dirty |= SWR_NEW_FRAMEBUFFER;766}767}768769770static void771swr_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)772{773struct swr_context *ctx = swr_context(pipe);774775if (sample_mask != ctx->sample_mask) {776ctx->sample_mask = sample_mask;777ctx->dirty |= SWR_NEW_RASTERIZER;778}779}780781/*782* MSAA fixed sample position table783* used by update_derived and get_sample_position784* (integer locations on a 16x16 grid)785*/786static const uint8_t swr_sample_positions[][2] =787{ /* 1x*/ { 8, 8},788/* 2x*/ {12,12},{ 4, 4},789/* 4x*/ { 6, 2},{14, 6},{ 2,10},{10,14},790/* 8x*/ { 9, 5},{ 7,11},{13, 9},{ 5, 3},791{ 3,13},{ 1, 7},{11,15},{15, 1},792/*16x*/ { 9, 9},{ 7, 5},{ 5,10},{12, 7},793{ 3, 6},{10,13},{13,11},{11, 3},794{ 6,14},{ 8, 1},{ 4, 2},{ 2,12},795{ 0, 8},{15, 4},{14,15},{ 1, 0} };796797static void798swr_get_sample_position(struct pipe_context *pipe,799unsigned sample_count, unsigned sample_index,800float *out_value)801{802/* validate sample_count */803sample_count = GetNumSamples(GetSampleCount(sample_count));804805const uint8_t *sample = swr_sample_positions[sample_count-1 + sample_index];806out_value[0] = sample[0] / 16.0f;807out_value[1] = sample[1] / 16.0f;808}809810811/*812* Update resource in-use status813* All resources bound to color or depth targets marked as WRITE resources.814* VBO Vertex/index buffers and texture views marked as READ resources.815*/816void817swr_update_resource_status(struct pipe_context *pipe,818const struct pipe_draw_info *p_draw_info)819{820struct swr_context *ctx = swr_context(pipe);821struct pipe_framebuffer_state *fb = &ctx->framebuffer;822823/* colorbuffer targets */824if (fb->nr_cbufs)825for (uint32_t i = 0; i < fb->nr_cbufs; ++i)826if (fb->cbufs[i])827swr_resource_write(fb->cbufs[i]->texture);828829/* depth/stencil target */830if (fb->zsbuf)831swr_resource_write(fb->zsbuf->texture);832833/* VBO vertex buffers */834for (uint32_t i = 0; i < ctx->num_vertex_buffers; i++) {835struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i];836if (!vb->is_user_buffer && vb->buffer.resource)837swr_resource_read(vb->buffer.resource);838}839840/* VBO index buffer */841if (p_draw_info && p_draw_info->index_size) {842if (!p_draw_info->has_user_indices)843swr_resource_read(p_draw_info->index.resource);844}845846/* transform feedback buffers */847for (uint32_t i = 0; i < ctx->num_so_targets; i++) {848struct pipe_stream_output_target *target = ctx->so_targets[i];849if (target && target->buffer)850swr_resource_write(target->buffer);851}852853/* texture sampler views */854for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) {855for (uint32_t i = 0; i < ctx->num_sampler_views[j]; i++) {856struct pipe_sampler_view *view = ctx->sampler_views[j][i];857if (view)858swr_resource_read(view->texture);859}860}861862/* constant buffers */863for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) {864for (uint32_t i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {865struct pipe_constant_buffer *cb = &ctx->constants[j][i];866if (cb->buffer)867swr_resource_read(cb->buffer);868}869}870}871872static void873swr_update_texture_state(struct swr_context *ctx,874enum pipe_shader_type shader_type,875unsigned num_sampler_views,876swr_jit_texture *textures)877{878for (unsigned i = 0; i < num_sampler_views; i++) {879struct pipe_sampler_view *view =880ctx->sampler_views[shader_type][i];881struct swr_jit_texture *jit_tex = &textures[i];882883memset(jit_tex, 0, sizeof(*jit_tex));884if (view) {885struct pipe_resource *res = view->texture;886struct swr_resource *swr_res = swr_resource(res);887SWR_SURFACE_STATE *swr = &swr_res->swr;888size_t *mip_offsets = swr_res->mip_offsets;889if (swr_res->has_depth && swr_res->has_stencil &&890!util_format_has_depth(util_format_description(view->format))) {891swr = &swr_res->secondary;892mip_offsets = swr_res->secondary_mip_offsets;893}894895jit_tex->width = res->width0;896jit_tex->height = res->height0;897jit_tex->base_ptr = (uint8_t*)swr->xpBaseAddress;898jit_tex->num_samples = swr->numSamples;899jit_tex->sample_stride = 0;900if (view->target != PIPE_BUFFER) {901jit_tex->first_level = view->u.tex.first_level;902jit_tex->last_level = view->u.tex.last_level;903if (view->target == PIPE_TEXTURE_3D)904jit_tex->depth = res->depth0;905else906jit_tex->depth =907view->u.tex.last_layer - view->u.tex.first_layer + 1;908jit_tex->base_ptr += view->u.tex.first_layer *909swr->qpitch * swr->pitch;910} else {911unsigned view_blocksize = util_format_get_blocksize(view->format);912jit_tex->base_ptr += view->u.buf.offset;913jit_tex->width = view->u.buf.size / view_blocksize;914jit_tex->depth = 1;915}916917for (unsigned level = jit_tex->first_level;918level <= jit_tex->last_level;919level++) {920jit_tex->row_stride[level] = swr->pitch;921jit_tex->img_stride[level] = swr->qpitch * swr->pitch;922jit_tex->mip_offsets[level] = mip_offsets[level];923}924}925}926}927928static void929swr_update_sampler_state(struct swr_context *ctx,930enum pipe_shader_type shader_type,931unsigned num_samplers,932swr_jit_sampler *samplers)933{934for (unsigned i = 0; i < num_samplers; i++) {935const struct pipe_sampler_state *sampler =936ctx->samplers[shader_type][i];937938if (sampler) {939samplers[i].min_lod = sampler->min_lod;940samplers[i].max_lod = sampler->max_lod;941samplers[i].lod_bias = sampler->lod_bias;942COPY_4V(samplers[i].border_color, sampler->border_color.f);943}944}945}946947static void948swr_update_constants(struct swr_context *ctx, enum pipe_shader_type shaderType)949{950swr_draw_context *pDC = &ctx->swrDC;951952const float **constant;953uint32_t *num_constants;954struct swr_scratch_space *scratch;955956switch (shaderType) {957case PIPE_SHADER_VERTEX:958constant = pDC->constantVS;959num_constants = pDC->num_constantsVS;960scratch = &ctx->scratch->vs_constants;961break;962case PIPE_SHADER_FRAGMENT:963constant = pDC->constantFS;964num_constants = pDC->num_constantsFS;965scratch = &ctx->scratch->fs_constants;966break;967case PIPE_SHADER_GEOMETRY:968constant = pDC->constantGS;969num_constants = pDC->num_constantsGS;970scratch = &ctx->scratch->gs_constants;971break;972case PIPE_SHADER_TESS_CTRL:973constant = pDC->constantTCS;974num_constants = pDC->num_constantsTCS;975scratch = &ctx->scratch->tcs_constants;976break;977case PIPE_SHADER_TESS_EVAL:978constant = pDC->constantTES;979num_constants = pDC->num_constantsTES;980scratch = &ctx->scratch->tes_constants;981break;982default:983assert(0 && "Unsupported shader type constants");984return;985}986987for (UINT i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {988const pipe_constant_buffer *cb = &ctx->constants[shaderType][i];989num_constants[i] = cb->buffer_size;990if (cb->buffer) {991constant[i] =992(const float *)(swr_resource_data(cb->buffer) +993cb->buffer_offset);994} else {995/* Need to copy these constants to scratch space */996if (cb->user_buffer && cb->buffer_size) {997const void *ptr =998((const uint8_t *)cb->user_buffer + cb->buffer_offset);999uint32_t size = AlignUp(cb->buffer_size, 4);1000ptr = swr_copy_to_scratch_space(ctx, scratch, ptr, size);1001constant[i] = (const float *)ptr;1002}1003}1004}1005}10061007static bool1008swr_change_rt(struct swr_context *ctx,1009unsigned attachment,1010const struct pipe_surface *sf)1011{1012swr_draw_context *pDC = &ctx->swrDC;1013struct SWR_SURFACE_STATE *rt = &pDC->renderTargets[attachment];10141015/* Do nothing if the render target hasn't changed */1016if ((!sf || !sf->texture) && (void*)(rt->xpBaseAddress) == nullptr)1017return false;10181019/* Deal with disabling RT up front */1020if (!sf || !sf->texture) {1021/* If detaching attachment, mark tiles as RESOLVED so core1022* won't try to load from non-existent target. */1023swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_RESOLVED);1024*rt = {0};1025return true;1026}10271028const struct swr_resource *swr = swr_resource(sf->texture);1029const SWR_SURFACE_STATE *swr_surface = &swr->swr;1030SWR_FORMAT fmt = mesa_to_swr_format(sf->format);10311032if (attachment == SWR_ATTACHMENT_STENCIL && swr->secondary.xpBaseAddress) {1033swr_surface = &swr->secondary;1034fmt = swr_surface->format;1035}10361037if (rt->xpBaseAddress == swr_surface->xpBaseAddress &&1038rt->format == fmt &&1039rt->lod == sf->u.tex.level &&1040rt->arrayIndex == sf->u.tex.first_layer)1041return false;10421043bool need_fence = false;10441045/* StoreTile for changed target */1046if (rt->xpBaseAddress) {1047/* If changing attachment to a new target, mark tiles as1048* INVALID so they are reloaded from surface. */1049swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_INVALID);1050need_fence = true;1051} else {1052/* if no previous attachment, invalidate tiles that may be marked1053* RESOLVED because of an old attachment */1054swr_invalidate_render_target(&ctx->pipe, attachment, sf->width, sf->height);1055/* no need to set fence here */1056}10571058/* Make new attachment */1059*rt = *swr_surface;1060rt->format = fmt;1061rt->lod = sf->u.tex.level;1062rt->arrayIndex = sf->u.tex.first_layer;10631064return need_fence;1065}10661067/*1068* for cases where resources are shared between contexts, invalidate1069* this ctx's resource. so it can be fetched fresh. Old ctx's resource1070* is already stored during a flush1071*/1072static inline void1073swr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe)1074{1075struct swr_context *ctx = swr_context(pipe);10761077for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) {1078struct pipe_surface *cb = ctx->framebuffer.cbufs[i];1079if (cb) {1080struct swr_resource *res = swr_resource(cb->texture);1081if (res->curr_pipe != pipe) {1082/* if curr_pipe is NULL (first use), status should not be WRITE */1083assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));1084if (res->status & SWR_RESOURCE_WRITE) {1085swr_invalidate_render_target(pipe, i, cb->width, cb->height);1086}1087}1088res->curr_pipe = pipe;1089}1090}1091if (ctx->framebuffer.zsbuf) {1092struct pipe_surface *zb = ctx->framebuffer.zsbuf;1093if (zb) {1094struct swr_resource *res = swr_resource(zb->texture);1095if (res->curr_pipe != pipe) {1096/* if curr_pipe is NULL (first use), status should not be WRITE */1097assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));1098if (res->status & SWR_RESOURCE_WRITE) {1099swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height);1100swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height);1101}1102}1103res->curr_pipe = pipe;1104}1105}1106}11071108static inline void1109swr_user_vbuf_range(const struct pipe_draw_info *info,1110const struct swr_vertex_element_state *velems,1111const struct pipe_vertex_buffer *vb,1112uint32_t i,1113uint32_t *totelems,1114uint32_t *base,1115uint32_t *size,1116int index_bias)1117{1118/* FIXME: The size is too large - we don't access the full extra stride. */1119unsigned elems;1120unsigned elem_pitch = vb->stride + velems->stream_pitch[i];1121if (velems->instanced_bufs & (1U << i)) {1122elems = info->instance_count / velems->min_instance_div[i] + 1;1123*totelems = info->start_instance + elems;1124*base = info->start_instance * vb->stride;1125*size = elems * elem_pitch;1126} else if (vb->stride) {1127elems = info->max_index - info->min_index + 1;1128*totelems = (info->max_index + (info->index_size ? index_bias : 0)) + 1;1129*base = (info->min_index + (info->index_size ? index_bias : 0)) * vb->stride;1130*size = elems * elem_pitch;1131} else {1132*totelems = 1;1133*base = 0;1134*size = velems->stream_pitch[i];1135}1136}11371138static void1139swr_update_poly_stipple(struct swr_context *ctx)1140{1141struct swr_draw_context *pDC = &ctx->swrDC;11421143assert(sizeof(ctx->poly_stipple.pipe.stipple) == sizeof(pDC->polyStipple));1144memcpy(pDC->polyStipple,1145ctx->poly_stipple.pipe.stipple,1146sizeof(ctx->poly_stipple.pipe.stipple));1147}114811491150static struct tgsi_shader_info *1151swr_get_last_fe(const struct swr_context *ctx)1152{1153tgsi_shader_info *pLastFE = &ctx->vs->info.base;11541155if (ctx->gs) {1156pLastFE = &ctx->gs->info.base;1157}1158else if (ctx->tes) {1159pLastFE = &ctx->tes->info.base;1160}1161else if (ctx->tcs) {1162pLastFE = &ctx->tcs->info.base;1163}1164return pLastFE;1165}116611671168void1169swr_update_derived(struct pipe_context *pipe,1170const struct pipe_draw_info *p_draw_info,1171const struct pipe_draw_start_count_bias *draw)1172{1173struct swr_context *ctx = swr_context(pipe);1174struct swr_screen *screen = swr_screen(pipe->screen);11751176/* When called from swr_clear (p_draw_info = null), set any null1177* state-objects to the dummy state objects to prevent nullptr dereference1178* in validation below.1179*1180* Important that this remains static for zero initialization. These1181* aren't meant to be proper state objects, just empty structs. They will1182* not be written to.1183*1184* Shaders can't be part of the union since they contain std::unordered_map1185*/1186static struct {1187union {1188struct pipe_rasterizer_state rasterizer;1189struct pipe_depth_stencil_alpha_state depth_stencil;1190struct swr_blend_state blend;1191} state;1192struct swr_vertex_shader vs;1193struct swr_fragment_shader fs;1194} swr_dummy;11951196if (!p_draw_info) {1197if (!ctx->rasterizer)1198ctx->rasterizer = &swr_dummy.state.rasterizer;1199if (!ctx->depth_stencil)1200ctx->depth_stencil = &swr_dummy.state.depth_stencil;1201if (!ctx->blend)1202ctx->blend = &swr_dummy.state.blend;1203if (!ctx->vs)1204ctx->vs = &swr_dummy.vs;1205if (!ctx->fs)1206ctx->fs = &swr_dummy.fs;1207}12081209/* Update screen->pipe to current pipe context. */1210screen->pipe = pipe;12111212/* Any state that requires dirty flags to be re-triggered sets this mask */1213/* For example, user_buffer vertex and index buffers. */1214unsigned post_update_dirty_flags = 0;12151216/* bring resources that changed context up-to-date */1217swr_invalidate_buffers_after_ctx_change(pipe);12181219/* Render Targets */1220if (ctx->dirty & SWR_NEW_FRAMEBUFFER) {1221struct pipe_framebuffer_state *fb = &ctx->framebuffer;1222const struct util_format_description *desc = NULL;1223bool need_fence = false;12241225/* colorbuffer targets */1226if (fb->nr_cbufs) {1227for (unsigned i = 0; i < fb->nr_cbufs; ++i)1228need_fence |= swr_change_rt(1229ctx, SWR_ATTACHMENT_COLOR0 + i, fb->cbufs[i]);1230}1231for (unsigned i = fb->nr_cbufs; i < SWR_NUM_RENDERTARGETS; ++i)1232need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_COLOR0 + i, NULL);12331234/* depth/stencil target */1235if (fb->zsbuf)1236desc = util_format_description(fb->zsbuf->format);1237if (fb->zsbuf && util_format_has_depth(desc))1238need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, fb->zsbuf);1239else1240need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, NULL);12411242if (fb->zsbuf && util_format_has_stencil(desc))1243need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, fb->zsbuf);1244else1245need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, NULL);12461247/* This fence ensures any attachment changes are resolved before the1248* next draw */1249if (need_fence)1250swr_fence_submit(ctx, screen->flush_fence);1251}12521253/* Raster state */1254if (ctx->dirty & (SWR_NEW_RASTERIZER |1255SWR_NEW_VS | // clipping1256SWR_NEW_TES |1257SWR_NEW_TCS |1258SWR_NEW_FRAMEBUFFER)) {1259pipe_rasterizer_state *rasterizer = ctx->rasterizer;1260pipe_framebuffer_state *fb = &ctx->framebuffer;12611262SWR_RASTSTATE *rastState = &ctx->derived.rastState;1263rastState->cullMode = swr_convert_cull_mode(rasterizer->cull_face);1264rastState->frontWinding = rasterizer->front_ccw1265? SWR_FRONTWINDING_CCW1266: SWR_FRONTWINDING_CW;1267rastState->scissorEnable = rasterizer->scissor;1268rastState->pointSize = rasterizer->point_size > 0.0f1269? rasterizer->point_size1270: 1.0f;1271rastState->lineWidth = rasterizer->line_width > 0.0f1272? rasterizer->line_width1273: 1.0f;12741275rastState->pointParam = rasterizer->point_size_per_vertex;12761277rastState->pointSpriteEnable = rasterizer->sprite_coord_enable;1278rastState->pointSpriteTopOrigin =1279rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT;12801281/* If SWR_MSAA_FORCE_ENABLE is set, turn msaa on */1282if (screen->msaa_force_enable && !rasterizer->multisample) {1283/* Force enable and use the value the surface was created with */1284rasterizer->multisample = true;1285fb->samples = swr_resource(fb->cbufs[0]->texture)->swr.numSamples;1286fprintf(stderr,"msaa force enable: %d samples\n", fb->samples);1287}12881289rastState->sampleCount = GetSampleCount(fb->samples);1290rastState->forcedSampleCount = false;1291rastState->bIsCenterPattern = !rasterizer->multisample;1292rastState->pixelLocation = SWR_PIXEL_LOCATION_CENTER;12931294/* Only initialize sample positions if msaa is enabled */1295if (rasterizer->multisample) {1296for (uint32_t i = 0; i < fb->samples; i++) {1297const uint8_t *sample = swr_sample_positions[fb->samples-1 + i];1298rastState->samplePositions.SetXi(i, sample[0] << 4);1299rastState->samplePositions.SetYi(i, sample[1] << 4);1300rastState->samplePositions.SetX (i, sample[0] / 16.0f);1301rastState->samplePositions.SetY (i, sample[1] / 16.0f);1302}1303rastState->samplePositions.PrecalcSampleData(fb->samples);1304}13051306bool do_offset = false;1307switch (rasterizer->fill_front) {1308case PIPE_POLYGON_MODE_FILL:1309do_offset = rasterizer->offset_tri;1310break;1311case PIPE_POLYGON_MODE_LINE:1312do_offset = rasterizer->offset_line;1313break;1314case PIPE_POLYGON_MODE_POINT:1315do_offset = rasterizer->offset_point;1316break;1317}13181319if (do_offset) {1320rastState->depthBias = rasterizer->offset_units;1321rastState->slopeScaledDepthBias = rasterizer->offset_scale;1322rastState->depthBiasClamp = rasterizer->offset_clamp;1323} else {1324rastState->depthBias = 0;1325rastState->slopeScaledDepthBias = 0;1326rastState->depthBiasClamp = 0;1327}13281329/* translate polygon mode, at least for the front==back case */1330rastState->fillMode = swr_convert_fill_mode(rasterizer->fill_front);13311332struct pipe_surface *zb = fb->zsbuf;1333if (zb && swr_resource(zb->texture)->has_depth)1334rastState->depthFormat = swr_resource(zb->texture)->swr.format;13351336rastState->depthClipEnable = rasterizer->depth_clip_near;1337rastState->clipEnable = rasterizer->depth_clip_near | rasterizer->depth_clip_far;1338rastState->clipHalfZ = rasterizer->clip_halfz;13391340ctx->api.pfnSwrSetRastState(ctx->swrContext, rastState);1341}13421343/* Viewport */1344if (ctx->dirty & (SWR_NEW_VIEWPORT | SWR_NEW_FRAMEBUFFER1345| SWR_NEW_RASTERIZER)) {1346pipe_viewport_state *state = &ctx->viewports[0];1347pipe_framebuffer_state *fb = &ctx->framebuffer;1348pipe_rasterizer_state *rasterizer = ctx->rasterizer;13491350SWR_VIEWPORT *vp = &ctx->derived.vp[0];1351SWR_VIEWPORT_MATRICES *vpm = &ctx->derived.vpm;13521353for (unsigned i = 0; i < KNOB_NUM_VIEWPORTS_SCISSORS; i++) {1354vp->x = state->translate[0] - state->scale[0];1355vp->width = 2 * state->scale[0];1356vp->y = state->translate[1] - fabs(state->scale[1]);1357vp->height = 2 * fabs(state->scale[1]);1358util_viewport_zmin_zmax(state, rasterizer->clip_halfz,1359&vp->minZ, &vp->maxZ);13601361if (rasterizer->depth_clip_near) {1362vp->minZ = 0.0f;1363}13641365if (rasterizer->depth_clip_far) {1366vp->maxZ = 1.0f;1367}13681369vpm->m00[i] = state->scale[0];1370vpm->m11[i] = state->scale[1];1371vpm->m22[i] = state->scale[2];1372vpm->m30[i] = state->translate[0];1373vpm->m31[i] = state->translate[1];1374vpm->m32[i] = state->translate[2];13751376/* Now that the matrix is calculated, clip the view coords to screen1377* size. OpenGL allows for -ve x,y in the viewport. */1378if (vp->x < 0.0f) {1379vp->width += vp->x;1380vp->x = 0.0f;1381}1382if (vp->y < 0.0f) {1383vp->height += vp->y;1384vp->y = 0.0f;1385}1386vp->width = std::min(vp->width, (float) fb->width - vp->x);1387vp->height = std::min(vp->height, (float) fb->height - vp->y);13881389vp++;1390state++;1391}1392ctx->api.pfnSwrSetViewports(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS,1393&ctx->derived.vp[0], &ctx->derived.vpm);1394}13951396/* When called from swr_clear (p_draw_info = null), render targets,1397* rasterState and viewports (dependent on render targets) are the only1398* necessary validation. Defer remaining validation by setting1399* post_update_dirty_flags and clear all dirty flags. BackendState is1400* still unconditionally validated below */1401if (!p_draw_info) {1402post_update_dirty_flags = ctx->dirty & ~(SWR_NEW_FRAMEBUFFER |1403SWR_NEW_RASTERIZER |1404SWR_NEW_VIEWPORT);1405ctx->dirty = 0;1406}14071408/* Scissor */1409if (ctx->dirty & SWR_NEW_SCISSOR) {1410ctx->api.pfnSwrSetScissorRects(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS, ctx->swr_scissors);1411}14121413/* Set vertex & index buffers */1414if (ctx->dirty & SWR_NEW_VERTEX) {1415const struct pipe_draw_info &info = *p_draw_info;14161417/* vertex buffers */1418SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS];1419for (UINT i = 0; i < ctx->num_vertex_buffers; i++) {1420uint32_t size = 0, pitch = 0, elems = 0, partial_inbounds = 0;1421uint32_t min_vertex_index = 0;1422const uint8_t *p_data;1423struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i];14241425pitch = vb->stride;1426if (vb->is_user_buffer) {1427/* Client buffer1428* client memory is one-time use, re-trigger SWR_NEW_VERTEX to1429* revalidate on each draw */1430post_update_dirty_flags |= SWR_NEW_VERTEX;14311432uint32_t base;1433swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size, draw->index_bias);1434partial_inbounds = 0;1435min_vertex_index = info.min_index + (info.index_size ? draw->index_bias : 0);14361437size = AlignUp(size, 4);1438/* If size of client memory copy is too large, don't copy. The1439* draw will access user-buffer directly and then block. This is1440* faster than queuing many large client draws. */1441if (size >= screen->client_copy_limit) {1442post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW;1443p_data = (const uint8_t *) vb->buffer.user;1444} else {1445/* Copy only needed vertices to scratch space */1446const void *ptr = (const uint8_t *) vb->buffer.user + base;1447ptr = (uint8_t *)swr_copy_to_scratch_space(1448ctx, &ctx->scratch->vertex_buffer, ptr, size);1449p_data = (const uint8_t *)ptr - base;1450}1451} else if (vb->buffer.resource) {1452/* VBO */1453if (!pitch) {1454/* If pitch=0 (ie vb->stride), buffer contains a single1455* constant attribute. Use the stream_pitch which was1456* calculated during creation of vertex_elements_state for the1457* size of the attribute. */1458size = ctx->velems->stream_pitch[i];1459elems = 1;1460partial_inbounds = 0;1461min_vertex_index = 0;1462} else {1463/* size is based on buffer->width0 rather than info.max_index1464* to prevent having to validate VBO on each draw. */1465size = vb->buffer.resource->width0;1466elems = size / pitch;1467partial_inbounds = size % pitch;1468min_vertex_index = 0;1469}14701471p_data = swr_resource_data(vb->buffer.resource) + vb->buffer_offset;1472} else1473p_data = NULL;14741475swrVertexBuffers[i] = {0};1476swrVertexBuffers[i].index = i;1477swrVertexBuffers[i].pitch = pitch;1478swrVertexBuffers[i].xpData = (gfxptr_t) p_data;1479swrVertexBuffers[i].size = size;1480swrVertexBuffers[i].minVertex = min_vertex_index;1481swrVertexBuffers[i].maxVertex = elems;1482swrVertexBuffers[i].partialInboundsSize = partial_inbounds;1483}14841485ctx->api.pfnSwrSetVertexBuffers(1486ctx->swrContext, ctx->num_vertex_buffers, swrVertexBuffers);14871488/* index buffer, if required (info passed in by swr_draw_vbo) */1489SWR_FORMAT index_type = R32_UINT; /* Default for non-indexed draws */1490if (info.index_size) {1491const uint8_t *p_data;1492uint32_t size, pitch;14931494pitch = info.index_size ? info.index_size : sizeof(uint32_t);1495index_type = swr_convert_index_type(pitch);14961497if (!info.has_user_indices) {1498/* VBO1499* size is based on buffer->width0 rather than info.count1500* to prevent having to validate VBO on each draw */1501size = info.index.resource->width0;1502p_data = swr_resource_data(info.index.resource);1503} else {1504/* Client buffer1505* client memory is one-time use, re-trigger SWR_NEW_VERTEX to1506* revalidate on each draw */1507post_update_dirty_flags |= SWR_NEW_VERTEX;15081509size = draw->count * pitch;15101511size = AlignUp(size, 4);1512/* If size of client memory copy is too large, don't copy. The1513* draw will access user-buffer directly and then block. This is1514* faster than queuing many large client draws. */1515if (size >= screen->client_copy_limit) {1516post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW;1517p_data = (const uint8_t *) info.index.user +1518draw->start * info.index_size;1519} else {1520/* Copy indices to scratch space */1521const void *ptr = (char*)info.index.user +1522draw->start * info.index_size;1523ptr = swr_copy_to_scratch_space(1524ctx, &ctx->scratch->index_buffer, ptr, size);1525p_data = (const uint8_t *)ptr;1526}1527}15281529SWR_INDEX_BUFFER_STATE swrIndexBuffer;1530swrIndexBuffer.format = swr_convert_index_type(info.index_size);1531swrIndexBuffer.xpIndices = (gfxptr_t) p_data;1532swrIndexBuffer.size = size;15331534ctx->api.pfnSwrSetIndexBuffer(ctx->swrContext, &swrIndexBuffer);1535}15361537struct swr_vertex_element_state *velems = ctx->velems;1538if (velems && velems->fsState.indexType != index_type) {1539velems->fsFunc = NULL;1540velems->fsState.indexType = index_type;1541}1542}15431544/* GeometryShader */1545if (ctx->dirty & (SWR_NEW_GS |1546SWR_NEW_VS |1547SWR_NEW_TCS |1548SWR_NEW_TES |1549SWR_NEW_SAMPLER |1550SWR_NEW_SAMPLER_VIEW)) {1551if (ctx->gs) {1552swr_jit_gs_key key;1553swr_generate_gs_key(key, ctx, ctx->gs);1554auto search = ctx->gs->map.find(key);1555PFN_GS_FUNC func;1556if (search != ctx->gs->map.end()) {1557func = search->second->shader;1558} else {1559func = swr_compile_gs(ctx, key);1560}1561ctx->api.pfnSwrSetGsFunc(ctx->swrContext, func);15621563/* JIT sampler state */1564if (ctx->dirty & SWR_NEW_SAMPLER) {1565swr_update_sampler_state(ctx,1566PIPE_SHADER_GEOMETRY,1567key.nr_samplers,1568ctx->swrDC.samplersGS);1569}15701571/* JIT sampler view state */1572if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {1573swr_update_texture_state(ctx,1574PIPE_SHADER_GEOMETRY,1575key.nr_sampler_views,1576ctx->swrDC.texturesGS);1577}15781579ctx->api.pfnSwrSetGsState(ctx->swrContext, &ctx->gs->gsState);1580} else {1581SWR_GS_STATE state = { 0 };1582ctx->api.pfnSwrSetGsState(ctx->swrContext, &state);1583ctx->api.pfnSwrSetGsFunc(ctx->swrContext, NULL);1584}1585}15861587// We may need to restore tessellation state1588// This restored state may be however overwritten1589// during shader compilation1590if (ctx->dirty & SWR_NEW_TS) {1591if (ctx->tes != nullptr) {1592ctx->tsState = ctx->tes->ts_state;1593ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);1594} else {1595SWR_TS_STATE state = { 0 };1596ctx->api.pfnSwrSetTsState(ctx->swrContext, &state);1597}1598}15991600// Tessellation Evaluation Shader1601// Compile TES first, because TCS is optional1602if (ctx->dirty & (SWR_NEW_GS |1603SWR_NEW_VS |1604SWR_NEW_TCS |1605SWR_NEW_TES |1606SWR_NEW_SAMPLER |1607SWR_NEW_SAMPLER_VIEW)) {1608if (ctx->tes) {1609swr_jit_tes_key key;1610swr_generate_tes_key(key, ctx, ctx->tes);16111612auto search = ctx->tes->map.find(key);1613PFN_TES_FUNC func;1614if (search != ctx->tes->map.end()) {1615func = search->second->shader;1616} else {1617func = swr_compile_tes(ctx, key);1618}16191620ctx->api.pfnSwrSetDsFunc(ctx->swrContext, func);16211622/* JIT sampler state */1623if (ctx->dirty & SWR_NEW_SAMPLER) {1624swr_update_sampler_state(ctx,1625PIPE_SHADER_TESS_EVAL,1626key.nr_samplers,1627ctx->swrDC.samplersTES);1628}16291630/* JIT sampler view state */1631if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {1632swr_update_texture_state(ctx,1633PIPE_SHADER_TESS_EVAL,1634key.nr_sampler_views,1635ctx->swrDC.texturesTES);1636}16371638// Update tessellation state in case it's been updated1639ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);1640} else {1641ctx->api.pfnSwrSetDsFunc(ctx->swrContext, NULL);1642}1643}16441645/* Tessellation Control Shader */1646if (ctx->dirty & (SWR_NEW_GS |1647SWR_NEW_VS |1648SWR_NEW_TCS |1649SWR_NEW_TES |1650SWR_NEW_SAMPLER |1651SWR_NEW_SAMPLER_VIEW)) {1652if (ctx->tcs) {1653ctx->tcs->vertices_per_patch = p_draw_info->vertices_per_patch;16541655swr_jit_tcs_key key;1656swr_generate_tcs_key(key, ctx, ctx->tcs);16571658auto search = ctx->tcs->map.find(key);1659PFN_TCS_FUNC func;1660if (search != ctx->tcs->map.end()) {1661func = search->second->shader;1662} else {1663func = swr_compile_tcs(ctx, key);1664}16651666ctx->api.pfnSwrSetHsFunc(ctx->swrContext, func);16671668/* JIT sampler state */1669if (ctx->dirty & SWR_NEW_SAMPLER) {1670swr_update_sampler_state(ctx,1671PIPE_SHADER_TESS_CTRL,1672key.nr_samplers,1673ctx->swrDC.samplersTCS);1674}16751676/* JIT sampler view state */1677if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {1678swr_update_texture_state(ctx,1679PIPE_SHADER_TESS_CTRL,1680key.nr_sampler_views,1681ctx->swrDC.texturesTCS);1682}16831684// Update tessellation state in case it's been updated1685ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState);1686} else {1687ctx->api.pfnSwrSetHsFunc(ctx->swrContext, NULL);1688}1689}16901691/* VertexShader */1692if (ctx->dirty1693& (SWR_NEW_VS | SWR_NEW_RASTERIZER | // for clip planes1694SWR_NEW_SAMPLER | SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {1695swr_jit_vs_key key;1696swr_generate_vs_key(key, ctx, ctx->vs);1697auto search = ctx->vs->map.find(key);1698PFN_VERTEX_FUNC func;1699if (search != ctx->vs->map.end()) {1700func = search->second->shader;1701} else {1702func = swr_compile_vs(ctx, key);1703}1704ctx->api.pfnSwrSetVertexFunc(ctx->swrContext, func);17051706/* JIT sampler state */1707if (ctx->dirty & SWR_NEW_SAMPLER) {1708swr_update_sampler_state(1709ctx, PIPE_SHADER_VERTEX, key.nr_samplers, ctx->swrDC.samplersVS);1710}17111712/* JIT sampler view state */1713if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) {1714swr_update_texture_state(ctx,1715PIPE_SHADER_VERTEX,1716key.nr_sampler_views,1717ctx->swrDC.texturesVS);1718}1719}17201721/* work around the fact that poly stipple also affects lines */1722/* and points, since we rasterize them as triangles, too */1723/* Has to be before fragment shader, since it sets SWR_NEW_FS */1724if (p_draw_info) {1725bool new_prim_is_poly =1726(u_reduced_prim(p_draw_info->mode) == PIPE_PRIM_TRIANGLES) &&1727(ctx->derived.rastState.fillMode == SWR_FILLMODE_SOLID);1728if (new_prim_is_poly != ctx->poly_stipple.prim_is_poly) {1729ctx->dirty |= SWR_NEW_FS;1730ctx->poly_stipple.prim_is_poly = new_prim_is_poly;1731}1732}17331734/* FragmentShader */1735if (ctx->dirty & (SWR_NEW_FS |1736SWR_NEW_VS |1737SWR_NEW_GS |1738SWR_NEW_TES |1739SWR_NEW_TCS |1740SWR_NEW_RASTERIZER |1741SWR_NEW_SAMPLER |1742SWR_NEW_SAMPLER_VIEW |1743SWR_NEW_FRAMEBUFFER)) {1744swr_jit_fs_key key;1745swr_generate_fs_key(key, ctx, ctx->fs);1746auto search = ctx->fs->map.find(key);1747PFN_PIXEL_KERNEL func;1748if (search != ctx->fs->map.end()) {1749func = search->second->shader;1750} else {1751func = swr_compile_fs(ctx, key);1752}1753SWR_PS_STATE psState = {0};1754psState.pfnPixelShader = func;1755psState.killsPixel = ctx->fs->info.base.uses_kill;1756psState.inputCoverage = SWR_INPUT_COVERAGE_NORMAL;1757psState.writesODepth = ctx->fs->info.base.writes_z;1758psState.usesSourceDepth = ctx->fs->info.base.reads_z;1759psState.shadingRate = SWR_SHADING_RATE_PIXEL;1760psState.renderTargetMask = (1 << ctx->framebuffer.nr_cbufs) - 1;1761psState.posOffset = SWR_PS_POSITION_SAMPLE_NONE;1762uint32_t barycentricsMask = 0;1763#if 01764// when we switch to mesa-master1765if (ctx->fs->info.base.uses_persp_center ||1766ctx->fs->info.base.uses_linear_center)1767barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK;1768if (ctx->fs->info.base.uses_persp_centroid ||1769ctx->fs->info.base.uses_linear_centroid)1770barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK;1771if (ctx->fs->info.base.uses_persp_sample ||1772ctx->fs->info.base.uses_linear_sample)1773barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK;1774#else1775for (unsigned i = 0; i < ctx->fs->info.base.num_inputs; i++) {1776switch (ctx->fs->info.base.input_interpolate_loc[i]) {1777case TGSI_INTERPOLATE_LOC_CENTER:1778barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK;1779break;1780case TGSI_INTERPOLATE_LOC_CENTROID:1781barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK;1782break;1783case TGSI_INTERPOLATE_LOC_SAMPLE:1784barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK;1785break;1786}1787}1788#endif1789psState.barycentricsMask = barycentricsMask;1790psState.usesUAV = false; // XXX1791psState.forceEarlyZ = false;1792ctx->api.pfnSwrSetPixelShaderState(ctx->swrContext, &psState);17931794/* JIT sampler state */1795if (ctx->dirty & (SWR_NEW_SAMPLER |1796SWR_NEW_FS)) {1797swr_update_sampler_state(ctx,1798PIPE_SHADER_FRAGMENT,1799key.nr_samplers,1800ctx->swrDC.samplersFS);1801}18021803/* JIT sampler view state */1804if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW |1805SWR_NEW_FRAMEBUFFER |1806SWR_NEW_FS)) {1807swr_update_texture_state(ctx,1808PIPE_SHADER_FRAGMENT,1809key.nr_sampler_views,1810ctx->swrDC.texturesFS);1811}1812}181318141815/* VertexShader Constants */1816if (ctx->dirty & SWR_NEW_VSCONSTANTS) {1817swr_update_constants(ctx, PIPE_SHADER_VERTEX);1818}18191820/* FragmentShader Constants */1821if (ctx->dirty & SWR_NEW_FSCONSTANTS) {1822swr_update_constants(ctx, PIPE_SHADER_FRAGMENT);1823}18241825/* GeometryShader Constants */1826if (ctx->dirty & SWR_NEW_GSCONSTANTS) {1827swr_update_constants(ctx, PIPE_SHADER_GEOMETRY);1828}18291830/* Tessellation Control Shader Constants */1831if (ctx->dirty & SWR_NEW_TCSCONSTANTS) {1832swr_update_constants(ctx, PIPE_SHADER_TESS_CTRL);1833}18341835/* Tessellation Evaluation Shader Constants */1836if (ctx->dirty & SWR_NEW_TESCONSTANTS) {1837swr_update_constants(ctx, PIPE_SHADER_TESS_EVAL);1838}18391840/* Depth/stencil state */1841if (ctx->dirty & (SWR_NEW_DEPTH_STENCIL_ALPHA | SWR_NEW_FRAMEBUFFER)) {1842struct pipe_depth_stencil_alpha_state *depth = ctx->depth_stencil;1843struct pipe_stencil_state *stencil = depth->stencil;1844SWR_DEPTH_STENCIL_STATE depthStencilState = {{0}};1845SWR_DEPTH_BOUNDS_STATE depthBoundsState = {0};18461847/* XXX, incomplete. Need to flesh out stencil & alpha test state1848struct pipe_stencil_state *front_stencil =1849ctx->depth_stencil.stencil[0];1850struct pipe_stencil_state *back_stencil = ctx->depth_stencil.stencil[1];1851*/1852if (stencil[0].enabled) {1853depthStencilState.stencilWriteEnable = 1;1854depthStencilState.stencilTestEnable = 1;1855depthStencilState.stencilTestFunc =1856swr_convert_depth_func(stencil[0].func);18571858depthStencilState.stencilPassDepthPassOp =1859swr_convert_stencil_op(stencil[0].zpass_op);1860depthStencilState.stencilPassDepthFailOp =1861swr_convert_stencil_op(stencil[0].zfail_op);1862depthStencilState.stencilFailOp =1863swr_convert_stencil_op(stencil[0].fail_op);1864depthStencilState.stencilWriteMask = stencil[0].writemask;1865depthStencilState.stencilTestMask = stencil[0].valuemask;1866depthStencilState.stencilRefValue = ctx->stencil_ref.ref_value[0];1867}1868if (stencil[1].enabled) {1869depthStencilState.doubleSidedStencilTestEnable = 1;18701871depthStencilState.backfaceStencilTestFunc =1872swr_convert_depth_func(stencil[1].func);18731874depthStencilState.backfaceStencilPassDepthPassOp =1875swr_convert_stencil_op(stencil[1].zpass_op);1876depthStencilState.backfaceStencilPassDepthFailOp =1877swr_convert_stencil_op(stencil[1].zfail_op);1878depthStencilState.backfaceStencilFailOp =1879swr_convert_stencil_op(stencil[1].fail_op);1880depthStencilState.backfaceStencilWriteMask = stencil[1].writemask;1881depthStencilState.backfaceStencilTestMask = stencil[1].valuemask;18821883depthStencilState.backfaceStencilRefValue =1884ctx->stencil_ref.ref_value[1];1885}18861887depthStencilState.depthTestEnable = depth->depth_enabled;1888depthStencilState.depthTestFunc = swr_convert_depth_func(depth->depth_func);1889depthStencilState.depthWriteEnable = depth->depth_writemask;1890ctx->api.pfnSwrSetDepthStencilState(ctx->swrContext, &depthStencilState);18911892depthBoundsState.depthBoundsTestEnable = depth->depth_bounds_test;1893depthBoundsState.depthBoundsTestMinValue = depth->depth_bounds_min;1894depthBoundsState.depthBoundsTestMaxValue = depth->depth_bounds_max;1895ctx->api.pfnSwrSetDepthBoundsState(ctx->swrContext, &depthBoundsState);1896}18971898/* Blend State */1899if (ctx->dirty & (SWR_NEW_BLEND |1900SWR_NEW_RASTERIZER |1901SWR_NEW_FRAMEBUFFER |1902SWR_NEW_DEPTH_STENCIL_ALPHA)) {1903struct pipe_framebuffer_state *fb = &ctx->framebuffer;19041905SWR_BLEND_STATE blendState;1906memcpy(&blendState, &ctx->blend->blendState, sizeof(blendState));1907blendState.constantColor[0] = ctx->blend_color.color[0];1908blendState.constantColor[1] = ctx->blend_color.color[1];1909blendState.constantColor[2] = ctx->blend_color.color[2];1910blendState.constantColor[3] = ctx->blend_color.color[3];1911blendState.alphaTestReference =1912*((uint32_t*)&ctx->depth_stencil->alpha_ref_value);19131914blendState.sampleMask = ctx->sample_mask;1915blendState.sampleCount = GetSampleCount(fb->samples);19161917/* If there are no color buffers bound, disable writes on RT01918* and skip loop */1919if (fb->nr_cbufs == 0) {1920blendState.renderTarget[0].writeDisableRed = 1;1921blendState.renderTarget[0].writeDisableGreen = 1;1922blendState.renderTarget[0].writeDisableBlue = 1;1923blendState.renderTarget[0].writeDisableAlpha = 1;1924ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, 0, NULL);1925}1926else1927for (int target = 0;1928target < std::min(SWR_NUM_RENDERTARGETS,1929PIPE_MAX_COLOR_BUFS);1930target++) {1931if (!fb->cbufs[target])1932continue;19331934struct swr_resource *colorBuffer =1935swr_resource(fb->cbufs[target]->texture);19361937BLEND_COMPILE_STATE compileState;1938memset(&compileState, 0, sizeof(compileState));1939compileState.format = colorBuffer->swr.format;1940memcpy(&compileState.blendState,1941&ctx->blend->compileState[target],1942sizeof(compileState.blendState));19431944const SWR_FORMAT_INFO& info = GetFormatInfo(compileState.format);1945if (compileState.blendState.logicOpEnable &&1946((info.type[0] == SWR_TYPE_FLOAT) || info.isSRGB)) {1947compileState.blendState.logicOpEnable = false;1948}19491950if (info.type[0] == SWR_TYPE_SINT || info.type[0] == SWR_TYPE_UINT)1951compileState.blendState.blendEnable = false;19521953if (compileState.blendState.blendEnable == false &&1954compileState.blendState.logicOpEnable == false &&1955ctx->depth_stencil->alpha_enabled == 0) {1956ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, NULL);1957continue;1958}19591960compileState.desc.alphaTestEnable =1961ctx->depth_stencil->alpha_enabled;1962compileState.desc.independentAlphaBlendEnable =1963(compileState.blendState.sourceBlendFactor !=1964compileState.blendState.sourceAlphaBlendFactor) ||1965(compileState.blendState.destBlendFactor !=1966compileState.blendState.destAlphaBlendFactor) ||1967(compileState.blendState.colorBlendFunc !=1968compileState.blendState.alphaBlendFunc);1969compileState.desc.alphaToCoverageEnable =1970ctx->blend->pipe.alpha_to_coverage;1971compileState.desc.sampleMaskEnable = (blendState.sampleMask != 0);1972compileState.desc.numSamples = fb->samples;19731974compileState.alphaTestFunction =1975swr_convert_depth_func(ctx->depth_stencil->alpha_func);1976compileState.alphaTestFormat = ALPHA_TEST_FLOAT32; // xxx19771978compileState.Canonicalize();19791980PFN_BLEND_JIT_FUNC func = NULL;1981auto search = ctx->blendJIT->find(compileState);1982if (search != ctx->blendJIT->end()) {1983func = search->second;1984} else {1985HANDLE hJitMgr = screen->hJitMgr;1986func = JitCompileBlend(hJitMgr, compileState);1987debug_printf("BLEND shader %p\n", func);1988assert(func && "Error: BlendShader = NULL");19891990ctx->blendJIT->insert(std::make_pair(compileState, func));1991}1992ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, func);1993}19941995ctx->api.pfnSwrSetBlendState(ctx->swrContext, &blendState);1996}19971998if (ctx->dirty & SWR_NEW_STIPPLE) {1999swr_update_poly_stipple(ctx);2000}20012002if (ctx->dirty & (SWR_NEW_VS | SWR_NEW_TCS | SWR_NEW_TES | SWR_NEW_SO | SWR_NEW_RASTERIZER)) {2003ctx->vs->soState.rasterizerDisable =2004ctx->rasterizer->rasterizer_discard;2005ctx->api.pfnSwrSetSoState(ctx->swrContext, &ctx->vs->soState);20062007pipe_stream_output_info *stream_output = &ctx->vs->pipe.stream_output;20082009for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) {2010SWR_STREAMOUT_BUFFER buffer = {0};2011if (ctx->so_targets[i]) {2012buffer.enable = true;2013buffer.pBuffer =2014(gfxptr_t)(swr_resource_data(ctx->so_targets[i]->buffer) +2015ctx->so_targets[i]->buffer_offset);2016buffer.bufferSize = ctx->so_targets[i]->buffer_size >> 2;2017buffer.pitch = stream_output->stride[i];2018buffer.streamOffset = 0;2019}20202021ctx->api.pfnSwrSetSoBuffers(ctx->swrContext, &buffer, i);2022}2023}202420252026if (ctx->dirty & (SWR_NEW_CLIP | SWR_NEW_RASTERIZER | SWR_NEW_VS)) {2027// shader exporting clip distances overrides all user clip planes2028if (ctx->rasterizer->clip_plane_enable &&2029!swr_get_last_fe(ctx)->num_written_clipdistance)2030{2031swr_draw_context *pDC = &ctx->swrDC;2032memcpy(pDC->userClipPlanes,2033ctx->clip.ucp,2034sizeof(pDC->userClipPlanes));2035}2036}20372038// set up backend state2039SWR_BACKEND_STATE backendState = {0};2040if (ctx->gs) {2041backendState.numAttributes = ctx->gs->info.base.num_outputs - 1;2042} else2043if (ctx->tes) {2044backendState.numAttributes = ctx->tes->info.base.num_outputs - 1;2045// no case for TCS, because if TCS is active, TES must be active2046// as well - pipeline stages after tessellation does not support patches2047} else {2048backendState.numAttributes = ctx->vs->info.base.num_outputs - 1;2049if (ctx->fs->info.base.uses_primid) {2050backendState.numAttributes++;2051backendState.swizzleEnable = true;2052for (unsigned i = 0; i < sizeof(backendState.numComponents); i++) {2053backendState.swizzleMap[i].sourceAttrib = i;2054}2055backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].constantSource =2056SWR_CONSTANT_SOURCE_PRIM_ID;2057backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].componentOverrideMask = 1;2058}2059}2060if (ctx->rasterizer->sprite_coord_enable)2061backendState.numAttributes++;20622063backendState.numAttributes = std::min((size_t)backendState.numAttributes,2064sizeof(backendState.numComponents));2065for (unsigned i = 0; i < backendState.numAttributes; i++)2066backendState.numComponents[i] = 4;2067backendState.constantInterpolationMask = ctx->fs->constantMask |2068(ctx->rasterizer->flatshade ? ctx->fs->flatConstantMask : 0);2069backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask;20702071struct tgsi_shader_info *pLastFE = swr_get_last_fe(ctx);20722073backendState.readRenderTargetArrayIndex = pLastFE->writes_layer;2074backendState.readViewportArrayIndex = pLastFE->writes_viewport_index;2075backendState.vertexAttribOffset = VERTEX_ATTRIB_START_SLOT; // TODO: optimize20762077backendState.clipDistanceMask =2078pLastFE->num_written_clipdistance ?2079pLastFE->clipdist_writemask & ctx->rasterizer->clip_plane_enable :2080ctx->rasterizer->clip_plane_enable;20812082backendState.cullDistanceMask =2083pLastFE->culldist_writemask << pLastFE->num_written_clipdistance;20842085// Assume old layout of SGV, POSITION, CLIPCULL, ATTRIB2086backendState.vertexClipCullOffset = backendState.vertexAttribOffset - 2;20872088ctx->api.pfnSwrSetBackendState(ctx->swrContext, &backendState);20892090/* Ensure that any in-progress attachment change StoreTiles finish */2091if (swr_is_fence_pending(screen->flush_fence))2092swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0);20932094/* Finally, update the in-use status of all resources involved in draw */2095swr_update_resource_status(pipe, p_draw_info);20962097ctx->dirty = post_update_dirty_flags;2098}209921002101static struct pipe_stream_output_target *2102swr_create_so_target(struct pipe_context *pipe,2103struct pipe_resource *buffer,2104unsigned buffer_offset,2105unsigned buffer_size)2106{2107struct pipe_stream_output_target *target;21082109target = CALLOC_STRUCT(pipe_stream_output_target);2110if (!target)2111return NULL;21122113target->context = pipe;2114target->reference.count = 1;2115pipe_resource_reference(&target->buffer, buffer);2116target->buffer_offset = buffer_offset;2117target->buffer_size = buffer_size;2118return target;2119}21202121static void2122swr_destroy_so_target(struct pipe_context *pipe,2123struct pipe_stream_output_target *target)2124{2125pipe_resource_reference(&target->buffer, NULL);2126FREE(target);2127}21282129static void2130swr_set_so_targets(struct pipe_context *pipe,2131unsigned num_targets,2132struct pipe_stream_output_target **targets,2133const unsigned *offsets)2134{2135struct swr_context *swr = swr_context(pipe);2136uint32_t i;21372138assert(num_targets <= MAX_SO_STREAMS);21392140for (i = 0; i < num_targets; i++) {2141pipe_so_target_reference(2142(struct pipe_stream_output_target **)&swr->so_targets[i],2143targets[i]);2144}21452146for (/* fall-through */; i < swr->num_so_targets; i++) {2147pipe_so_target_reference(2148(struct pipe_stream_output_target **)&swr->so_targets[i], NULL);2149}21502151swr->num_so_targets = num_targets;2152swr->swrDC.soPrims = &swr->so_primCounter;21532154swr->dirty |= SWR_NEW_SO;2155}215621572158void2159swr_state_init(struct pipe_context *pipe)2160{2161pipe->create_blend_state = swr_create_blend_state;2162pipe->bind_blend_state = swr_bind_blend_state;2163pipe->delete_blend_state = swr_delete_blend_state;21642165pipe->create_depth_stencil_alpha_state = swr_create_depth_stencil_state;2166pipe->bind_depth_stencil_alpha_state = swr_bind_depth_stencil_state;2167pipe->delete_depth_stencil_alpha_state = swr_delete_depth_stencil_state;21682169pipe->create_rasterizer_state = swr_create_rasterizer_state;2170pipe->bind_rasterizer_state = swr_bind_rasterizer_state;2171pipe->delete_rasterizer_state = swr_delete_rasterizer_state;21722173pipe->create_sampler_state = swr_create_sampler_state;2174pipe->bind_sampler_states = swr_bind_sampler_states;2175pipe->delete_sampler_state = swr_delete_sampler_state;21762177pipe->create_sampler_view = swr_create_sampler_view;2178pipe->set_sampler_views = swr_set_sampler_views;2179pipe->sampler_view_destroy = swr_sampler_view_destroy;21802181pipe->create_vs_state = swr_create_vs_state;2182pipe->bind_vs_state = swr_bind_vs_state;2183pipe->delete_vs_state = swr_delete_vs_state;21842185pipe->create_fs_state = swr_create_fs_state;2186pipe->bind_fs_state = swr_bind_fs_state;2187pipe->delete_fs_state = swr_delete_fs_state;21882189pipe->create_gs_state = swr_create_gs_state;2190pipe->bind_gs_state = swr_bind_gs_state;2191pipe->delete_gs_state = swr_delete_gs_state;21922193pipe->create_tcs_state = swr_create_tcs_state;2194pipe->bind_tcs_state = swr_bind_tcs_state;2195pipe->delete_tcs_state = swr_delete_tcs_state;21962197pipe->create_tes_state = swr_create_tes_state;2198pipe->bind_tes_state = swr_bind_tes_state;2199pipe->delete_tes_state = swr_delete_tes_state;22002201pipe->set_constant_buffer = swr_set_constant_buffer;22022203pipe->create_vertex_elements_state = swr_create_vertex_elements_state;2204pipe->bind_vertex_elements_state = swr_bind_vertex_elements_state;2205pipe->delete_vertex_elements_state = swr_delete_vertex_elements_state;22062207pipe->set_vertex_buffers = swr_set_vertex_buffers;22082209pipe->set_polygon_stipple = swr_set_polygon_stipple;2210pipe->set_clip_state = swr_set_clip_state;2211pipe->set_scissor_states = swr_set_scissor_states;2212pipe->set_viewport_states = swr_set_viewport_states;22132214pipe->set_framebuffer_state = swr_set_framebuffer_state;22152216pipe->set_blend_color = swr_set_blend_color;2217pipe->set_stencil_ref = swr_set_stencil_ref;22182219pipe->set_sample_mask = swr_set_sample_mask;2220pipe->get_sample_position = swr_get_sample_position;22212222pipe->create_stream_output_target = swr_create_so_target;2223pipe->stream_output_target_destroy = swr_destroy_so_target;2224pipe->set_stream_output_targets = swr_set_so_targets;2225}222622272228