Path: blob/21.2-virgl/src/gallium/drivers/softpipe/sp_state_shader.c
4570 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "sp_context.h"28#include "sp_screen.h"29#include "sp_state.h"30#include "sp_fs.h"31#include "sp_texture.h"3233#include "nir.h"34#include "nir/nir_to_tgsi.h"35#include "pipe/p_defines.h"36#include "util/ralloc.h"37#include "util/u_memory.h"38#include "util/u_inlines.h"39#include "util/u_pstipple.h"40#include "draw/draw_context.h"41#include "draw/draw_vs.h"42#include "draw/draw_gs.h"43#include "tgsi/tgsi_dump.h"44#include "tgsi/tgsi_from_mesa.h"45#include "tgsi/tgsi_scan.h"46#include "tgsi/tgsi_parse.h"47#include "compiler/shader_enums.h"484950/**51* Create a new fragment shader variant.52*/53static struct sp_fragment_shader_variant *54create_fs_variant(struct softpipe_context *softpipe,55struct sp_fragment_shader *fs,56const struct sp_fragment_shader_variant_key *key)57{58struct sp_fragment_shader_variant *var;59struct pipe_shader_state *curfs = &fs->shader;6061/* codegen, create variant object */62var = softpipe_create_fs_variant_exec(softpipe);6364if (var) {65var->key = *key;6667#if DO_PSTIPPLE_IN_HELPER_MODULE68if (key->polygon_stipple) {69/* get new shader that implements polygon stippling */70var->tokens =71util_pstipple_create_fragment_shader(curfs->tokens,72&var->stipple_sampler_unit, 0,73TGSI_FILE_INPUT);74}75else76#endif77{78var->tokens = tgsi_dup_tokens(curfs->tokens);79var->stipple_sampler_unit = 0;80}8182tgsi_scan_shader(var->tokens, &var->info);8384/* See comments elsewhere about draw fragment shaders */85#if 086/* draw's fs state */87var->draw_shader = draw_create_fragment_shader(softpipe->draw,88&fs->shader);89if (!var->draw_shader) {90var->delete(var);91FREE((void *) var->tokens);92return NULL;93}94#endif9596/* insert variant into linked list */97var->next = fs->variants;98fs->variants = var;99}100101return var;102}103104105struct sp_fragment_shader_variant *106softpipe_find_fs_variant(struct softpipe_context *sp,107struct sp_fragment_shader *fs,108const struct sp_fragment_shader_variant_key *key)109{110struct sp_fragment_shader_variant *var;111112for (var = fs->variants; var; var = var->next) {113if (memcmp(&var->key, key, sizeof(*key)) == 0) {114/* found it */115return var;116}117}118119return create_fs_variant(sp, fs, key);120}121122static void123softpipe_shader_db(struct pipe_context *pipe, const struct tgsi_token *tokens)124{125struct softpipe_context *softpipe = softpipe_context(pipe);126127struct tgsi_shader_info info;128tgsi_scan_shader(tokens, &info);129pipe_debug_message(&softpipe->debug, SHADER_INFO, "%s shader: %d inst, %d loops, %d temps, %d const, %d imm",130_mesa_shader_stage_to_abbrev(tgsi_processor_to_shader_stage(info.processor)),131info.num_instructions,132info.opcode_count[TGSI_OPCODE_BGNLOOP],133info.file_max[TGSI_FILE_TEMPORARY] + 1,134info.file_max[TGSI_FILE_CONSTANT] + 1,135info.immediate_count);136}137138static void139softpipe_create_shader_state(struct pipe_context *pipe,140struct pipe_shader_state *shader,141const struct pipe_shader_state *templ,142bool debug)143{144if (templ->type == PIPE_SHADER_IR_NIR) {145if (debug)146nir_print_shader(templ->ir.nir, stderr);147148shader->tokens = nir_to_tgsi(templ->ir.nir, pipe->screen);149} else {150assert(templ->type == PIPE_SHADER_IR_TGSI);151/* we need to keep a local copy of the tokens */152shader->tokens = tgsi_dup_tokens(templ->tokens);153}154155shader->type = PIPE_SHADER_IR_TGSI;156157shader->stream_output = templ->stream_output;158159if (debug)160tgsi_dump(shader->tokens, 0);161162softpipe_shader_db(pipe, shader->tokens);163}164165static void *166softpipe_create_fs_state(struct pipe_context *pipe,167const struct pipe_shader_state *templ)168{169struct softpipe_context *softpipe = softpipe_context(pipe);170struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);171172softpipe_create_shader_state(pipe, &state->shader, templ,173sp_debug & SP_DBG_FS);174175/* draw's fs state */176state->draw_shader = draw_create_fragment_shader(softpipe->draw,177&state->shader);178if (!state->draw_shader) {179tgsi_free_tokens(state->shader.tokens);180FREE(state);181return NULL;182}183184return state;185}186187188static void189softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)190{191struct softpipe_context *softpipe = softpipe_context(pipe);192struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;193194if (softpipe->fs == fs)195return;196197draw_flush(softpipe->draw);198199softpipe->fs = fs;200201/* This depends on the current fragment shader and must always be202* re-validated before use.203*/204softpipe->fs_variant = NULL;205206if (state)207draw_bind_fragment_shader(softpipe->draw,208state->draw_shader);209else210draw_bind_fragment_shader(softpipe->draw, NULL);211212softpipe->dirty |= SP_NEW_FS;213}214215216static void217softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)218{219struct softpipe_context *softpipe = softpipe_context(pipe);220struct sp_fragment_shader *state = fs;221struct sp_fragment_shader_variant *var, *next_var;222223assert(fs != softpipe->fs);224225/* delete variants */226for (var = state->variants; var; var = next_var) {227next_var = var->next;228229assert(var != softpipe->fs_variant);230231/* See comments elsewhere about draw fragment shaders */232#if 0233draw_delete_fragment_shader(softpipe->draw, var->draw_shader);234#endif235236var->delete(var, softpipe->fs_machine);237}238239draw_delete_fragment_shader(softpipe->draw, state->draw_shader);240241tgsi_free_tokens(state->shader.tokens);242FREE(state);243}244245246static void *247softpipe_create_vs_state(struct pipe_context *pipe,248const struct pipe_shader_state *templ)249{250struct softpipe_context *softpipe = softpipe_context(pipe);251struct sp_vertex_shader *state;252253state = CALLOC_STRUCT(sp_vertex_shader);254if (!state)255goto fail;256257softpipe_create_shader_state(pipe, &state->shader, templ,258sp_debug & SP_DBG_VS);259if (!state->shader.tokens)260goto fail;261262state->draw_data = draw_create_vertex_shader(softpipe->draw, &state->shader);263if (state->draw_data == NULL)264goto fail;265266state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];267268return state;269270fail:271if (state) {272tgsi_free_tokens(state->shader.tokens);273FREE( state->draw_data );274FREE( state );275}276return NULL;277}278279280static void281softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)282{283struct softpipe_context *softpipe = softpipe_context(pipe);284285softpipe->vs = (struct sp_vertex_shader *) vs;286287draw_bind_vertex_shader(softpipe->draw,288(softpipe->vs ? softpipe->vs->draw_data : NULL));289290softpipe->dirty |= SP_NEW_VS;291}292293294static void295softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)296{297struct softpipe_context *softpipe = softpipe_context(pipe);298299struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;300301draw_delete_vertex_shader(softpipe->draw, state->draw_data);302tgsi_free_tokens(state->shader.tokens);303FREE( state );304}305306307static void *308softpipe_create_gs_state(struct pipe_context *pipe,309const struct pipe_shader_state *templ)310{311struct softpipe_context *softpipe = softpipe_context(pipe);312struct sp_geometry_shader *state;313314state = CALLOC_STRUCT(sp_geometry_shader);315if (!state)316goto fail;317318softpipe_create_shader_state(pipe, &state->shader, templ,319sp_debug & SP_DBG_GS);320321if (state->shader.tokens) {322state->draw_data = draw_create_geometry_shader(softpipe->draw,323&state->shader);324if (state->draw_data == NULL)325goto fail;326327state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];328}329330return state;331332fail:333if (state) {334tgsi_free_tokens(state->shader.tokens);335FREE( state->draw_data );336FREE( state );337}338return NULL;339}340341342static void343softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)344{345struct softpipe_context *softpipe = softpipe_context(pipe);346347softpipe->gs = (struct sp_geometry_shader *)gs;348349draw_bind_geometry_shader(softpipe->draw,350(softpipe->gs ? softpipe->gs->draw_data : NULL));351352softpipe->dirty |= SP_NEW_GS;353}354355356static void357softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)358{359struct softpipe_context *softpipe = softpipe_context(pipe);360361struct sp_geometry_shader *state =362(struct sp_geometry_shader *)gs;363364draw_delete_geometry_shader(softpipe->draw,365(state) ? state->draw_data : 0);366367tgsi_free_tokens(state->shader.tokens);368FREE(state);369}370371372static void373softpipe_set_constant_buffer(struct pipe_context *pipe,374enum pipe_shader_type shader, uint index,375bool take_ownership,376const struct pipe_constant_buffer *cb)377{378struct softpipe_context *softpipe = softpipe_context(pipe);379struct pipe_resource *constants = cb ? cb->buffer : NULL;380unsigned size;381const void *data;382383assert(shader < PIPE_SHADER_TYPES);384385if (cb && cb->user_buffer) {386constants = softpipe_user_buffer_create(pipe->screen,387(void *) cb->user_buffer,388cb->buffer_size,389PIPE_BIND_CONSTANT_BUFFER);390}391392size = cb ? cb->buffer_size : 0;393data = constants ? softpipe_resource_data(constants) : NULL;394if (data)395data = (const char *) data + cb->buffer_offset;396397draw_flush(softpipe->draw);398399/* note: reference counting */400if (take_ownership) {401pipe_resource_reference(&softpipe->constants[shader][index], NULL);402softpipe->constants[shader][index] = constants;403} else {404pipe_resource_reference(&softpipe->constants[shader][index], constants);405}406407if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {408draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);409}410411softpipe->mapped_constants[shader][index] = data;412softpipe->const_buffer_size[shader][index] = size;413414softpipe->dirty |= SP_NEW_CONSTANTS;415416if (cb && cb->user_buffer) {417pipe_resource_reference(&constants, NULL);418}419}420421static void *422softpipe_create_compute_state(struct pipe_context *pipe,423const struct pipe_compute_state *templ)424{425struct sp_compute_shader *state = CALLOC_STRUCT(sp_compute_shader);426427state->shader = *templ;428429if (templ->ir_type == PIPE_SHADER_IR_NIR) {430nir_shader *s = (void *)templ->prog;431432if (sp_debug & SP_DBG_CS)433nir_print_shader(s, stderr);434435state->tokens = (void *)nir_to_tgsi(s, pipe->screen);436} else {437assert(templ->ir_type == PIPE_SHADER_IR_TGSI);438/* we need to keep a local copy of the tokens */439state->tokens = tgsi_dup_tokens(templ->prog);440}441442if (sp_debug & SP_DBG_CS)443tgsi_dump(state->tokens, 0);444445softpipe_shader_db(pipe, state->tokens);446447tgsi_scan_shader(state->tokens, &state->info);448449state->max_sampler = state->info.file_max[TGSI_FILE_SAMPLER];450451return state;452}453454static void455softpipe_bind_compute_state(struct pipe_context *pipe,456void *cs)457{458struct softpipe_context *softpipe = softpipe_context(pipe);459struct sp_compute_shader *state = (struct sp_compute_shader *)cs;460if (softpipe->cs == state)461return;462463softpipe->cs = state;464}465466static void467softpipe_delete_compute_state(struct pipe_context *pipe,468void *cs)469{470ASSERTED struct softpipe_context *softpipe = softpipe_context(pipe);471struct sp_compute_shader *state = (struct sp_compute_shader *)cs;472473assert(softpipe->cs != state);474tgsi_free_tokens(state->tokens);475FREE(state);476}477478void479softpipe_init_shader_funcs(struct pipe_context *pipe)480{481pipe->create_fs_state = softpipe_create_fs_state;482pipe->bind_fs_state = softpipe_bind_fs_state;483pipe->delete_fs_state = softpipe_delete_fs_state;484485pipe->create_vs_state = softpipe_create_vs_state;486pipe->bind_vs_state = softpipe_bind_vs_state;487pipe->delete_vs_state = softpipe_delete_vs_state;488489pipe->create_gs_state = softpipe_create_gs_state;490pipe->bind_gs_state = softpipe_bind_gs_state;491pipe->delete_gs_state = softpipe_delete_gs_state;492493pipe->set_constant_buffer = softpipe_set_constant_buffer;494495pipe->create_compute_state = softpipe_create_compute_state;496pipe->bind_compute_state = softpipe_bind_compute_state;497pipe->delete_compute_state = softpipe_delete_compute_state;498}499500501