101e04c3fSmrg/**************************************************************************** 201e04c3fSmrg * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg ***************************************************************************/ 2301e04c3fSmrg 247ec681f3Smrg#include <llvm/Config/llvm-config.h> 257ec681f3Smrg 267ec681f3Smrg#if LLVM_VERSION_MAJOR < 7 2701e04c3fSmrg// llvm redefines DEBUG 2801e04c3fSmrg#pragma push_macro("DEBUG") 2901e04c3fSmrg#undef DEBUG 307ec681f3Smrg#endif 317ec681f3Smrg 327ec681f3Smrg#include <rasterizer/core/state.h> 3301e04c3fSmrg#include "JitManager.h" 347ec681f3Smrg 357ec681f3Smrg#if LLVM_VERSION_MAJOR < 7 3601e04c3fSmrg#pragma pop_macro("DEBUG") 377ec681f3Smrg#endif 3801e04c3fSmrg 3901e04c3fSmrg#include "common/os.h" 4001e04c3fSmrg#include "jit_api.h" 4101e04c3fSmrg#include "gen_state_llvm.h" 4201e04c3fSmrg#include "core/multisample.h" 4301e04c3fSmrg#include "core/state_funcs.h" 4401e04c3fSmrg 4501e04c3fSmrg#include "gallivm/lp_bld_tgsi.h" 467ec681f3Smrg#include "util/format/u_format.h" 4701e04c3fSmrg 4801e04c3fSmrg#include "util/u_memory.h" 4901e04c3fSmrg#include "util/u_inlines.h" 5001e04c3fSmrg#include "util/u_helpers.h" 5101e04c3fSmrg#include "util/u_framebuffer.h" 5201e04c3fSmrg#include "util/u_viewport.h" 5301e04c3fSmrg#include "util/u_prim.h" 5401e04c3fSmrg 5501e04c3fSmrg#include "swr_state.h" 5601e04c3fSmrg#include "swr_context.h" 577ec681f3Smrg#include "gen_surf_state_llvm.h" 5801e04c3fSmrg#include "gen_swr_context_llvm.h" 5901e04c3fSmrg#include "swr_screen.h" 6001e04c3fSmrg#include "swr_resource.h" 6101e04c3fSmrg#include "swr_tex_sample.h" 6201e04c3fSmrg#include "swr_scratch.h" 6301e04c3fSmrg#include "swr_shader.h" 6401e04c3fSmrg#include "swr_fence.h" 6501e04c3fSmrg 6601e04c3fSmrg/* These should be pulled out into separate files as necessary 6701e04c3fSmrg * Just initializing everything here to get going. */ 6801e04c3fSmrg 6901e04c3fSmrgstatic void * 7001e04c3fSmrgswr_create_blend_state(struct pipe_context *pipe, 7101e04c3fSmrg const struct pipe_blend_state *blend) 7201e04c3fSmrg{ 7301e04c3fSmrg struct swr_blend_state *state = CALLOC_STRUCT(swr_blend_state); 747ec681f3Smrg assert(state != nullptr); 7501e04c3fSmrg 7601e04c3fSmrg memcpy(&state->pipe, blend, sizeof(*blend)); 7701e04c3fSmrg 7801e04c3fSmrg struct pipe_blend_state *pipe_blend = &state->pipe; 7901e04c3fSmrg 8001e04c3fSmrg for (int target = 0; 8101e04c3fSmrg target < std::min(SWR_NUM_RENDERTARGETS, PIPE_MAX_COLOR_BUFS); 8201e04c3fSmrg target++) { 8301e04c3fSmrg 8401e04c3fSmrg struct pipe_rt_blend_state *rt_blend = &pipe_blend->rt[target]; 8501e04c3fSmrg SWR_RENDER_TARGET_BLEND_STATE &blendState = 8601e04c3fSmrg state->blendState.renderTarget[target]; 8701e04c3fSmrg RENDER_TARGET_BLEND_COMPILE_STATE &compileState = 8801e04c3fSmrg state->compileState[target]; 8901e04c3fSmrg 9001e04c3fSmrg if (target != 0 && !pipe_blend->independent_blend_enable) { 9101e04c3fSmrg memcpy(&compileState, 9201e04c3fSmrg &state->compileState[0], 9301e04c3fSmrg sizeof(RENDER_TARGET_BLEND_COMPILE_STATE)); 9401e04c3fSmrg continue; 9501e04c3fSmrg } 9601e04c3fSmrg 9701e04c3fSmrg compileState.blendEnable = rt_blend->blend_enable; 9801e04c3fSmrg if (compileState.blendEnable) { 9901e04c3fSmrg compileState.sourceAlphaBlendFactor = 10001e04c3fSmrg swr_convert_blend_factor(rt_blend->alpha_src_factor); 10101e04c3fSmrg compileState.destAlphaBlendFactor = 10201e04c3fSmrg swr_convert_blend_factor(rt_blend->alpha_dst_factor); 10301e04c3fSmrg compileState.sourceBlendFactor = 10401e04c3fSmrg swr_convert_blend_factor(rt_blend->rgb_src_factor); 10501e04c3fSmrg compileState.destBlendFactor = 10601e04c3fSmrg swr_convert_blend_factor(rt_blend->rgb_dst_factor); 10701e04c3fSmrg 10801e04c3fSmrg compileState.colorBlendFunc = 10901e04c3fSmrg swr_convert_blend_func(rt_blend->rgb_func); 11001e04c3fSmrg compileState.alphaBlendFunc = 11101e04c3fSmrg swr_convert_blend_func(rt_blend->alpha_func); 11201e04c3fSmrg } 11301e04c3fSmrg compileState.logicOpEnable = state->pipe.logicop_enable; 11401e04c3fSmrg if (compileState.logicOpEnable) { 11501e04c3fSmrg compileState.logicOpFunc = 11601e04c3fSmrg swr_convert_logic_op(state->pipe.logicop_func); 11701e04c3fSmrg } 11801e04c3fSmrg 11901e04c3fSmrg blendState.writeDisableRed = 12001e04c3fSmrg (rt_blend->colormask & PIPE_MASK_R) ? 0 : 1; 12101e04c3fSmrg blendState.writeDisableGreen = 12201e04c3fSmrg (rt_blend->colormask & PIPE_MASK_G) ? 0 : 1; 12301e04c3fSmrg blendState.writeDisableBlue = 12401e04c3fSmrg (rt_blend->colormask & PIPE_MASK_B) ? 0 : 1; 12501e04c3fSmrg blendState.writeDisableAlpha = 12601e04c3fSmrg (rt_blend->colormask & PIPE_MASK_A) ? 0 : 1; 12701e04c3fSmrg 12801e04c3fSmrg if (rt_blend->colormask == 0) 12901e04c3fSmrg compileState.blendEnable = false; 13001e04c3fSmrg } 13101e04c3fSmrg 13201e04c3fSmrg return state; 13301e04c3fSmrg} 13401e04c3fSmrg 13501e04c3fSmrgstatic void 13601e04c3fSmrgswr_bind_blend_state(struct pipe_context *pipe, void *blend) 13701e04c3fSmrg{ 13801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 13901e04c3fSmrg 14001e04c3fSmrg if (ctx->blend == blend) 14101e04c3fSmrg return; 14201e04c3fSmrg 14301e04c3fSmrg ctx->blend = (swr_blend_state *)blend; 14401e04c3fSmrg 14501e04c3fSmrg ctx->dirty |= SWR_NEW_BLEND; 14601e04c3fSmrg} 14701e04c3fSmrg 14801e04c3fSmrgstatic void 14901e04c3fSmrgswr_delete_blend_state(struct pipe_context *pipe, void *blend) 15001e04c3fSmrg{ 15101e04c3fSmrg FREE(blend); 15201e04c3fSmrg} 15301e04c3fSmrg 15401e04c3fSmrgstatic void 15501e04c3fSmrgswr_set_blend_color(struct pipe_context *pipe, 15601e04c3fSmrg const struct pipe_blend_color *color) 15701e04c3fSmrg{ 15801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 15901e04c3fSmrg 16001e04c3fSmrg ctx->blend_color = *color; 16101e04c3fSmrg 16201e04c3fSmrg ctx->dirty |= SWR_NEW_BLEND; 16301e04c3fSmrg} 16401e04c3fSmrg 16501e04c3fSmrgstatic void 16601e04c3fSmrgswr_set_stencil_ref(struct pipe_context *pipe, 1677ec681f3Smrg const struct pipe_stencil_ref ref) 16801e04c3fSmrg{ 16901e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 17001e04c3fSmrg 1717ec681f3Smrg ctx->stencil_ref = ref; 17201e04c3fSmrg 17301e04c3fSmrg ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA; 17401e04c3fSmrg} 17501e04c3fSmrg 17601e04c3fSmrgstatic void * 17701e04c3fSmrgswr_create_depth_stencil_state( 17801e04c3fSmrg struct pipe_context *pipe, 17901e04c3fSmrg const struct pipe_depth_stencil_alpha_state *depth_stencil) 18001e04c3fSmrg{ 18101e04c3fSmrg struct pipe_depth_stencil_alpha_state *state; 18201e04c3fSmrg 18301e04c3fSmrg state = (pipe_depth_stencil_alpha_state *)mem_dup(depth_stencil, 18401e04c3fSmrg sizeof *depth_stencil); 18501e04c3fSmrg 18601e04c3fSmrg return state; 18701e04c3fSmrg} 18801e04c3fSmrg 18901e04c3fSmrgstatic void 19001e04c3fSmrgswr_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) 19101e04c3fSmrg{ 19201e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 19301e04c3fSmrg 19401e04c3fSmrg if (ctx->depth_stencil == (pipe_depth_stencil_alpha_state *)depth_stencil) 19501e04c3fSmrg return; 19601e04c3fSmrg 19701e04c3fSmrg ctx->depth_stencil = (pipe_depth_stencil_alpha_state *)depth_stencil; 19801e04c3fSmrg 19901e04c3fSmrg ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA; 20001e04c3fSmrg} 20101e04c3fSmrg 20201e04c3fSmrgstatic void 20301e04c3fSmrgswr_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) 20401e04c3fSmrg{ 20501e04c3fSmrg FREE(depth); 20601e04c3fSmrg} 20701e04c3fSmrg 20801e04c3fSmrg 20901e04c3fSmrgstatic void * 21001e04c3fSmrgswr_create_rasterizer_state(struct pipe_context *pipe, 21101e04c3fSmrg const struct pipe_rasterizer_state *rast) 21201e04c3fSmrg{ 21301e04c3fSmrg struct pipe_rasterizer_state *state; 21401e04c3fSmrg state = (pipe_rasterizer_state *)mem_dup(rast, sizeof *rast); 21501e04c3fSmrg 21601e04c3fSmrg return state; 21701e04c3fSmrg} 21801e04c3fSmrg 21901e04c3fSmrgstatic void 22001e04c3fSmrgswr_bind_rasterizer_state(struct pipe_context *pipe, void *handle) 22101e04c3fSmrg{ 22201e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 22301e04c3fSmrg const struct pipe_rasterizer_state *rasterizer = 22401e04c3fSmrg (const struct pipe_rasterizer_state *)handle; 22501e04c3fSmrg 22601e04c3fSmrg if (ctx->rasterizer == (pipe_rasterizer_state *)rasterizer) 22701e04c3fSmrg return; 22801e04c3fSmrg 22901e04c3fSmrg ctx->rasterizer = (pipe_rasterizer_state *)rasterizer; 23001e04c3fSmrg 23101e04c3fSmrg ctx->dirty |= SWR_NEW_RASTERIZER; 23201e04c3fSmrg} 23301e04c3fSmrg 23401e04c3fSmrgstatic void 23501e04c3fSmrgswr_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer) 23601e04c3fSmrg{ 23701e04c3fSmrg FREE(rasterizer); 23801e04c3fSmrg} 23901e04c3fSmrg 24001e04c3fSmrg 24101e04c3fSmrgstatic void * 24201e04c3fSmrgswr_create_sampler_state(struct pipe_context *pipe, 24301e04c3fSmrg const struct pipe_sampler_state *sampler) 24401e04c3fSmrg{ 24501e04c3fSmrg struct pipe_sampler_state *state = 24601e04c3fSmrg (pipe_sampler_state *)mem_dup(sampler, sizeof *sampler); 24701e04c3fSmrg 24801e04c3fSmrg return state; 24901e04c3fSmrg} 25001e04c3fSmrg 25101e04c3fSmrgstatic void 25201e04c3fSmrgswr_bind_sampler_states(struct pipe_context *pipe, 25301e04c3fSmrg enum pipe_shader_type shader, 25401e04c3fSmrg unsigned start, 25501e04c3fSmrg unsigned num, 25601e04c3fSmrg void **samplers) 25701e04c3fSmrg{ 25801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 25901e04c3fSmrg unsigned i; 26001e04c3fSmrg 26101e04c3fSmrg assert(shader < PIPE_SHADER_TYPES); 26201e04c3fSmrg assert(start + num <= ARRAY_SIZE(ctx->samplers[shader])); 26301e04c3fSmrg 26401e04c3fSmrg /* set the new samplers */ 26501e04c3fSmrg ctx->num_samplers[shader] = num; 26601e04c3fSmrg for (i = 0; i < num; i++) { 26701e04c3fSmrg ctx->samplers[shader][start + i] = (pipe_sampler_state *)samplers[i]; 26801e04c3fSmrg } 26901e04c3fSmrg 27001e04c3fSmrg ctx->dirty |= SWR_NEW_SAMPLER; 27101e04c3fSmrg} 27201e04c3fSmrg 27301e04c3fSmrgstatic void 27401e04c3fSmrgswr_delete_sampler_state(struct pipe_context *pipe, void *sampler) 27501e04c3fSmrg{ 27601e04c3fSmrg FREE(sampler); 27701e04c3fSmrg} 27801e04c3fSmrg 27901e04c3fSmrg 28001e04c3fSmrgstatic struct pipe_sampler_view * 28101e04c3fSmrgswr_create_sampler_view(struct pipe_context *pipe, 28201e04c3fSmrg struct pipe_resource *texture, 28301e04c3fSmrg const struct pipe_sampler_view *templ) 28401e04c3fSmrg{ 28501e04c3fSmrg struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); 28601e04c3fSmrg 28701e04c3fSmrg if (view) { 28801e04c3fSmrg *view = *templ; 28901e04c3fSmrg view->reference.count = 1; 29001e04c3fSmrg view->texture = NULL; 29101e04c3fSmrg pipe_resource_reference(&view->texture, texture); 29201e04c3fSmrg view->context = pipe; 29301e04c3fSmrg } 29401e04c3fSmrg 29501e04c3fSmrg return view; 29601e04c3fSmrg} 29701e04c3fSmrg 29801e04c3fSmrgstatic void 29901e04c3fSmrgswr_set_sampler_views(struct pipe_context *pipe, 30001e04c3fSmrg enum pipe_shader_type shader, 30101e04c3fSmrg unsigned start, 30201e04c3fSmrg unsigned num, 3037ec681f3Smrg unsigned unbind_num_trailing_slots, 3047ec681f3Smrg bool take_ownership, 30501e04c3fSmrg struct pipe_sampler_view **views) 30601e04c3fSmrg{ 30701e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 30801e04c3fSmrg uint i; 30901e04c3fSmrg 31001e04c3fSmrg assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); 31101e04c3fSmrg 31201e04c3fSmrg assert(shader < PIPE_SHADER_TYPES); 31301e04c3fSmrg assert(start + num <= ARRAY_SIZE(ctx->sampler_views[shader])); 31401e04c3fSmrg 31501e04c3fSmrg /* set the new sampler views */ 31601e04c3fSmrg ctx->num_sampler_views[shader] = num; 31701e04c3fSmrg for (i = 0; i < num; i++) { 3187ec681f3Smrg if (take_ownership) { 3197ec681f3Smrg pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i], 3207ec681f3Smrg NULL); 3217ec681f3Smrg ctx->sampler_views[shader][start + i] = views[i]; 3227ec681f3Smrg } else { 3237ec681f3Smrg pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i], 3247ec681f3Smrg views[i]); 3257ec681f3Smrg } 3267ec681f3Smrg } 3277ec681f3Smrg for (; i < num + unbind_num_trailing_slots; i++) { 32801e04c3fSmrg pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i], 3297ec681f3Smrg NULL); 33001e04c3fSmrg } 33101e04c3fSmrg 33201e04c3fSmrg ctx->dirty |= SWR_NEW_SAMPLER_VIEW; 33301e04c3fSmrg} 33401e04c3fSmrg 33501e04c3fSmrgstatic void 33601e04c3fSmrgswr_sampler_view_destroy(struct pipe_context *pipe, 33701e04c3fSmrg struct pipe_sampler_view *view) 33801e04c3fSmrg{ 33901e04c3fSmrg pipe_resource_reference(&view->texture, NULL); 34001e04c3fSmrg FREE(view); 34101e04c3fSmrg} 34201e04c3fSmrg 34301e04c3fSmrgstatic void * 34401e04c3fSmrgswr_create_vs_state(struct pipe_context *pipe, 34501e04c3fSmrg const struct pipe_shader_state *vs) 34601e04c3fSmrg{ 34701e04c3fSmrg struct swr_vertex_shader *swr_vs = new swr_vertex_shader; 34801e04c3fSmrg if (!swr_vs) 34901e04c3fSmrg return NULL; 35001e04c3fSmrg 35101e04c3fSmrg swr_vs->pipe.tokens = tgsi_dup_tokens(vs->tokens); 35201e04c3fSmrg swr_vs->pipe.stream_output = vs->stream_output; 35301e04c3fSmrg 35401e04c3fSmrg lp_build_tgsi_info(vs->tokens, &swr_vs->info); 35501e04c3fSmrg 35601e04c3fSmrg swr_vs->soState = {0}; 35701e04c3fSmrg 35801e04c3fSmrg if (swr_vs->pipe.stream_output.num_outputs) { 35901e04c3fSmrg pipe_stream_output_info *stream_output = &swr_vs->pipe.stream_output; 36001e04c3fSmrg 36101e04c3fSmrg swr_vs->soState.soEnable = true; 36201e04c3fSmrg // soState.rasterizerDisable set on state dirty 36301e04c3fSmrg // soState.streamToRasterizer not used 36401e04c3fSmrg 36501e04c3fSmrg for (uint32_t i = 0; i < stream_output->num_outputs; i++) { 36601e04c3fSmrg unsigned attrib_slot = stream_output->output[i].register_index; 36701e04c3fSmrg attrib_slot = swr_so_adjust_attrib(attrib_slot, swr_vs); 36801e04c3fSmrg swr_vs->soState.streamMasks[stream_output->output[i].stream] |= 36901e04c3fSmrg (1 << attrib_slot); 37001e04c3fSmrg } 37101e04c3fSmrg for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) { 37201e04c3fSmrg swr_vs->soState.streamNumEntries[i] = 37301e04c3fSmrg _mm_popcnt_u32(swr_vs->soState.streamMasks[i]); 37401e04c3fSmrg } 37501e04c3fSmrg } 37601e04c3fSmrg 37701e04c3fSmrg return swr_vs; 37801e04c3fSmrg} 37901e04c3fSmrg 38001e04c3fSmrgstatic void 38101e04c3fSmrgswr_bind_vs_state(struct pipe_context *pipe, void *vs) 38201e04c3fSmrg{ 38301e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 38401e04c3fSmrg 38501e04c3fSmrg if (ctx->vs == vs) 38601e04c3fSmrg return; 38701e04c3fSmrg 38801e04c3fSmrg ctx->vs = (swr_vertex_shader *)vs; 38901e04c3fSmrg ctx->dirty |= SWR_NEW_VS; 39001e04c3fSmrg} 39101e04c3fSmrg 39201e04c3fSmrgstatic void 39301e04c3fSmrgswr_delete_vs_state(struct pipe_context *pipe, void *vs) 39401e04c3fSmrg{ 39501e04c3fSmrg struct swr_vertex_shader *swr_vs = (swr_vertex_shader *)vs; 39601e04c3fSmrg FREE((void *)swr_vs->pipe.tokens); 39701e04c3fSmrg struct swr_screen *screen = swr_screen(pipe->screen); 39801e04c3fSmrg 39901e04c3fSmrg /* Defer deletion of vs state */ 40001e04c3fSmrg swr_fence_work_delete_vs(screen->flush_fence, swr_vs); 40101e04c3fSmrg} 40201e04c3fSmrg 40301e04c3fSmrgstatic void * 40401e04c3fSmrgswr_create_fs_state(struct pipe_context *pipe, 40501e04c3fSmrg const struct pipe_shader_state *fs) 40601e04c3fSmrg{ 40701e04c3fSmrg struct swr_fragment_shader *swr_fs = new swr_fragment_shader; 40801e04c3fSmrg if (!swr_fs) 40901e04c3fSmrg return NULL; 41001e04c3fSmrg 41101e04c3fSmrg swr_fs->pipe.tokens = tgsi_dup_tokens(fs->tokens); 41201e04c3fSmrg 41301e04c3fSmrg lp_build_tgsi_info(fs->tokens, &swr_fs->info); 41401e04c3fSmrg 41501e04c3fSmrg return swr_fs; 41601e04c3fSmrg} 41701e04c3fSmrg 41801e04c3fSmrg 41901e04c3fSmrgstatic void 42001e04c3fSmrgswr_bind_fs_state(struct pipe_context *pipe, void *fs) 42101e04c3fSmrg{ 42201e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 42301e04c3fSmrg 42401e04c3fSmrg if (ctx->fs == fs) 42501e04c3fSmrg return; 42601e04c3fSmrg 42701e04c3fSmrg ctx->fs = (swr_fragment_shader *)fs; 42801e04c3fSmrg ctx->dirty |= SWR_NEW_FS; 42901e04c3fSmrg} 43001e04c3fSmrg 43101e04c3fSmrgstatic void 43201e04c3fSmrgswr_delete_fs_state(struct pipe_context *pipe, void *fs) 43301e04c3fSmrg{ 43401e04c3fSmrg struct swr_fragment_shader *swr_fs = (swr_fragment_shader *)fs; 43501e04c3fSmrg FREE((void *)swr_fs->pipe.tokens); 43601e04c3fSmrg struct swr_screen *screen = swr_screen(pipe->screen); 43701e04c3fSmrg 43801e04c3fSmrg /* Defer deleton of fs state */ 43901e04c3fSmrg swr_fence_work_delete_fs(screen->flush_fence, swr_fs); 44001e04c3fSmrg} 44101e04c3fSmrg 44201e04c3fSmrgstatic void * 44301e04c3fSmrgswr_create_gs_state(struct pipe_context *pipe, 44401e04c3fSmrg const struct pipe_shader_state *gs) 44501e04c3fSmrg{ 44601e04c3fSmrg struct swr_geometry_shader *swr_gs = new swr_geometry_shader; 44701e04c3fSmrg if (!swr_gs) 44801e04c3fSmrg return NULL; 44901e04c3fSmrg 45001e04c3fSmrg swr_gs->pipe.tokens = tgsi_dup_tokens(gs->tokens); 45101e04c3fSmrg lp_build_tgsi_info(gs->tokens, &swr_gs->info); 45201e04c3fSmrg return swr_gs; 45301e04c3fSmrg} 45401e04c3fSmrg 45501e04c3fSmrgstatic void 45601e04c3fSmrgswr_bind_gs_state(struct pipe_context *pipe, void *gs) 45701e04c3fSmrg{ 45801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 45901e04c3fSmrg 46001e04c3fSmrg if (ctx->gs == gs) 46101e04c3fSmrg return; 46201e04c3fSmrg 46301e04c3fSmrg ctx->gs = (swr_geometry_shader *)gs; 46401e04c3fSmrg ctx->dirty |= SWR_NEW_GS; 46501e04c3fSmrg} 46601e04c3fSmrg 46701e04c3fSmrgstatic void 46801e04c3fSmrgswr_delete_gs_state(struct pipe_context *pipe, void *gs) 46901e04c3fSmrg{ 47001e04c3fSmrg struct swr_geometry_shader *swr_gs = (swr_geometry_shader *)gs; 47101e04c3fSmrg FREE((void *)swr_gs->pipe.tokens); 47201e04c3fSmrg struct swr_screen *screen = swr_screen(pipe->screen); 47301e04c3fSmrg 47401e04c3fSmrg /* Defer deleton of fs state */ 47501e04c3fSmrg swr_fence_work_delete_gs(screen->flush_fence, swr_gs); 47601e04c3fSmrg} 47701e04c3fSmrg 4787ec681f3Smrgstatic void * 4797ec681f3Smrgswr_create_tcs_state(struct pipe_context *pipe, 4807ec681f3Smrg const struct pipe_shader_state *tcs) 4817ec681f3Smrg{ 4827ec681f3Smrg struct swr_tess_control_shader *swr_tcs = new swr_tess_control_shader; 4837ec681f3Smrg if (!swr_tcs) 4847ec681f3Smrg return NULL; 4857ec681f3Smrg 4867ec681f3Smrg swr_tcs->pipe.tokens = tgsi_dup_tokens(tcs->tokens); 4877ec681f3Smrg lp_build_tgsi_info(tcs->tokens, &swr_tcs->info); 4887ec681f3Smrg return swr_tcs; 4897ec681f3Smrg} 4907ec681f3Smrg 4917ec681f3Smrgstatic void 4927ec681f3Smrgswr_bind_tcs_state(struct pipe_context *pipe, void *tcs) 4937ec681f3Smrg{ 4947ec681f3Smrg struct swr_context *ctx = swr_context(pipe); 4957ec681f3Smrg 4967ec681f3Smrg if (ctx->tcs == tcs) 4977ec681f3Smrg return; 4987ec681f3Smrg 4997ec681f3Smrg ctx->tcs = (swr_tess_control_shader *)tcs; 5007ec681f3Smrg ctx->dirty |= SWR_NEW_TCS; 5017ec681f3Smrg ctx->dirty |= SWR_NEW_TS; 5027ec681f3Smrg} 5037ec681f3Smrg 5047ec681f3Smrgstatic void 5057ec681f3Smrgswr_delete_tcs_state(struct pipe_context *pipe, void *tcs) 5067ec681f3Smrg{ 5077ec681f3Smrg struct swr_tess_control_shader *swr_tcs = (swr_tess_control_shader *)tcs; 5087ec681f3Smrg FREE((void *)swr_tcs->pipe.tokens); 5097ec681f3Smrg struct swr_screen *screen = swr_screen(pipe->screen); 5107ec681f3Smrg 5117ec681f3Smrg /* Defer deleton of tcs state */ 5127ec681f3Smrg swr_fence_work_delete_tcs(screen->flush_fence, swr_tcs); 5137ec681f3Smrg} 5147ec681f3Smrg 5157ec681f3Smrgstatic void * 5167ec681f3Smrgswr_create_tes_state(struct pipe_context *pipe, 5177ec681f3Smrg const struct pipe_shader_state *tes) 5187ec681f3Smrg{ 5197ec681f3Smrg struct swr_tess_evaluation_shader *swr_tes = new swr_tess_evaluation_shader; 5207ec681f3Smrg if (!swr_tes) 5217ec681f3Smrg return NULL; 5227ec681f3Smrg 5237ec681f3Smrg swr_tes->pipe.tokens = tgsi_dup_tokens(tes->tokens); 5247ec681f3Smrg lp_build_tgsi_info(tes->tokens, &swr_tes->info); 5257ec681f3Smrg return swr_tes; 5267ec681f3Smrg} 5277ec681f3Smrg 5287ec681f3Smrgstatic void 5297ec681f3Smrgswr_bind_tes_state(struct pipe_context *pipe, void *tes) 5307ec681f3Smrg{ 5317ec681f3Smrg struct swr_context *ctx = swr_context(pipe); 5327ec681f3Smrg 5337ec681f3Smrg if (ctx->tes == tes) 5347ec681f3Smrg return; 5357ec681f3Smrg 5367ec681f3Smrg // Save current tessellator state first 5377ec681f3Smrg if (ctx->tes != nullptr) { 5387ec681f3Smrg ctx->tes->ts_state = ctx->tsState; 5397ec681f3Smrg } 5407ec681f3Smrg 5417ec681f3Smrg ctx->tes = (swr_tess_evaluation_shader *)tes; 5427ec681f3Smrg 5437ec681f3Smrg ctx->dirty |= SWR_NEW_TES; 5447ec681f3Smrg ctx->dirty |= SWR_NEW_TS; 5457ec681f3Smrg} 5467ec681f3Smrg 5477ec681f3Smrgstatic void 5487ec681f3Smrgswr_delete_tes_state(struct pipe_context *pipe, void *tes) 5497ec681f3Smrg{ 5507ec681f3Smrg struct swr_tess_evaluation_shader *swr_tes = (swr_tess_evaluation_shader *)tes; 5517ec681f3Smrg FREE((void *)swr_tes->pipe.tokens); 5527ec681f3Smrg struct swr_screen *screen = swr_screen(pipe->screen); 5537ec681f3Smrg 5547ec681f3Smrg /* Defer deleton of tes state */ 5557ec681f3Smrg swr_fence_work_delete_tes(screen->flush_fence, swr_tes); 5567ec681f3Smrg} 5577ec681f3Smrg 55801e04c3fSmrgstatic void 55901e04c3fSmrgswr_set_constant_buffer(struct pipe_context *pipe, 56001e04c3fSmrg enum pipe_shader_type shader, 5617ec681f3Smrg uint index, bool take_ownership, 56201e04c3fSmrg const struct pipe_constant_buffer *cb) 56301e04c3fSmrg{ 56401e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 56501e04c3fSmrg struct pipe_resource *constants = cb ? cb->buffer : NULL; 56601e04c3fSmrg 56701e04c3fSmrg assert(shader < PIPE_SHADER_TYPES); 56801e04c3fSmrg assert(index < ARRAY_SIZE(ctx->constants[shader])); 56901e04c3fSmrg 57001e04c3fSmrg /* note: reference counting */ 5717ec681f3Smrg util_copy_constant_buffer(&ctx->constants[shader][index], cb, take_ownership); 57201e04c3fSmrg 57301e04c3fSmrg if (shader == PIPE_SHADER_VERTEX) { 57401e04c3fSmrg ctx->dirty |= SWR_NEW_VSCONSTANTS; 57501e04c3fSmrg } else if (shader == PIPE_SHADER_FRAGMENT) { 57601e04c3fSmrg ctx->dirty |= SWR_NEW_FSCONSTANTS; 57701e04c3fSmrg } else if (shader == PIPE_SHADER_GEOMETRY) { 57801e04c3fSmrg ctx->dirty |= SWR_NEW_GSCONSTANTS; 5797ec681f3Smrg } else if (shader == PIPE_SHADER_TESS_CTRL) { 5807ec681f3Smrg ctx->dirty |= SWR_NEW_TCSCONSTANTS; 5817ec681f3Smrg } else if (shader == PIPE_SHADER_TESS_EVAL) { 5827ec681f3Smrg ctx->dirty |= SWR_NEW_TESCONSTANTS; 58301e04c3fSmrg } 58401e04c3fSmrg if (cb && cb->user_buffer) { 58501e04c3fSmrg pipe_resource_reference(&constants, NULL); 58601e04c3fSmrg } 58701e04c3fSmrg} 58801e04c3fSmrg 58901e04c3fSmrg 59001e04c3fSmrgstatic void * 59101e04c3fSmrgswr_create_vertex_elements_state(struct pipe_context *pipe, 59201e04c3fSmrg unsigned num_elements, 59301e04c3fSmrg const struct pipe_vertex_element *attribs) 59401e04c3fSmrg{ 59501e04c3fSmrg struct swr_vertex_element_state *velems; 59601e04c3fSmrg assert(num_elements <= PIPE_MAX_ATTRIBS); 59701e04c3fSmrg velems = new swr_vertex_element_state; 59801e04c3fSmrg if (velems) { 5997ec681f3Smrg memset((void*)&velems->fsState, 0, sizeof(velems->fsState)); 60001e04c3fSmrg velems->fsState.bVertexIDOffsetEnable = true; 60101e04c3fSmrg velems->fsState.numAttribs = num_elements; 60201e04c3fSmrg for (unsigned i = 0; i < num_elements; i++) { 60301e04c3fSmrg // XXX: we should do this keyed on the VS usage info 60401e04c3fSmrg 60501e04c3fSmrg const struct util_format_description *desc = 6067ec681f3Smrg util_format_description((enum pipe_format)attribs[i].src_format); 60701e04c3fSmrg 60801e04c3fSmrg velems->fsState.layout[i].AlignedByteOffset = attribs[i].src_offset; 60901e04c3fSmrg velems->fsState.layout[i].Format = 6107ec681f3Smrg mesa_to_swr_format((enum pipe_format)attribs[i].src_format); 61101e04c3fSmrg velems->fsState.layout[i].StreamIndex = 61201e04c3fSmrg attribs[i].vertex_buffer_index; 61301e04c3fSmrg velems->fsState.layout[i].InstanceEnable = 61401e04c3fSmrg attribs[i].instance_divisor != 0; 61501e04c3fSmrg velems->fsState.layout[i].ComponentControl0 = 61601e04c3fSmrg desc->channel[0].type != UTIL_FORMAT_TYPE_VOID 61701e04c3fSmrg ? ComponentControl::StoreSrc 61801e04c3fSmrg : ComponentControl::Store0; 61901e04c3fSmrg velems->fsState.layout[i].ComponentControl1 = 62001e04c3fSmrg desc->channel[1].type != UTIL_FORMAT_TYPE_VOID 62101e04c3fSmrg ? ComponentControl::StoreSrc 62201e04c3fSmrg : ComponentControl::Store0; 62301e04c3fSmrg velems->fsState.layout[i].ComponentControl2 = 62401e04c3fSmrg desc->channel[2].type != UTIL_FORMAT_TYPE_VOID 62501e04c3fSmrg ? ComponentControl::StoreSrc 62601e04c3fSmrg : ComponentControl::Store0; 62701e04c3fSmrg velems->fsState.layout[i].ComponentControl3 = 62801e04c3fSmrg desc->channel[3].type != UTIL_FORMAT_TYPE_VOID 62901e04c3fSmrg ? ComponentControl::StoreSrc 63001e04c3fSmrg : ComponentControl::Store1Fp; 63101e04c3fSmrg velems->fsState.layout[i].ComponentPacking = ComponentEnable::XYZW; 63201e04c3fSmrg velems->fsState.layout[i].InstanceAdvancementState = 63301e04c3fSmrg attribs[i].instance_divisor; 63401e04c3fSmrg 63501e04c3fSmrg /* Calculate the pitch of each stream */ 63601e04c3fSmrg const SWR_FORMAT_INFO &swr_desc = GetFormatInfo( 6377ec681f3Smrg mesa_to_swr_format((enum pipe_format)attribs[i].src_format)); 63801e04c3fSmrg velems->stream_pitch[attribs[i].vertex_buffer_index] += swr_desc.Bpp; 63901e04c3fSmrg 64001e04c3fSmrg if (attribs[i].instance_divisor != 0) { 64101e04c3fSmrg velems->instanced_bufs |= 1U << attribs[i].vertex_buffer_index; 64201e04c3fSmrg uint32_t *min_instance_div = 64301e04c3fSmrg &velems->min_instance_div[attribs[i].vertex_buffer_index]; 64401e04c3fSmrg if (!*min_instance_div || 64501e04c3fSmrg attribs[i].instance_divisor < *min_instance_div) 64601e04c3fSmrg *min_instance_div = attribs[i].instance_divisor; 64701e04c3fSmrg } 64801e04c3fSmrg } 64901e04c3fSmrg } 65001e04c3fSmrg 65101e04c3fSmrg return velems; 65201e04c3fSmrg} 65301e04c3fSmrg 65401e04c3fSmrgstatic void 65501e04c3fSmrgswr_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) 65601e04c3fSmrg{ 65701e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 65801e04c3fSmrg struct swr_vertex_element_state *swr_velems = 65901e04c3fSmrg (struct swr_vertex_element_state *)velems; 66001e04c3fSmrg 66101e04c3fSmrg ctx->velems = swr_velems; 66201e04c3fSmrg ctx->dirty |= SWR_NEW_VERTEX; 66301e04c3fSmrg} 66401e04c3fSmrg 66501e04c3fSmrgstatic void 66601e04c3fSmrgswr_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) 66701e04c3fSmrg{ 66801e04c3fSmrg struct swr_vertex_element_state *swr_velems = 66901e04c3fSmrg (struct swr_vertex_element_state *) velems; 67001e04c3fSmrg /* XXX Need to destroy fetch shader? */ 67101e04c3fSmrg delete swr_velems; 67201e04c3fSmrg} 67301e04c3fSmrg 67401e04c3fSmrg 67501e04c3fSmrgstatic void 67601e04c3fSmrgswr_set_vertex_buffers(struct pipe_context *pipe, 67701e04c3fSmrg unsigned start_slot, 67801e04c3fSmrg unsigned num_elements, 6797ec681f3Smrg unsigned unbind_num_trailing_slots, 6807ec681f3Smrg bool take_ownership, 68101e04c3fSmrg const struct pipe_vertex_buffer *buffers) 68201e04c3fSmrg{ 68301e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 68401e04c3fSmrg 68501e04c3fSmrg assert(num_elements <= PIPE_MAX_ATTRIBS); 68601e04c3fSmrg 68701e04c3fSmrg util_set_vertex_buffers_count(ctx->vertex_buffer, 68801e04c3fSmrg &ctx->num_vertex_buffers, 68901e04c3fSmrg buffers, 69001e04c3fSmrg start_slot, 6917ec681f3Smrg num_elements, 6927ec681f3Smrg unbind_num_trailing_slots, 6937ec681f3Smrg take_ownership); 69401e04c3fSmrg 69501e04c3fSmrg ctx->dirty |= SWR_NEW_VERTEX; 69601e04c3fSmrg} 69701e04c3fSmrg 69801e04c3fSmrg 69901e04c3fSmrgstatic void 70001e04c3fSmrgswr_set_polygon_stipple(struct pipe_context *pipe, 70101e04c3fSmrg const struct pipe_poly_stipple *stipple) 70201e04c3fSmrg{ 70301e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 70401e04c3fSmrg 70501e04c3fSmrg ctx->poly_stipple.pipe = *stipple; /* struct copy */ 70601e04c3fSmrg ctx->dirty |= SWR_NEW_STIPPLE; 70701e04c3fSmrg} 70801e04c3fSmrg 70901e04c3fSmrgstatic void 71001e04c3fSmrgswr_set_clip_state(struct pipe_context *pipe, 71101e04c3fSmrg const struct pipe_clip_state *clip) 71201e04c3fSmrg{ 71301e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 71401e04c3fSmrg 71501e04c3fSmrg ctx->clip = *clip; 71601e04c3fSmrg /* XXX Unimplemented, but prevents crash */ 71701e04c3fSmrg 71801e04c3fSmrg ctx->dirty |= SWR_NEW_CLIP; 71901e04c3fSmrg} 72001e04c3fSmrg 72101e04c3fSmrg 72201e04c3fSmrgstatic void 72301e04c3fSmrgswr_set_scissor_states(struct pipe_context *pipe, 72401e04c3fSmrg unsigned start_slot, 7257ec681f3Smrg unsigned num_scissors, 7267ec681f3Smrg const struct pipe_scissor_state *scissors) 72701e04c3fSmrg{ 72801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 72901e04c3fSmrg 7307ec681f3Smrg memcpy(ctx->scissors + start_slot, scissors, 7317ec681f3Smrg sizeof(struct pipe_scissor_state) * num_scissors); 7327ec681f3Smrg 7337ec681f3Smrg for (unsigned i = 0; i < num_scissors; i++) { 7347ec681f3Smrg auto idx = start_slot + i; 7357ec681f3Smrg ctx->swr_scissors[idx].xmin = scissors[idx].minx; 7367ec681f3Smrg ctx->swr_scissors[idx].xmax = scissors[idx].maxx; 7377ec681f3Smrg ctx->swr_scissors[idx].ymin = scissors[idx].miny; 7387ec681f3Smrg ctx->swr_scissors[idx].ymax = scissors[idx].maxy; 7397ec681f3Smrg } 74001e04c3fSmrg ctx->dirty |= SWR_NEW_SCISSOR; 74101e04c3fSmrg} 74201e04c3fSmrg 74301e04c3fSmrgstatic void 74401e04c3fSmrgswr_set_viewport_states(struct pipe_context *pipe, 74501e04c3fSmrg unsigned start_slot, 74601e04c3fSmrg unsigned num_viewports, 74701e04c3fSmrg const struct pipe_viewport_state *vpt) 74801e04c3fSmrg{ 74901e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 75001e04c3fSmrg 7517ec681f3Smrg memcpy(ctx->viewports + start_slot, vpt, sizeof(struct pipe_viewport_state) * num_viewports); 75201e04c3fSmrg ctx->dirty |= SWR_NEW_VIEWPORT; 75301e04c3fSmrg} 75401e04c3fSmrg 75501e04c3fSmrg 75601e04c3fSmrgstatic void 75701e04c3fSmrgswr_set_framebuffer_state(struct pipe_context *pipe, 75801e04c3fSmrg const struct pipe_framebuffer_state *fb) 75901e04c3fSmrg{ 76001e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 76101e04c3fSmrg 7627ec681f3Smrg bool changed = !util_framebuffer_state_equal(&ctx->framebuffer, fb); 76301e04c3fSmrg 76401e04c3fSmrg assert(fb->width <= KNOB_GUARDBAND_WIDTH); 76501e04c3fSmrg assert(fb->height <= KNOB_GUARDBAND_HEIGHT); 76601e04c3fSmrg 76701e04c3fSmrg if (changed) { 76801e04c3fSmrg util_copy_framebuffer_state(&ctx->framebuffer, fb); 76901e04c3fSmrg 77001e04c3fSmrg /* 0 and 1 both indicate no msaa. Core doesn't understand 0 samples */ 77101e04c3fSmrg ctx->framebuffer.samples = std::max((ubyte)1, ctx->framebuffer.samples); 77201e04c3fSmrg 77301e04c3fSmrg ctx->dirty |= SWR_NEW_FRAMEBUFFER; 77401e04c3fSmrg } 77501e04c3fSmrg} 77601e04c3fSmrg 77701e04c3fSmrg 77801e04c3fSmrgstatic void 77901e04c3fSmrgswr_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) 78001e04c3fSmrg{ 78101e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 78201e04c3fSmrg 78301e04c3fSmrg if (sample_mask != ctx->sample_mask) { 78401e04c3fSmrg ctx->sample_mask = sample_mask; 78501e04c3fSmrg ctx->dirty |= SWR_NEW_RASTERIZER; 78601e04c3fSmrg } 78701e04c3fSmrg} 78801e04c3fSmrg 78901e04c3fSmrg/* 79001e04c3fSmrg * MSAA fixed sample position table 79101e04c3fSmrg * used by update_derived and get_sample_position 79201e04c3fSmrg * (integer locations on a 16x16 grid) 79301e04c3fSmrg */ 79401e04c3fSmrgstatic const uint8_t swr_sample_positions[][2] = 79501e04c3fSmrg{ /* 1x*/ { 8, 8}, 79601e04c3fSmrg /* 2x*/ {12,12},{ 4, 4}, 79701e04c3fSmrg /* 4x*/ { 6, 2},{14, 6},{ 2,10},{10,14}, 79801e04c3fSmrg /* 8x*/ { 9, 5},{ 7,11},{13, 9},{ 5, 3}, 79901e04c3fSmrg { 3,13},{ 1, 7},{11,15},{15, 1}, 80001e04c3fSmrg /*16x*/ { 9, 9},{ 7, 5},{ 5,10},{12, 7}, 80101e04c3fSmrg { 3, 6},{10,13},{13,11},{11, 3}, 80201e04c3fSmrg { 6,14},{ 8, 1},{ 4, 2},{ 2,12}, 80301e04c3fSmrg { 0, 8},{15, 4},{14,15},{ 1, 0} }; 80401e04c3fSmrg 80501e04c3fSmrgstatic void 80601e04c3fSmrgswr_get_sample_position(struct pipe_context *pipe, 80701e04c3fSmrg unsigned sample_count, unsigned sample_index, 80801e04c3fSmrg float *out_value) 80901e04c3fSmrg{ 81001e04c3fSmrg /* validate sample_count */ 81101e04c3fSmrg sample_count = GetNumSamples(GetSampleCount(sample_count)); 81201e04c3fSmrg 81301e04c3fSmrg const uint8_t *sample = swr_sample_positions[sample_count-1 + sample_index]; 81401e04c3fSmrg out_value[0] = sample[0] / 16.0f; 81501e04c3fSmrg out_value[1] = sample[1] / 16.0f; 81601e04c3fSmrg} 81701e04c3fSmrg 81801e04c3fSmrg 81901e04c3fSmrg/* 82001e04c3fSmrg * Update resource in-use status 82101e04c3fSmrg * All resources bound to color or depth targets marked as WRITE resources. 82201e04c3fSmrg * VBO Vertex/index buffers and texture views marked as READ resources. 82301e04c3fSmrg */ 82401e04c3fSmrgvoid 82501e04c3fSmrgswr_update_resource_status(struct pipe_context *pipe, 82601e04c3fSmrg const struct pipe_draw_info *p_draw_info) 82701e04c3fSmrg{ 82801e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 82901e04c3fSmrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 83001e04c3fSmrg 83101e04c3fSmrg /* colorbuffer targets */ 83201e04c3fSmrg if (fb->nr_cbufs) 83301e04c3fSmrg for (uint32_t i = 0; i < fb->nr_cbufs; ++i) 83401e04c3fSmrg if (fb->cbufs[i]) 83501e04c3fSmrg swr_resource_write(fb->cbufs[i]->texture); 83601e04c3fSmrg 83701e04c3fSmrg /* depth/stencil target */ 83801e04c3fSmrg if (fb->zsbuf) 83901e04c3fSmrg swr_resource_write(fb->zsbuf->texture); 84001e04c3fSmrg 84101e04c3fSmrg /* VBO vertex buffers */ 84201e04c3fSmrg for (uint32_t i = 0; i < ctx->num_vertex_buffers; i++) { 84301e04c3fSmrg struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; 8449f464c52Smaya if (!vb->is_user_buffer && vb->buffer.resource) 84501e04c3fSmrg swr_resource_read(vb->buffer.resource); 84601e04c3fSmrg } 84701e04c3fSmrg 84801e04c3fSmrg /* VBO index buffer */ 84901e04c3fSmrg if (p_draw_info && p_draw_info->index_size) { 85001e04c3fSmrg if (!p_draw_info->has_user_indices) 85101e04c3fSmrg swr_resource_read(p_draw_info->index.resource); 85201e04c3fSmrg } 85301e04c3fSmrg 85401e04c3fSmrg /* transform feedback buffers */ 85501e04c3fSmrg for (uint32_t i = 0; i < ctx->num_so_targets; i++) { 85601e04c3fSmrg struct pipe_stream_output_target *target = ctx->so_targets[i]; 85701e04c3fSmrg if (target && target->buffer) 85801e04c3fSmrg swr_resource_write(target->buffer); 85901e04c3fSmrg } 86001e04c3fSmrg 86101e04c3fSmrg /* texture sampler views */ 86201e04c3fSmrg for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) { 86301e04c3fSmrg for (uint32_t i = 0; i < ctx->num_sampler_views[j]; i++) { 86401e04c3fSmrg struct pipe_sampler_view *view = ctx->sampler_views[j][i]; 86501e04c3fSmrg if (view) 86601e04c3fSmrg swr_resource_read(view->texture); 86701e04c3fSmrg } 86801e04c3fSmrg } 86901e04c3fSmrg 87001e04c3fSmrg /* constant buffers */ 87101e04c3fSmrg for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) { 87201e04c3fSmrg for (uint32_t i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 87301e04c3fSmrg struct pipe_constant_buffer *cb = &ctx->constants[j][i]; 87401e04c3fSmrg if (cb->buffer) 87501e04c3fSmrg swr_resource_read(cb->buffer); 87601e04c3fSmrg } 87701e04c3fSmrg } 87801e04c3fSmrg} 87901e04c3fSmrg 88001e04c3fSmrgstatic void 88101e04c3fSmrgswr_update_texture_state(struct swr_context *ctx, 88201e04c3fSmrg enum pipe_shader_type shader_type, 88301e04c3fSmrg unsigned num_sampler_views, 88401e04c3fSmrg swr_jit_texture *textures) 88501e04c3fSmrg{ 88601e04c3fSmrg for (unsigned i = 0; i < num_sampler_views; i++) { 88701e04c3fSmrg struct pipe_sampler_view *view = 88801e04c3fSmrg ctx->sampler_views[shader_type][i]; 88901e04c3fSmrg struct swr_jit_texture *jit_tex = &textures[i]; 89001e04c3fSmrg 89101e04c3fSmrg memset(jit_tex, 0, sizeof(*jit_tex)); 89201e04c3fSmrg if (view) { 89301e04c3fSmrg struct pipe_resource *res = view->texture; 89401e04c3fSmrg struct swr_resource *swr_res = swr_resource(res); 89501e04c3fSmrg SWR_SURFACE_STATE *swr = &swr_res->swr; 89601e04c3fSmrg size_t *mip_offsets = swr_res->mip_offsets; 89701e04c3fSmrg if (swr_res->has_depth && swr_res->has_stencil && 89801e04c3fSmrg !util_format_has_depth(util_format_description(view->format))) { 89901e04c3fSmrg swr = &swr_res->secondary; 90001e04c3fSmrg mip_offsets = swr_res->secondary_mip_offsets; 90101e04c3fSmrg } 90201e04c3fSmrg 90301e04c3fSmrg jit_tex->width = res->width0; 90401e04c3fSmrg jit_tex->height = res->height0; 90501e04c3fSmrg jit_tex->base_ptr = (uint8_t*)swr->xpBaseAddress; 9067ec681f3Smrg jit_tex->num_samples = swr->numSamples; 9077ec681f3Smrg jit_tex->sample_stride = 0; 90801e04c3fSmrg if (view->target != PIPE_BUFFER) { 90901e04c3fSmrg jit_tex->first_level = view->u.tex.first_level; 91001e04c3fSmrg jit_tex->last_level = view->u.tex.last_level; 91101e04c3fSmrg if (view->target == PIPE_TEXTURE_3D) 91201e04c3fSmrg jit_tex->depth = res->depth0; 91301e04c3fSmrg else 91401e04c3fSmrg jit_tex->depth = 91501e04c3fSmrg view->u.tex.last_layer - view->u.tex.first_layer + 1; 91601e04c3fSmrg jit_tex->base_ptr += view->u.tex.first_layer * 91701e04c3fSmrg swr->qpitch * swr->pitch; 91801e04c3fSmrg } else { 91901e04c3fSmrg unsigned view_blocksize = util_format_get_blocksize(view->format); 92001e04c3fSmrg jit_tex->base_ptr += view->u.buf.offset; 92101e04c3fSmrg jit_tex->width = view->u.buf.size / view_blocksize; 92201e04c3fSmrg jit_tex->depth = 1; 92301e04c3fSmrg } 92401e04c3fSmrg 92501e04c3fSmrg for (unsigned level = jit_tex->first_level; 92601e04c3fSmrg level <= jit_tex->last_level; 92701e04c3fSmrg level++) { 92801e04c3fSmrg jit_tex->row_stride[level] = swr->pitch; 92901e04c3fSmrg jit_tex->img_stride[level] = swr->qpitch * swr->pitch; 93001e04c3fSmrg jit_tex->mip_offsets[level] = mip_offsets[level]; 93101e04c3fSmrg } 93201e04c3fSmrg } 93301e04c3fSmrg } 93401e04c3fSmrg} 93501e04c3fSmrg 93601e04c3fSmrgstatic void 93701e04c3fSmrgswr_update_sampler_state(struct swr_context *ctx, 93801e04c3fSmrg enum pipe_shader_type shader_type, 93901e04c3fSmrg unsigned num_samplers, 94001e04c3fSmrg swr_jit_sampler *samplers) 94101e04c3fSmrg{ 94201e04c3fSmrg for (unsigned i = 0; i < num_samplers; i++) { 94301e04c3fSmrg const struct pipe_sampler_state *sampler = 94401e04c3fSmrg ctx->samplers[shader_type][i]; 94501e04c3fSmrg 94601e04c3fSmrg if (sampler) { 94701e04c3fSmrg samplers[i].min_lod = sampler->min_lod; 94801e04c3fSmrg samplers[i].max_lod = sampler->max_lod; 94901e04c3fSmrg samplers[i].lod_bias = sampler->lod_bias; 95001e04c3fSmrg COPY_4V(samplers[i].border_color, sampler->border_color.f); 95101e04c3fSmrg } 95201e04c3fSmrg } 95301e04c3fSmrg} 95401e04c3fSmrg 95501e04c3fSmrgstatic void 95601e04c3fSmrgswr_update_constants(struct swr_context *ctx, enum pipe_shader_type shaderType) 95701e04c3fSmrg{ 95801e04c3fSmrg swr_draw_context *pDC = &ctx->swrDC; 95901e04c3fSmrg 96001e04c3fSmrg const float **constant; 96101e04c3fSmrg uint32_t *num_constants; 96201e04c3fSmrg struct swr_scratch_space *scratch; 96301e04c3fSmrg 96401e04c3fSmrg switch (shaderType) { 96501e04c3fSmrg case PIPE_SHADER_VERTEX: 96601e04c3fSmrg constant = pDC->constantVS; 96701e04c3fSmrg num_constants = pDC->num_constantsVS; 96801e04c3fSmrg scratch = &ctx->scratch->vs_constants; 96901e04c3fSmrg break; 97001e04c3fSmrg case PIPE_SHADER_FRAGMENT: 97101e04c3fSmrg constant = pDC->constantFS; 97201e04c3fSmrg num_constants = pDC->num_constantsFS; 97301e04c3fSmrg scratch = &ctx->scratch->fs_constants; 97401e04c3fSmrg break; 97501e04c3fSmrg case PIPE_SHADER_GEOMETRY: 97601e04c3fSmrg constant = pDC->constantGS; 97701e04c3fSmrg num_constants = pDC->num_constantsGS; 97801e04c3fSmrg scratch = &ctx->scratch->gs_constants; 97901e04c3fSmrg break; 9807ec681f3Smrg case PIPE_SHADER_TESS_CTRL: 9817ec681f3Smrg constant = pDC->constantTCS; 9827ec681f3Smrg num_constants = pDC->num_constantsTCS; 9837ec681f3Smrg scratch = &ctx->scratch->tcs_constants; 9847ec681f3Smrg break; 9857ec681f3Smrg case PIPE_SHADER_TESS_EVAL: 9867ec681f3Smrg constant = pDC->constantTES; 9877ec681f3Smrg num_constants = pDC->num_constantsTES; 9887ec681f3Smrg scratch = &ctx->scratch->tes_constants; 9897ec681f3Smrg break; 99001e04c3fSmrg default: 9917ec681f3Smrg assert(0 && "Unsupported shader type constants"); 99201e04c3fSmrg return; 99301e04c3fSmrg } 99401e04c3fSmrg 99501e04c3fSmrg for (UINT i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 99601e04c3fSmrg const pipe_constant_buffer *cb = &ctx->constants[shaderType][i]; 99701e04c3fSmrg num_constants[i] = cb->buffer_size; 99801e04c3fSmrg if (cb->buffer) { 99901e04c3fSmrg constant[i] = 100001e04c3fSmrg (const float *)(swr_resource_data(cb->buffer) + 100101e04c3fSmrg cb->buffer_offset); 100201e04c3fSmrg } else { 100301e04c3fSmrg /* Need to copy these constants to scratch space */ 100401e04c3fSmrg if (cb->user_buffer && cb->buffer_size) { 100501e04c3fSmrg const void *ptr = 100601e04c3fSmrg ((const uint8_t *)cb->user_buffer + cb->buffer_offset); 100701e04c3fSmrg uint32_t size = AlignUp(cb->buffer_size, 4); 100801e04c3fSmrg ptr = swr_copy_to_scratch_space(ctx, scratch, ptr, size); 100901e04c3fSmrg constant[i] = (const float *)ptr; 101001e04c3fSmrg } 101101e04c3fSmrg } 101201e04c3fSmrg } 101301e04c3fSmrg} 101401e04c3fSmrg 101501e04c3fSmrgstatic bool 101601e04c3fSmrgswr_change_rt(struct swr_context *ctx, 101701e04c3fSmrg unsigned attachment, 101801e04c3fSmrg const struct pipe_surface *sf) 101901e04c3fSmrg{ 102001e04c3fSmrg swr_draw_context *pDC = &ctx->swrDC; 102101e04c3fSmrg struct SWR_SURFACE_STATE *rt = &pDC->renderTargets[attachment]; 102201e04c3fSmrg 102301e04c3fSmrg /* Do nothing if the render target hasn't changed */ 102401e04c3fSmrg if ((!sf || !sf->texture) && (void*)(rt->xpBaseAddress) == nullptr) 102501e04c3fSmrg return false; 102601e04c3fSmrg 102701e04c3fSmrg /* Deal with disabling RT up front */ 102801e04c3fSmrg if (!sf || !sf->texture) { 102901e04c3fSmrg /* If detaching attachment, mark tiles as RESOLVED so core 103001e04c3fSmrg * won't try to load from non-existent target. */ 103101e04c3fSmrg swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_RESOLVED); 103201e04c3fSmrg *rt = {0}; 103301e04c3fSmrg return true; 103401e04c3fSmrg } 103501e04c3fSmrg 103601e04c3fSmrg const struct swr_resource *swr = swr_resource(sf->texture); 103701e04c3fSmrg const SWR_SURFACE_STATE *swr_surface = &swr->swr; 103801e04c3fSmrg SWR_FORMAT fmt = mesa_to_swr_format(sf->format); 103901e04c3fSmrg 104001e04c3fSmrg if (attachment == SWR_ATTACHMENT_STENCIL && swr->secondary.xpBaseAddress) { 104101e04c3fSmrg swr_surface = &swr->secondary; 104201e04c3fSmrg fmt = swr_surface->format; 104301e04c3fSmrg } 104401e04c3fSmrg 104501e04c3fSmrg if (rt->xpBaseAddress == swr_surface->xpBaseAddress && 104601e04c3fSmrg rt->format == fmt && 104701e04c3fSmrg rt->lod == sf->u.tex.level && 104801e04c3fSmrg rt->arrayIndex == sf->u.tex.first_layer) 104901e04c3fSmrg return false; 105001e04c3fSmrg 105101e04c3fSmrg bool need_fence = false; 105201e04c3fSmrg 105301e04c3fSmrg /* StoreTile for changed target */ 105401e04c3fSmrg if (rt->xpBaseAddress) { 105501e04c3fSmrg /* If changing attachment to a new target, mark tiles as 105601e04c3fSmrg * INVALID so they are reloaded from surface. */ 105701e04c3fSmrg swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_INVALID); 105801e04c3fSmrg need_fence = true; 105901e04c3fSmrg } else { 106001e04c3fSmrg /* if no previous attachment, invalidate tiles that may be marked 106101e04c3fSmrg * RESOLVED because of an old attachment */ 106201e04c3fSmrg swr_invalidate_render_target(&ctx->pipe, attachment, sf->width, sf->height); 106301e04c3fSmrg /* no need to set fence here */ 106401e04c3fSmrg } 106501e04c3fSmrg 106601e04c3fSmrg /* Make new attachment */ 106701e04c3fSmrg *rt = *swr_surface; 106801e04c3fSmrg rt->format = fmt; 106901e04c3fSmrg rt->lod = sf->u.tex.level; 107001e04c3fSmrg rt->arrayIndex = sf->u.tex.first_layer; 107101e04c3fSmrg 107201e04c3fSmrg return need_fence; 107301e04c3fSmrg} 107401e04c3fSmrg 107501e04c3fSmrg/* 107601e04c3fSmrg * for cases where resources are shared between contexts, invalidate 107701e04c3fSmrg * this ctx's resource. so it can be fetched fresh. Old ctx's resource 107801e04c3fSmrg * is already stored during a flush 107901e04c3fSmrg */ 108001e04c3fSmrgstatic inline void 108101e04c3fSmrgswr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe) 108201e04c3fSmrg{ 108301e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 108401e04c3fSmrg 108501e04c3fSmrg for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) { 108601e04c3fSmrg struct pipe_surface *cb = ctx->framebuffer.cbufs[i]; 108701e04c3fSmrg if (cb) { 108801e04c3fSmrg struct swr_resource *res = swr_resource(cb->texture); 108901e04c3fSmrg if (res->curr_pipe != pipe) { 109001e04c3fSmrg /* if curr_pipe is NULL (first use), status should not be WRITE */ 109101e04c3fSmrg assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); 109201e04c3fSmrg if (res->status & SWR_RESOURCE_WRITE) { 109301e04c3fSmrg swr_invalidate_render_target(pipe, i, cb->width, cb->height); 109401e04c3fSmrg } 109501e04c3fSmrg } 109601e04c3fSmrg res->curr_pipe = pipe; 109701e04c3fSmrg } 109801e04c3fSmrg } 109901e04c3fSmrg if (ctx->framebuffer.zsbuf) { 110001e04c3fSmrg struct pipe_surface *zb = ctx->framebuffer.zsbuf; 110101e04c3fSmrg if (zb) { 110201e04c3fSmrg struct swr_resource *res = swr_resource(zb->texture); 110301e04c3fSmrg if (res->curr_pipe != pipe) { 110401e04c3fSmrg /* if curr_pipe is NULL (first use), status should not be WRITE */ 110501e04c3fSmrg assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); 110601e04c3fSmrg if (res->status & SWR_RESOURCE_WRITE) { 110701e04c3fSmrg swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height); 110801e04c3fSmrg swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height); 110901e04c3fSmrg } 111001e04c3fSmrg } 111101e04c3fSmrg res->curr_pipe = pipe; 111201e04c3fSmrg } 111301e04c3fSmrg } 111401e04c3fSmrg} 111501e04c3fSmrg 111601e04c3fSmrgstatic inline void 111701e04c3fSmrgswr_user_vbuf_range(const struct pipe_draw_info *info, 111801e04c3fSmrg const struct swr_vertex_element_state *velems, 111901e04c3fSmrg const struct pipe_vertex_buffer *vb, 112001e04c3fSmrg uint32_t i, 112101e04c3fSmrg uint32_t *totelems, 112201e04c3fSmrg uint32_t *base, 11237ec681f3Smrg uint32_t *size, 11247ec681f3Smrg int index_bias) 112501e04c3fSmrg{ 112601e04c3fSmrg /* FIXME: The size is too large - we don't access the full extra stride. */ 112701e04c3fSmrg unsigned elems; 11287ec681f3Smrg unsigned elem_pitch = vb->stride + velems->stream_pitch[i]; 112901e04c3fSmrg if (velems->instanced_bufs & (1U << i)) { 113001e04c3fSmrg elems = info->instance_count / velems->min_instance_div[i] + 1; 113101e04c3fSmrg *totelems = info->start_instance + elems; 113201e04c3fSmrg *base = info->start_instance * vb->stride; 11337ec681f3Smrg *size = elems * elem_pitch; 113401e04c3fSmrg } else if (vb->stride) { 113501e04c3fSmrg elems = info->max_index - info->min_index + 1; 11367ec681f3Smrg *totelems = (info->max_index + (info->index_size ? index_bias : 0)) + 1; 11377ec681f3Smrg *base = (info->min_index + (info->index_size ? index_bias : 0)) * vb->stride; 11387ec681f3Smrg *size = elems * elem_pitch; 113901e04c3fSmrg } else { 114001e04c3fSmrg *totelems = 1; 114101e04c3fSmrg *base = 0; 114201e04c3fSmrg *size = velems->stream_pitch[i]; 114301e04c3fSmrg } 114401e04c3fSmrg} 114501e04c3fSmrg 114601e04c3fSmrgstatic void 114701e04c3fSmrgswr_update_poly_stipple(struct swr_context *ctx) 114801e04c3fSmrg{ 114901e04c3fSmrg struct swr_draw_context *pDC = &ctx->swrDC; 115001e04c3fSmrg 115101e04c3fSmrg assert(sizeof(ctx->poly_stipple.pipe.stipple) == sizeof(pDC->polyStipple)); 115201e04c3fSmrg memcpy(pDC->polyStipple, 115301e04c3fSmrg ctx->poly_stipple.pipe.stipple, 115401e04c3fSmrg sizeof(ctx->poly_stipple.pipe.stipple)); 115501e04c3fSmrg} 115601e04c3fSmrg 11577ec681f3Smrg 11587ec681f3Smrgstatic struct tgsi_shader_info * 11597ec681f3Smrgswr_get_last_fe(const struct swr_context *ctx) 11607ec681f3Smrg{ 11617ec681f3Smrg tgsi_shader_info *pLastFE = &ctx->vs->info.base; 11627ec681f3Smrg 11637ec681f3Smrg if (ctx->gs) { 11647ec681f3Smrg pLastFE = &ctx->gs->info.base; 11657ec681f3Smrg } 11667ec681f3Smrg else if (ctx->tes) { 11677ec681f3Smrg pLastFE = &ctx->tes->info.base; 11687ec681f3Smrg } 11697ec681f3Smrg else if (ctx->tcs) { 11707ec681f3Smrg pLastFE = &ctx->tcs->info.base; 11717ec681f3Smrg } 11727ec681f3Smrg return pLastFE; 11737ec681f3Smrg} 11747ec681f3Smrg 11757ec681f3Smrg 117601e04c3fSmrgvoid 117701e04c3fSmrgswr_update_derived(struct pipe_context *pipe, 11787ec681f3Smrg const struct pipe_draw_info *p_draw_info, 11797ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 118001e04c3fSmrg{ 118101e04c3fSmrg struct swr_context *ctx = swr_context(pipe); 118201e04c3fSmrg struct swr_screen *screen = swr_screen(pipe->screen); 118301e04c3fSmrg 118401e04c3fSmrg /* When called from swr_clear (p_draw_info = null), set any null 118501e04c3fSmrg * state-objects to the dummy state objects to prevent nullptr dereference 118601e04c3fSmrg * in validation below. 118701e04c3fSmrg * 118801e04c3fSmrg * Important that this remains static for zero initialization. These 118901e04c3fSmrg * aren't meant to be proper state objects, just empty structs. They will 119001e04c3fSmrg * not be written to. 119101e04c3fSmrg * 119201e04c3fSmrg * Shaders can't be part of the union since they contain std::unordered_map 119301e04c3fSmrg */ 119401e04c3fSmrg static struct { 119501e04c3fSmrg union { 119601e04c3fSmrg struct pipe_rasterizer_state rasterizer; 119701e04c3fSmrg struct pipe_depth_stencil_alpha_state depth_stencil; 119801e04c3fSmrg struct swr_blend_state blend; 119901e04c3fSmrg } state; 120001e04c3fSmrg struct swr_vertex_shader vs; 120101e04c3fSmrg struct swr_fragment_shader fs; 120201e04c3fSmrg } swr_dummy; 120301e04c3fSmrg 120401e04c3fSmrg if (!p_draw_info) { 120501e04c3fSmrg if (!ctx->rasterizer) 120601e04c3fSmrg ctx->rasterizer = &swr_dummy.state.rasterizer; 120701e04c3fSmrg if (!ctx->depth_stencil) 120801e04c3fSmrg ctx->depth_stencil = &swr_dummy.state.depth_stencil; 120901e04c3fSmrg if (!ctx->blend) 121001e04c3fSmrg ctx->blend = &swr_dummy.state.blend; 121101e04c3fSmrg if (!ctx->vs) 121201e04c3fSmrg ctx->vs = &swr_dummy.vs; 121301e04c3fSmrg if (!ctx->fs) 121401e04c3fSmrg ctx->fs = &swr_dummy.fs; 121501e04c3fSmrg } 121601e04c3fSmrg 121701e04c3fSmrg /* Update screen->pipe to current pipe context. */ 121801e04c3fSmrg screen->pipe = pipe; 121901e04c3fSmrg 122001e04c3fSmrg /* Any state that requires dirty flags to be re-triggered sets this mask */ 122101e04c3fSmrg /* For example, user_buffer vertex and index buffers. */ 122201e04c3fSmrg unsigned post_update_dirty_flags = 0; 122301e04c3fSmrg 122401e04c3fSmrg /* bring resources that changed context up-to-date */ 122501e04c3fSmrg swr_invalidate_buffers_after_ctx_change(pipe); 122601e04c3fSmrg 122701e04c3fSmrg /* Render Targets */ 122801e04c3fSmrg if (ctx->dirty & SWR_NEW_FRAMEBUFFER) { 122901e04c3fSmrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 123001e04c3fSmrg const struct util_format_description *desc = NULL; 123101e04c3fSmrg bool need_fence = false; 123201e04c3fSmrg 123301e04c3fSmrg /* colorbuffer targets */ 123401e04c3fSmrg if (fb->nr_cbufs) { 123501e04c3fSmrg for (unsigned i = 0; i < fb->nr_cbufs; ++i) 123601e04c3fSmrg need_fence |= swr_change_rt( 123701e04c3fSmrg ctx, SWR_ATTACHMENT_COLOR0 + i, fb->cbufs[i]); 123801e04c3fSmrg } 123901e04c3fSmrg for (unsigned i = fb->nr_cbufs; i < SWR_NUM_RENDERTARGETS; ++i) 124001e04c3fSmrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_COLOR0 + i, NULL); 124101e04c3fSmrg 124201e04c3fSmrg /* depth/stencil target */ 124301e04c3fSmrg if (fb->zsbuf) 124401e04c3fSmrg desc = util_format_description(fb->zsbuf->format); 124501e04c3fSmrg if (fb->zsbuf && util_format_has_depth(desc)) 124601e04c3fSmrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, fb->zsbuf); 124701e04c3fSmrg else 124801e04c3fSmrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, NULL); 124901e04c3fSmrg 125001e04c3fSmrg if (fb->zsbuf && util_format_has_stencil(desc)) 125101e04c3fSmrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, fb->zsbuf); 125201e04c3fSmrg else 125301e04c3fSmrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, NULL); 125401e04c3fSmrg 125501e04c3fSmrg /* This fence ensures any attachment changes are resolved before the 125601e04c3fSmrg * next draw */ 125701e04c3fSmrg if (need_fence) 125801e04c3fSmrg swr_fence_submit(ctx, screen->flush_fence); 125901e04c3fSmrg } 126001e04c3fSmrg 126101e04c3fSmrg /* Raster state */ 126201e04c3fSmrg if (ctx->dirty & (SWR_NEW_RASTERIZER | 126301e04c3fSmrg SWR_NEW_VS | // clipping 12647ec681f3Smrg SWR_NEW_TES | 12657ec681f3Smrg SWR_NEW_TCS | 126601e04c3fSmrg SWR_NEW_FRAMEBUFFER)) { 126701e04c3fSmrg pipe_rasterizer_state *rasterizer = ctx->rasterizer; 126801e04c3fSmrg pipe_framebuffer_state *fb = &ctx->framebuffer; 126901e04c3fSmrg 127001e04c3fSmrg SWR_RASTSTATE *rastState = &ctx->derived.rastState; 127101e04c3fSmrg rastState->cullMode = swr_convert_cull_mode(rasterizer->cull_face); 127201e04c3fSmrg rastState->frontWinding = rasterizer->front_ccw 127301e04c3fSmrg ? SWR_FRONTWINDING_CCW 127401e04c3fSmrg : SWR_FRONTWINDING_CW; 127501e04c3fSmrg rastState->scissorEnable = rasterizer->scissor; 127601e04c3fSmrg rastState->pointSize = rasterizer->point_size > 0.0f 127701e04c3fSmrg ? rasterizer->point_size 127801e04c3fSmrg : 1.0f; 127901e04c3fSmrg rastState->lineWidth = rasterizer->line_width > 0.0f 128001e04c3fSmrg ? rasterizer->line_width 128101e04c3fSmrg : 1.0f; 128201e04c3fSmrg 128301e04c3fSmrg rastState->pointParam = rasterizer->point_size_per_vertex; 128401e04c3fSmrg 128501e04c3fSmrg rastState->pointSpriteEnable = rasterizer->sprite_coord_enable; 128601e04c3fSmrg rastState->pointSpriteTopOrigin = 128701e04c3fSmrg rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT; 128801e04c3fSmrg 128901e04c3fSmrg /* If SWR_MSAA_FORCE_ENABLE is set, turn msaa on */ 129001e04c3fSmrg if (screen->msaa_force_enable && !rasterizer->multisample) { 129101e04c3fSmrg /* Force enable and use the value the surface was created with */ 129201e04c3fSmrg rasterizer->multisample = true; 129301e04c3fSmrg fb->samples = swr_resource(fb->cbufs[0]->texture)->swr.numSamples; 129401e04c3fSmrg fprintf(stderr,"msaa force enable: %d samples\n", fb->samples); 129501e04c3fSmrg } 129601e04c3fSmrg 129701e04c3fSmrg rastState->sampleCount = GetSampleCount(fb->samples); 129801e04c3fSmrg rastState->forcedSampleCount = false; 129901e04c3fSmrg rastState->bIsCenterPattern = !rasterizer->multisample; 130001e04c3fSmrg rastState->pixelLocation = SWR_PIXEL_LOCATION_CENTER; 130101e04c3fSmrg 130201e04c3fSmrg /* Only initialize sample positions if msaa is enabled */ 130301e04c3fSmrg if (rasterizer->multisample) { 130401e04c3fSmrg for (uint32_t i = 0; i < fb->samples; i++) { 130501e04c3fSmrg const uint8_t *sample = swr_sample_positions[fb->samples-1 + i]; 130601e04c3fSmrg rastState->samplePositions.SetXi(i, sample[0] << 4); 130701e04c3fSmrg rastState->samplePositions.SetYi(i, sample[1] << 4); 130801e04c3fSmrg rastState->samplePositions.SetX (i, sample[0] / 16.0f); 130901e04c3fSmrg rastState->samplePositions.SetY (i, sample[1] / 16.0f); 131001e04c3fSmrg } 131101e04c3fSmrg rastState->samplePositions.PrecalcSampleData(fb->samples); 131201e04c3fSmrg } 131301e04c3fSmrg 131401e04c3fSmrg bool do_offset = false; 131501e04c3fSmrg switch (rasterizer->fill_front) { 131601e04c3fSmrg case PIPE_POLYGON_MODE_FILL: 131701e04c3fSmrg do_offset = rasterizer->offset_tri; 131801e04c3fSmrg break; 131901e04c3fSmrg case PIPE_POLYGON_MODE_LINE: 132001e04c3fSmrg do_offset = rasterizer->offset_line; 132101e04c3fSmrg break; 132201e04c3fSmrg case PIPE_POLYGON_MODE_POINT: 132301e04c3fSmrg do_offset = rasterizer->offset_point; 132401e04c3fSmrg break; 132501e04c3fSmrg } 132601e04c3fSmrg 132701e04c3fSmrg if (do_offset) { 132801e04c3fSmrg rastState->depthBias = rasterizer->offset_units; 132901e04c3fSmrg rastState->slopeScaledDepthBias = rasterizer->offset_scale; 133001e04c3fSmrg rastState->depthBiasClamp = rasterizer->offset_clamp; 133101e04c3fSmrg } else { 133201e04c3fSmrg rastState->depthBias = 0; 133301e04c3fSmrg rastState->slopeScaledDepthBias = 0; 133401e04c3fSmrg rastState->depthBiasClamp = 0; 133501e04c3fSmrg } 133601e04c3fSmrg 133701e04c3fSmrg /* translate polygon mode, at least for the front==back case */ 133801e04c3fSmrg rastState->fillMode = swr_convert_fill_mode(rasterizer->fill_front); 133901e04c3fSmrg 134001e04c3fSmrg struct pipe_surface *zb = fb->zsbuf; 134101e04c3fSmrg if (zb && swr_resource(zb->texture)->has_depth) 134201e04c3fSmrg rastState->depthFormat = swr_resource(zb->texture)->swr.format; 134301e04c3fSmrg 134401e04c3fSmrg rastState->depthClipEnable = rasterizer->depth_clip_near; 13457ec681f3Smrg rastState->clipEnable = rasterizer->depth_clip_near | rasterizer->depth_clip_far; 134601e04c3fSmrg rastState->clipHalfZ = rasterizer->clip_halfz; 134701e04c3fSmrg 134801e04c3fSmrg ctx->api.pfnSwrSetRastState(ctx->swrContext, rastState); 134901e04c3fSmrg } 135001e04c3fSmrg 135101e04c3fSmrg /* Viewport */ 135201e04c3fSmrg if (ctx->dirty & (SWR_NEW_VIEWPORT | SWR_NEW_FRAMEBUFFER 135301e04c3fSmrg | SWR_NEW_RASTERIZER)) { 13547ec681f3Smrg pipe_viewport_state *state = &ctx->viewports[0]; 135501e04c3fSmrg pipe_framebuffer_state *fb = &ctx->framebuffer; 135601e04c3fSmrg pipe_rasterizer_state *rasterizer = ctx->rasterizer; 135701e04c3fSmrg 13587ec681f3Smrg SWR_VIEWPORT *vp = &ctx->derived.vp[0]; 135901e04c3fSmrg SWR_VIEWPORT_MATRICES *vpm = &ctx->derived.vpm; 136001e04c3fSmrg 13617ec681f3Smrg for (unsigned i = 0; i < KNOB_NUM_VIEWPORTS_SCISSORS; i++) { 13627ec681f3Smrg vp->x = state->translate[0] - state->scale[0]; 13637ec681f3Smrg vp->width = 2 * state->scale[0]; 13647ec681f3Smrg vp->y = state->translate[1] - fabs(state->scale[1]); 13657ec681f3Smrg vp->height = 2 * fabs(state->scale[1]); 13667ec681f3Smrg util_viewport_zmin_zmax(state, rasterizer->clip_halfz, 13677ec681f3Smrg &vp->minZ, &vp->maxZ); 136801e04c3fSmrg 13697ec681f3Smrg if (rasterizer->depth_clip_near) { 13707ec681f3Smrg vp->minZ = 0.0f; 13717ec681f3Smrg } 13727ec681f3Smrg 13737ec681f3Smrg if (rasterizer->depth_clip_far) { 13747ec681f3Smrg vp->maxZ = 1.0f; 13757ec681f3Smrg } 13767ec681f3Smrg 13777ec681f3Smrg vpm->m00[i] = state->scale[0]; 13787ec681f3Smrg vpm->m11[i] = state->scale[1]; 13797ec681f3Smrg vpm->m22[i] = state->scale[2]; 13807ec681f3Smrg vpm->m30[i] = state->translate[0]; 13817ec681f3Smrg vpm->m31[i] = state->translate[1]; 13827ec681f3Smrg vpm->m32[i] = state->translate[2]; 13837ec681f3Smrg 13847ec681f3Smrg /* Now that the matrix is calculated, clip the view coords to screen 13857ec681f3Smrg * size. OpenGL allows for -ve x,y in the viewport. */ 13867ec681f3Smrg if (vp->x < 0.0f) { 13877ec681f3Smrg vp->width += vp->x; 13887ec681f3Smrg vp->x = 0.0f; 13897ec681f3Smrg } 13907ec681f3Smrg if (vp->y < 0.0f) { 13917ec681f3Smrg vp->height += vp->y; 13927ec681f3Smrg vp->y = 0.0f; 13937ec681f3Smrg } 13947ec681f3Smrg vp->width = std::min(vp->width, (float) fb->width - vp->x); 13957ec681f3Smrg vp->height = std::min(vp->height, (float) fb->height - vp->y); 13967ec681f3Smrg 13977ec681f3Smrg vp++; 13987ec681f3Smrg state++; 13997ec681f3Smrg } 14007ec681f3Smrg ctx->api.pfnSwrSetViewports(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS, 14017ec681f3Smrg &ctx->derived.vp[0], &ctx->derived.vpm); 140201e04c3fSmrg } 140301e04c3fSmrg 140401e04c3fSmrg /* When called from swr_clear (p_draw_info = null), render targets, 140501e04c3fSmrg * rasterState and viewports (dependent on render targets) are the only 140601e04c3fSmrg * necessary validation. Defer remaining validation by setting 140701e04c3fSmrg * post_update_dirty_flags and clear all dirty flags. BackendState is 140801e04c3fSmrg * still unconditionally validated below */ 140901e04c3fSmrg if (!p_draw_info) { 141001e04c3fSmrg post_update_dirty_flags = ctx->dirty & ~(SWR_NEW_FRAMEBUFFER | 141101e04c3fSmrg SWR_NEW_RASTERIZER | 141201e04c3fSmrg SWR_NEW_VIEWPORT); 141301e04c3fSmrg ctx->dirty = 0; 141401e04c3fSmrg } 141501e04c3fSmrg 141601e04c3fSmrg /* Scissor */ 141701e04c3fSmrg if (ctx->dirty & SWR_NEW_SCISSOR) { 14187ec681f3Smrg ctx->api.pfnSwrSetScissorRects(ctx->swrContext, KNOB_NUM_VIEWPORTS_SCISSORS, ctx->swr_scissors); 141901e04c3fSmrg } 142001e04c3fSmrg 142101e04c3fSmrg /* Set vertex & index buffers */ 142201e04c3fSmrg if (ctx->dirty & SWR_NEW_VERTEX) { 142301e04c3fSmrg const struct pipe_draw_info &info = *p_draw_info; 142401e04c3fSmrg 142501e04c3fSmrg /* vertex buffers */ 142601e04c3fSmrg SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS]; 142701e04c3fSmrg for (UINT i = 0; i < ctx->num_vertex_buffers; i++) { 14287ec681f3Smrg uint32_t size = 0, pitch = 0, elems = 0, partial_inbounds = 0; 14297ec681f3Smrg uint32_t min_vertex_index = 0; 143001e04c3fSmrg const uint8_t *p_data; 143101e04c3fSmrg struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; 143201e04c3fSmrg 143301e04c3fSmrg pitch = vb->stride; 14349f464c52Smaya if (vb->is_user_buffer) { 143501e04c3fSmrg /* Client buffer 143601e04c3fSmrg * client memory is one-time use, re-trigger SWR_NEW_VERTEX to 143701e04c3fSmrg * revalidate on each draw */ 143801e04c3fSmrg post_update_dirty_flags |= SWR_NEW_VERTEX; 143901e04c3fSmrg 144001e04c3fSmrg uint32_t base; 14417ec681f3Smrg swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size, draw->index_bias); 144201e04c3fSmrg partial_inbounds = 0; 14437ec681f3Smrg min_vertex_index = info.min_index + (info.index_size ? draw->index_bias : 0); 144401e04c3fSmrg 144501e04c3fSmrg size = AlignUp(size, 4); 144601e04c3fSmrg /* If size of client memory copy is too large, don't copy. The 144701e04c3fSmrg * draw will access user-buffer directly and then block. This is 144801e04c3fSmrg * faster than queuing many large client draws. */ 144901e04c3fSmrg if (size >= screen->client_copy_limit) { 14507ec681f3Smrg post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW; 145101e04c3fSmrg p_data = (const uint8_t *) vb->buffer.user; 145201e04c3fSmrg } else { 145301e04c3fSmrg /* Copy only needed vertices to scratch space */ 145401e04c3fSmrg const void *ptr = (const uint8_t *) vb->buffer.user + base; 145501e04c3fSmrg ptr = (uint8_t *)swr_copy_to_scratch_space( 145601e04c3fSmrg ctx, &ctx->scratch->vertex_buffer, ptr, size); 145701e04c3fSmrg p_data = (const uint8_t *)ptr - base; 145801e04c3fSmrg } 14599f464c52Smaya } else if (vb->buffer.resource) { 14609f464c52Smaya /* VBO */ 14619f464c52Smaya if (!pitch) { 14629f464c52Smaya /* If pitch=0 (ie vb->stride), buffer contains a single 14639f464c52Smaya * constant attribute. Use the stream_pitch which was 14649f464c52Smaya * calculated during creation of vertex_elements_state for the 14659f464c52Smaya * size of the attribute. */ 14669f464c52Smaya size = ctx->velems->stream_pitch[i]; 14679f464c52Smaya elems = 1; 14689f464c52Smaya partial_inbounds = 0; 14699f464c52Smaya min_vertex_index = 0; 14709f464c52Smaya } else { 14719f464c52Smaya /* size is based on buffer->width0 rather than info.max_index 14729f464c52Smaya * to prevent having to validate VBO on each draw. */ 14739f464c52Smaya size = vb->buffer.resource->width0; 14749f464c52Smaya elems = size / pitch; 14759f464c52Smaya partial_inbounds = size % pitch; 14769f464c52Smaya min_vertex_index = 0; 14779f464c52Smaya } 14789f464c52Smaya 14799f464c52Smaya p_data = swr_resource_data(vb->buffer.resource) + vb->buffer_offset; 14809f464c52Smaya } else 14819f464c52Smaya p_data = NULL; 148201e04c3fSmrg 148301e04c3fSmrg swrVertexBuffers[i] = {0}; 148401e04c3fSmrg swrVertexBuffers[i].index = i; 148501e04c3fSmrg swrVertexBuffers[i].pitch = pitch; 148601e04c3fSmrg swrVertexBuffers[i].xpData = (gfxptr_t) p_data; 148701e04c3fSmrg swrVertexBuffers[i].size = size; 148801e04c3fSmrg swrVertexBuffers[i].minVertex = min_vertex_index; 148901e04c3fSmrg swrVertexBuffers[i].maxVertex = elems; 149001e04c3fSmrg swrVertexBuffers[i].partialInboundsSize = partial_inbounds; 149101e04c3fSmrg } 149201e04c3fSmrg 149301e04c3fSmrg ctx->api.pfnSwrSetVertexBuffers( 149401e04c3fSmrg ctx->swrContext, ctx->num_vertex_buffers, swrVertexBuffers); 149501e04c3fSmrg 149601e04c3fSmrg /* index buffer, if required (info passed in by swr_draw_vbo) */ 149701e04c3fSmrg SWR_FORMAT index_type = R32_UINT; /* Default for non-indexed draws */ 149801e04c3fSmrg if (info.index_size) { 149901e04c3fSmrg const uint8_t *p_data; 150001e04c3fSmrg uint32_t size, pitch; 150101e04c3fSmrg 150201e04c3fSmrg pitch = info.index_size ? info.index_size : sizeof(uint32_t); 150301e04c3fSmrg index_type = swr_convert_index_type(pitch); 150401e04c3fSmrg 150501e04c3fSmrg if (!info.has_user_indices) { 150601e04c3fSmrg /* VBO 150701e04c3fSmrg * size is based on buffer->width0 rather than info.count 150801e04c3fSmrg * to prevent having to validate VBO on each draw */ 150901e04c3fSmrg size = info.index.resource->width0; 151001e04c3fSmrg p_data = swr_resource_data(info.index.resource); 151101e04c3fSmrg } else { 151201e04c3fSmrg /* Client buffer 151301e04c3fSmrg * client memory is one-time use, re-trigger SWR_NEW_VERTEX to 151401e04c3fSmrg * revalidate on each draw */ 151501e04c3fSmrg post_update_dirty_flags |= SWR_NEW_VERTEX; 151601e04c3fSmrg 15177ec681f3Smrg size = draw->count * pitch; 15187ec681f3Smrg 151901e04c3fSmrg size = AlignUp(size, 4); 152001e04c3fSmrg /* If size of client memory copy is too large, don't copy. The 152101e04c3fSmrg * draw will access user-buffer directly and then block. This is 152201e04c3fSmrg * faster than queuing many large client draws. */ 152301e04c3fSmrg if (size >= screen->client_copy_limit) { 15247ec681f3Smrg post_update_dirty_flags |= SWR_BLOCK_CLIENT_DRAW; 15257ec681f3Smrg p_data = (const uint8_t *) info.index.user + 15267ec681f3Smrg draw->start * info.index_size; 152701e04c3fSmrg } else { 152801e04c3fSmrg /* Copy indices to scratch space */ 15297ec681f3Smrg const void *ptr = (char*)info.index.user + 15307ec681f3Smrg draw->start * info.index_size; 153101e04c3fSmrg ptr = swr_copy_to_scratch_space( 153201e04c3fSmrg ctx, &ctx->scratch->index_buffer, ptr, size); 153301e04c3fSmrg p_data = (const uint8_t *)ptr; 153401e04c3fSmrg } 153501e04c3fSmrg } 153601e04c3fSmrg 153701e04c3fSmrg SWR_INDEX_BUFFER_STATE swrIndexBuffer; 153801e04c3fSmrg swrIndexBuffer.format = swr_convert_index_type(info.index_size); 153901e04c3fSmrg swrIndexBuffer.xpIndices = (gfxptr_t) p_data; 154001e04c3fSmrg swrIndexBuffer.size = size; 154101e04c3fSmrg 154201e04c3fSmrg ctx->api.pfnSwrSetIndexBuffer(ctx->swrContext, &swrIndexBuffer); 154301e04c3fSmrg } 154401e04c3fSmrg 154501e04c3fSmrg struct swr_vertex_element_state *velems = ctx->velems; 154601e04c3fSmrg if (velems && velems->fsState.indexType != index_type) { 154701e04c3fSmrg velems->fsFunc = NULL; 154801e04c3fSmrg velems->fsState.indexType = index_type; 154901e04c3fSmrg } 155001e04c3fSmrg } 155101e04c3fSmrg 155201e04c3fSmrg /* GeometryShader */ 155301e04c3fSmrg if (ctx->dirty & (SWR_NEW_GS | 155401e04c3fSmrg SWR_NEW_VS | 15557ec681f3Smrg SWR_NEW_TCS | 15567ec681f3Smrg SWR_NEW_TES | 155701e04c3fSmrg SWR_NEW_SAMPLER | 155801e04c3fSmrg SWR_NEW_SAMPLER_VIEW)) { 155901e04c3fSmrg if (ctx->gs) { 156001e04c3fSmrg swr_jit_gs_key key; 156101e04c3fSmrg swr_generate_gs_key(key, ctx, ctx->gs); 156201e04c3fSmrg auto search = ctx->gs->map.find(key); 156301e04c3fSmrg PFN_GS_FUNC func; 156401e04c3fSmrg if (search != ctx->gs->map.end()) { 156501e04c3fSmrg func = search->second->shader; 156601e04c3fSmrg } else { 156701e04c3fSmrg func = swr_compile_gs(ctx, key); 156801e04c3fSmrg } 156901e04c3fSmrg ctx->api.pfnSwrSetGsFunc(ctx->swrContext, func); 157001e04c3fSmrg 157101e04c3fSmrg /* JIT sampler state */ 157201e04c3fSmrg if (ctx->dirty & SWR_NEW_SAMPLER) { 157301e04c3fSmrg swr_update_sampler_state(ctx, 157401e04c3fSmrg PIPE_SHADER_GEOMETRY, 157501e04c3fSmrg key.nr_samplers, 157601e04c3fSmrg ctx->swrDC.samplersGS); 157701e04c3fSmrg } 157801e04c3fSmrg 157901e04c3fSmrg /* JIT sampler view state */ 158001e04c3fSmrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 158101e04c3fSmrg swr_update_texture_state(ctx, 158201e04c3fSmrg PIPE_SHADER_GEOMETRY, 158301e04c3fSmrg key.nr_sampler_views, 158401e04c3fSmrg ctx->swrDC.texturesGS); 158501e04c3fSmrg } 158601e04c3fSmrg 158701e04c3fSmrg ctx->api.pfnSwrSetGsState(ctx->swrContext, &ctx->gs->gsState); 158801e04c3fSmrg } else { 158901e04c3fSmrg SWR_GS_STATE state = { 0 }; 159001e04c3fSmrg ctx->api.pfnSwrSetGsState(ctx->swrContext, &state); 159101e04c3fSmrg ctx->api.pfnSwrSetGsFunc(ctx->swrContext, NULL); 159201e04c3fSmrg } 159301e04c3fSmrg } 159401e04c3fSmrg 15957ec681f3Smrg // We may need to restore tessellation state 15967ec681f3Smrg // This restored state may be however overwritten 15977ec681f3Smrg // during shader compilation 15987ec681f3Smrg if (ctx->dirty & SWR_NEW_TS) { 15997ec681f3Smrg if (ctx->tes != nullptr) { 16007ec681f3Smrg ctx->tsState = ctx->tes->ts_state; 16017ec681f3Smrg ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState); 16027ec681f3Smrg } else { 16037ec681f3Smrg SWR_TS_STATE state = { 0 }; 16047ec681f3Smrg ctx->api.pfnSwrSetTsState(ctx->swrContext, &state); 16057ec681f3Smrg } 16067ec681f3Smrg } 16077ec681f3Smrg 16087ec681f3Smrg // Tessellation Evaluation Shader 16097ec681f3Smrg // Compile TES first, because TCS is optional 16107ec681f3Smrg if (ctx->dirty & (SWR_NEW_GS | 16117ec681f3Smrg SWR_NEW_VS | 16127ec681f3Smrg SWR_NEW_TCS | 16137ec681f3Smrg SWR_NEW_TES | 161401e04c3fSmrg SWR_NEW_SAMPLER | 16157ec681f3Smrg SWR_NEW_SAMPLER_VIEW)) { 16167ec681f3Smrg if (ctx->tes) { 16177ec681f3Smrg swr_jit_tes_key key; 16187ec681f3Smrg swr_generate_tes_key(key, ctx, ctx->tes); 16197ec681f3Smrg 16207ec681f3Smrg auto search = ctx->tes->map.find(key); 16217ec681f3Smrg PFN_TES_FUNC func; 16227ec681f3Smrg if (search != ctx->tes->map.end()) { 16237ec681f3Smrg func = search->second->shader; 16247ec681f3Smrg } else { 16257ec681f3Smrg func = swr_compile_tes(ctx, key); 16267ec681f3Smrg } 16277ec681f3Smrg 16287ec681f3Smrg ctx->api.pfnSwrSetDsFunc(ctx->swrContext, func); 16297ec681f3Smrg 16307ec681f3Smrg /* JIT sampler state */ 16317ec681f3Smrg if (ctx->dirty & SWR_NEW_SAMPLER) { 16327ec681f3Smrg swr_update_sampler_state(ctx, 16337ec681f3Smrg PIPE_SHADER_TESS_EVAL, 16347ec681f3Smrg key.nr_samplers, 16357ec681f3Smrg ctx->swrDC.samplersTES); 16367ec681f3Smrg } 16377ec681f3Smrg 16387ec681f3Smrg /* JIT sampler view state */ 16397ec681f3Smrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 16407ec681f3Smrg swr_update_texture_state(ctx, 16417ec681f3Smrg PIPE_SHADER_TESS_EVAL, 16427ec681f3Smrg key.nr_sampler_views, 16437ec681f3Smrg ctx->swrDC.texturesTES); 16447ec681f3Smrg } 16457ec681f3Smrg 16467ec681f3Smrg // Update tessellation state in case it's been updated 16477ec681f3Smrg ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState); 16487ec681f3Smrg } else { 16497ec681f3Smrg ctx->api.pfnSwrSetDsFunc(ctx->swrContext, NULL); 16507ec681f3Smrg } 16517ec681f3Smrg } 16527ec681f3Smrg 16537ec681f3Smrg /* Tessellation Control Shader */ 16547ec681f3Smrg if (ctx->dirty & (SWR_NEW_GS | 16557ec681f3Smrg SWR_NEW_VS | 16567ec681f3Smrg SWR_NEW_TCS | 16577ec681f3Smrg SWR_NEW_TES | 16587ec681f3Smrg SWR_NEW_SAMPLER | 16597ec681f3Smrg SWR_NEW_SAMPLER_VIEW)) { 16607ec681f3Smrg if (ctx->tcs) { 16617ec681f3Smrg ctx->tcs->vertices_per_patch = ctx->patch_vertices; 16627ec681f3Smrg 16637ec681f3Smrg swr_jit_tcs_key key; 16647ec681f3Smrg swr_generate_tcs_key(key, ctx, ctx->tcs); 16657ec681f3Smrg 16667ec681f3Smrg auto search = ctx->tcs->map.find(key); 16677ec681f3Smrg PFN_TCS_FUNC func; 16687ec681f3Smrg if (search != ctx->tcs->map.end()) { 16697ec681f3Smrg func = search->second->shader; 16707ec681f3Smrg } else { 16717ec681f3Smrg func = swr_compile_tcs(ctx, key); 16727ec681f3Smrg } 16737ec681f3Smrg 16747ec681f3Smrg ctx->api.pfnSwrSetHsFunc(ctx->swrContext, func); 16757ec681f3Smrg 16767ec681f3Smrg /* JIT sampler state */ 16777ec681f3Smrg if (ctx->dirty & SWR_NEW_SAMPLER) { 16787ec681f3Smrg swr_update_sampler_state(ctx, 16797ec681f3Smrg PIPE_SHADER_TESS_CTRL, 16807ec681f3Smrg key.nr_samplers, 16817ec681f3Smrg ctx->swrDC.samplersTCS); 16827ec681f3Smrg } 16837ec681f3Smrg 16847ec681f3Smrg /* JIT sampler view state */ 16857ec681f3Smrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 16867ec681f3Smrg swr_update_texture_state(ctx, 16877ec681f3Smrg PIPE_SHADER_TESS_CTRL, 16887ec681f3Smrg key.nr_sampler_views, 16897ec681f3Smrg ctx->swrDC.texturesTCS); 16907ec681f3Smrg } 16917ec681f3Smrg 16927ec681f3Smrg // Update tessellation state in case it's been updated 16937ec681f3Smrg ctx->api.pfnSwrSetTsState(ctx->swrContext, &ctx->tsState); 16947ec681f3Smrg } else { 16957ec681f3Smrg ctx->api.pfnSwrSetHsFunc(ctx->swrContext, NULL); 16967ec681f3Smrg } 16977ec681f3Smrg } 16987ec681f3Smrg 16997ec681f3Smrg /* VertexShader */ 17007ec681f3Smrg if (ctx->dirty 17017ec681f3Smrg & (SWR_NEW_VS | SWR_NEW_RASTERIZER | // for clip planes 17027ec681f3Smrg SWR_NEW_SAMPLER | SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 170301e04c3fSmrg swr_jit_vs_key key; 170401e04c3fSmrg swr_generate_vs_key(key, ctx, ctx->vs); 170501e04c3fSmrg auto search = ctx->vs->map.find(key); 170601e04c3fSmrg PFN_VERTEX_FUNC func; 170701e04c3fSmrg if (search != ctx->vs->map.end()) { 170801e04c3fSmrg func = search->second->shader; 170901e04c3fSmrg } else { 171001e04c3fSmrg func = swr_compile_vs(ctx, key); 171101e04c3fSmrg } 171201e04c3fSmrg ctx->api.pfnSwrSetVertexFunc(ctx->swrContext, func); 171301e04c3fSmrg 171401e04c3fSmrg /* JIT sampler state */ 171501e04c3fSmrg if (ctx->dirty & SWR_NEW_SAMPLER) { 17167ec681f3Smrg swr_update_sampler_state( 17177ec681f3Smrg ctx, PIPE_SHADER_VERTEX, key.nr_samplers, ctx->swrDC.samplersVS); 171801e04c3fSmrg } 171901e04c3fSmrg 172001e04c3fSmrg /* JIT sampler view state */ 172101e04c3fSmrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 172201e04c3fSmrg swr_update_texture_state(ctx, 172301e04c3fSmrg PIPE_SHADER_VERTEX, 172401e04c3fSmrg key.nr_sampler_views, 172501e04c3fSmrg ctx->swrDC.texturesVS); 172601e04c3fSmrg } 172701e04c3fSmrg } 172801e04c3fSmrg 172901e04c3fSmrg /* work around the fact that poly stipple also affects lines */ 173001e04c3fSmrg /* and points, since we rasterize them as triangles, too */ 173101e04c3fSmrg /* Has to be before fragment shader, since it sets SWR_NEW_FS */ 173201e04c3fSmrg if (p_draw_info) { 173301e04c3fSmrg bool new_prim_is_poly = 17347ec681f3Smrg (u_reduced_prim((enum pipe_prim_type)p_draw_info->mode) == PIPE_PRIM_TRIANGLES) && 173501e04c3fSmrg (ctx->derived.rastState.fillMode == SWR_FILLMODE_SOLID); 173601e04c3fSmrg if (new_prim_is_poly != ctx->poly_stipple.prim_is_poly) { 173701e04c3fSmrg ctx->dirty |= SWR_NEW_FS; 173801e04c3fSmrg ctx->poly_stipple.prim_is_poly = new_prim_is_poly; 173901e04c3fSmrg } 174001e04c3fSmrg } 174101e04c3fSmrg 174201e04c3fSmrg /* FragmentShader */ 174301e04c3fSmrg if (ctx->dirty & (SWR_NEW_FS | 174401e04c3fSmrg SWR_NEW_VS | 174501e04c3fSmrg SWR_NEW_GS | 17467ec681f3Smrg SWR_NEW_TES | 17477ec681f3Smrg SWR_NEW_TCS | 174801e04c3fSmrg SWR_NEW_RASTERIZER | 174901e04c3fSmrg SWR_NEW_SAMPLER | 175001e04c3fSmrg SWR_NEW_SAMPLER_VIEW | 175101e04c3fSmrg SWR_NEW_FRAMEBUFFER)) { 175201e04c3fSmrg swr_jit_fs_key key; 175301e04c3fSmrg swr_generate_fs_key(key, ctx, ctx->fs); 175401e04c3fSmrg auto search = ctx->fs->map.find(key); 175501e04c3fSmrg PFN_PIXEL_KERNEL func; 175601e04c3fSmrg if (search != ctx->fs->map.end()) { 175701e04c3fSmrg func = search->second->shader; 175801e04c3fSmrg } else { 175901e04c3fSmrg func = swr_compile_fs(ctx, key); 176001e04c3fSmrg } 176101e04c3fSmrg SWR_PS_STATE psState = {0}; 176201e04c3fSmrg psState.pfnPixelShader = func; 176301e04c3fSmrg psState.killsPixel = ctx->fs->info.base.uses_kill; 176401e04c3fSmrg psState.inputCoverage = SWR_INPUT_COVERAGE_NORMAL; 176501e04c3fSmrg psState.writesODepth = ctx->fs->info.base.writes_z; 176601e04c3fSmrg psState.usesSourceDepth = ctx->fs->info.base.reads_z; 176701e04c3fSmrg psState.shadingRate = SWR_SHADING_RATE_PIXEL; 176801e04c3fSmrg psState.renderTargetMask = (1 << ctx->framebuffer.nr_cbufs) - 1; 176901e04c3fSmrg psState.posOffset = SWR_PS_POSITION_SAMPLE_NONE; 177001e04c3fSmrg uint32_t barycentricsMask = 0; 177101e04c3fSmrg#if 0 177201e04c3fSmrg // when we switch to mesa-master 177301e04c3fSmrg if (ctx->fs->info.base.uses_persp_center || 177401e04c3fSmrg ctx->fs->info.base.uses_linear_center) 177501e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK; 177601e04c3fSmrg if (ctx->fs->info.base.uses_persp_centroid || 177701e04c3fSmrg ctx->fs->info.base.uses_linear_centroid) 177801e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK; 177901e04c3fSmrg if (ctx->fs->info.base.uses_persp_sample || 178001e04c3fSmrg ctx->fs->info.base.uses_linear_sample) 178101e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK; 178201e04c3fSmrg#else 178301e04c3fSmrg for (unsigned i = 0; i < ctx->fs->info.base.num_inputs; i++) { 178401e04c3fSmrg switch (ctx->fs->info.base.input_interpolate_loc[i]) { 178501e04c3fSmrg case TGSI_INTERPOLATE_LOC_CENTER: 178601e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK; 178701e04c3fSmrg break; 178801e04c3fSmrg case TGSI_INTERPOLATE_LOC_CENTROID: 178901e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK; 179001e04c3fSmrg break; 179101e04c3fSmrg case TGSI_INTERPOLATE_LOC_SAMPLE: 179201e04c3fSmrg barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK; 179301e04c3fSmrg break; 179401e04c3fSmrg } 179501e04c3fSmrg } 179601e04c3fSmrg#endif 179701e04c3fSmrg psState.barycentricsMask = barycentricsMask; 179801e04c3fSmrg psState.usesUAV = false; // XXX 179901e04c3fSmrg psState.forceEarlyZ = false; 180001e04c3fSmrg ctx->api.pfnSwrSetPixelShaderState(ctx->swrContext, &psState); 180101e04c3fSmrg 180201e04c3fSmrg /* JIT sampler state */ 180301e04c3fSmrg if (ctx->dirty & (SWR_NEW_SAMPLER | 180401e04c3fSmrg SWR_NEW_FS)) { 180501e04c3fSmrg swr_update_sampler_state(ctx, 180601e04c3fSmrg PIPE_SHADER_FRAGMENT, 180701e04c3fSmrg key.nr_samplers, 180801e04c3fSmrg ctx->swrDC.samplersFS); 180901e04c3fSmrg } 181001e04c3fSmrg 181101e04c3fSmrg /* JIT sampler view state */ 181201e04c3fSmrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | 181301e04c3fSmrg SWR_NEW_FRAMEBUFFER | 181401e04c3fSmrg SWR_NEW_FS)) { 181501e04c3fSmrg swr_update_texture_state(ctx, 181601e04c3fSmrg PIPE_SHADER_FRAGMENT, 181701e04c3fSmrg key.nr_sampler_views, 181801e04c3fSmrg ctx->swrDC.texturesFS); 181901e04c3fSmrg } 182001e04c3fSmrg } 182101e04c3fSmrg 182201e04c3fSmrg 182301e04c3fSmrg /* VertexShader Constants */ 182401e04c3fSmrg if (ctx->dirty & SWR_NEW_VSCONSTANTS) { 182501e04c3fSmrg swr_update_constants(ctx, PIPE_SHADER_VERTEX); 182601e04c3fSmrg } 182701e04c3fSmrg 182801e04c3fSmrg /* FragmentShader Constants */ 182901e04c3fSmrg if (ctx->dirty & SWR_NEW_FSCONSTANTS) { 183001e04c3fSmrg swr_update_constants(ctx, PIPE_SHADER_FRAGMENT); 183101e04c3fSmrg } 183201e04c3fSmrg 183301e04c3fSmrg /* GeometryShader Constants */ 183401e04c3fSmrg if (ctx->dirty & SWR_NEW_GSCONSTANTS) { 183501e04c3fSmrg swr_update_constants(ctx, PIPE_SHADER_GEOMETRY); 183601e04c3fSmrg } 183701e04c3fSmrg 18387ec681f3Smrg /* Tessellation Control Shader Constants */ 18397ec681f3Smrg if (ctx->dirty & SWR_NEW_TCSCONSTANTS) { 18407ec681f3Smrg swr_update_constants(ctx, PIPE_SHADER_TESS_CTRL); 18417ec681f3Smrg } 18427ec681f3Smrg 18437ec681f3Smrg /* Tessellation Evaluation Shader Constants */ 18447ec681f3Smrg if (ctx->dirty & SWR_NEW_TESCONSTANTS) { 18457ec681f3Smrg swr_update_constants(ctx, PIPE_SHADER_TESS_EVAL); 18467ec681f3Smrg } 18477ec681f3Smrg 184801e04c3fSmrg /* Depth/stencil state */ 184901e04c3fSmrg if (ctx->dirty & (SWR_NEW_DEPTH_STENCIL_ALPHA | SWR_NEW_FRAMEBUFFER)) { 18507ec681f3Smrg struct pipe_depth_stencil_alpha_state *depth = ctx->depth_stencil; 18517ec681f3Smrg struct pipe_stencil_state *stencil = depth->stencil; 185201e04c3fSmrg SWR_DEPTH_STENCIL_STATE depthStencilState = {{0}}; 185301e04c3fSmrg SWR_DEPTH_BOUNDS_STATE depthBoundsState = {0}; 185401e04c3fSmrg 185501e04c3fSmrg /* XXX, incomplete. Need to flesh out stencil & alpha test state 185601e04c3fSmrg struct pipe_stencil_state *front_stencil = 185701e04c3fSmrg ctx->depth_stencil.stencil[0]; 185801e04c3fSmrg struct pipe_stencil_state *back_stencil = ctx->depth_stencil.stencil[1]; 185901e04c3fSmrg */ 186001e04c3fSmrg if (stencil[0].enabled) { 186101e04c3fSmrg depthStencilState.stencilWriteEnable = 1; 186201e04c3fSmrg depthStencilState.stencilTestEnable = 1; 186301e04c3fSmrg depthStencilState.stencilTestFunc = 186401e04c3fSmrg swr_convert_depth_func(stencil[0].func); 186501e04c3fSmrg 186601e04c3fSmrg depthStencilState.stencilPassDepthPassOp = 186701e04c3fSmrg swr_convert_stencil_op(stencil[0].zpass_op); 186801e04c3fSmrg depthStencilState.stencilPassDepthFailOp = 186901e04c3fSmrg swr_convert_stencil_op(stencil[0].zfail_op); 187001e04c3fSmrg depthStencilState.stencilFailOp = 187101e04c3fSmrg swr_convert_stencil_op(stencil[0].fail_op); 187201e04c3fSmrg depthStencilState.stencilWriteMask = stencil[0].writemask; 187301e04c3fSmrg depthStencilState.stencilTestMask = stencil[0].valuemask; 187401e04c3fSmrg depthStencilState.stencilRefValue = ctx->stencil_ref.ref_value[0]; 187501e04c3fSmrg } 187601e04c3fSmrg if (stencil[1].enabled) { 187701e04c3fSmrg depthStencilState.doubleSidedStencilTestEnable = 1; 187801e04c3fSmrg 187901e04c3fSmrg depthStencilState.backfaceStencilTestFunc = 188001e04c3fSmrg swr_convert_depth_func(stencil[1].func); 188101e04c3fSmrg 188201e04c3fSmrg depthStencilState.backfaceStencilPassDepthPassOp = 188301e04c3fSmrg swr_convert_stencil_op(stencil[1].zpass_op); 188401e04c3fSmrg depthStencilState.backfaceStencilPassDepthFailOp = 188501e04c3fSmrg swr_convert_stencil_op(stencil[1].zfail_op); 188601e04c3fSmrg depthStencilState.backfaceStencilFailOp = 188701e04c3fSmrg swr_convert_stencil_op(stencil[1].fail_op); 188801e04c3fSmrg depthStencilState.backfaceStencilWriteMask = stencil[1].writemask; 188901e04c3fSmrg depthStencilState.backfaceStencilTestMask = stencil[1].valuemask; 189001e04c3fSmrg 189101e04c3fSmrg depthStencilState.backfaceStencilRefValue = 189201e04c3fSmrg ctx->stencil_ref.ref_value[1]; 189301e04c3fSmrg } 189401e04c3fSmrg 18957ec681f3Smrg depthStencilState.depthTestEnable = depth->depth_enabled; 18967ec681f3Smrg depthStencilState.depthTestFunc = swr_convert_depth_func(depth->depth_func); 18977ec681f3Smrg depthStencilState.depthWriteEnable = depth->depth_writemask; 189801e04c3fSmrg ctx->api.pfnSwrSetDepthStencilState(ctx->swrContext, &depthStencilState); 189901e04c3fSmrg 19007ec681f3Smrg depthBoundsState.depthBoundsTestEnable = depth->depth_bounds_test; 19017ec681f3Smrg depthBoundsState.depthBoundsTestMinValue = depth->depth_bounds_min; 19027ec681f3Smrg depthBoundsState.depthBoundsTestMaxValue = depth->depth_bounds_max; 190301e04c3fSmrg ctx->api.pfnSwrSetDepthBoundsState(ctx->swrContext, &depthBoundsState); 190401e04c3fSmrg } 190501e04c3fSmrg 190601e04c3fSmrg /* Blend State */ 190701e04c3fSmrg if (ctx->dirty & (SWR_NEW_BLEND | 190801e04c3fSmrg SWR_NEW_RASTERIZER | 190901e04c3fSmrg SWR_NEW_FRAMEBUFFER | 191001e04c3fSmrg SWR_NEW_DEPTH_STENCIL_ALPHA)) { 191101e04c3fSmrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 191201e04c3fSmrg 191301e04c3fSmrg SWR_BLEND_STATE blendState; 191401e04c3fSmrg memcpy(&blendState, &ctx->blend->blendState, sizeof(blendState)); 191501e04c3fSmrg blendState.constantColor[0] = ctx->blend_color.color[0]; 191601e04c3fSmrg blendState.constantColor[1] = ctx->blend_color.color[1]; 191701e04c3fSmrg blendState.constantColor[2] = ctx->blend_color.color[2]; 191801e04c3fSmrg blendState.constantColor[3] = ctx->blend_color.color[3]; 191901e04c3fSmrg blendState.alphaTestReference = 19207ec681f3Smrg *((uint32_t*)&ctx->depth_stencil->alpha_ref_value); 192101e04c3fSmrg 192201e04c3fSmrg blendState.sampleMask = ctx->sample_mask; 192301e04c3fSmrg blendState.sampleCount = GetSampleCount(fb->samples); 192401e04c3fSmrg 192501e04c3fSmrg /* If there are no color buffers bound, disable writes on RT0 192601e04c3fSmrg * and skip loop */ 192701e04c3fSmrg if (fb->nr_cbufs == 0) { 192801e04c3fSmrg blendState.renderTarget[0].writeDisableRed = 1; 192901e04c3fSmrg blendState.renderTarget[0].writeDisableGreen = 1; 193001e04c3fSmrg blendState.renderTarget[0].writeDisableBlue = 1; 193101e04c3fSmrg blendState.renderTarget[0].writeDisableAlpha = 1; 193201e04c3fSmrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, 0, NULL); 193301e04c3fSmrg } 193401e04c3fSmrg else 193501e04c3fSmrg for (int target = 0; 193601e04c3fSmrg target < std::min(SWR_NUM_RENDERTARGETS, 193701e04c3fSmrg PIPE_MAX_COLOR_BUFS); 193801e04c3fSmrg target++) { 193901e04c3fSmrg if (!fb->cbufs[target]) 194001e04c3fSmrg continue; 194101e04c3fSmrg 194201e04c3fSmrg struct swr_resource *colorBuffer = 194301e04c3fSmrg swr_resource(fb->cbufs[target]->texture); 194401e04c3fSmrg 194501e04c3fSmrg BLEND_COMPILE_STATE compileState; 194601e04c3fSmrg memset(&compileState, 0, sizeof(compileState)); 194701e04c3fSmrg compileState.format = colorBuffer->swr.format; 194801e04c3fSmrg memcpy(&compileState.blendState, 194901e04c3fSmrg &ctx->blend->compileState[target], 195001e04c3fSmrg sizeof(compileState.blendState)); 195101e04c3fSmrg 195201e04c3fSmrg const SWR_FORMAT_INFO& info = GetFormatInfo(compileState.format); 195301e04c3fSmrg if (compileState.blendState.logicOpEnable && 195401e04c3fSmrg ((info.type[0] == SWR_TYPE_FLOAT) || info.isSRGB)) { 195501e04c3fSmrg compileState.blendState.logicOpEnable = false; 195601e04c3fSmrg } 195701e04c3fSmrg 195801e04c3fSmrg if (info.type[0] == SWR_TYPE_SINT || info.type[0] == SWR_TYPE_UINT) 195901e04c3fSmrg compileState.blendState.blendEnable = false; 196001e04c3fSmrg 196101e04c3fSmrg if (compileState.blendState.blendEnable == false && 196201e04c3fSmrg compileState.blendState.logicOpEnable == false && 19637ec681f3Smrg ctx->depth_stencil->alpha_enabled == 0) { 196401e04c3fSmrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, NULL); 196501e04c3fSmrg continue; 196601e04c3fSmrg } 196701e04c3fSmrg 196801e04c3fSmrg compileState.desc.alphaTestEnable = 19697ec681f3Smrg ctx->depth_stencil->alpha_enabled; 197001e04c3fSmrg compileState.desc.independentAlphaBlendEnable = 197101e04c3fSmrg (compileState.blendState.sourceBlendFactor != 197201e04c3fSmrg compileState.blendState.sourceAlphaBlendFactor) || 197301e04c3fSmrg (compileState.blendState.destBlendFactor != 197401e04c3fSmrg compileState.blendState.destAlphaBlendFactor) || 197501e04c3fSmrg (compileState.blendState.colorBlendFunc != 197601e04c3fSmrg compileState.blendState.alphaBlendFunc); 197701e04c3fSmrg compileState.desc.alphaToCoverageEnable = 197801e04c3fSmrg ctx->blend->pipe.alpha_to_coverage; 197901e04c3fSmrg compileState.desc.sampleMaskEnable = (blendState.sampleMask != 0); 198001e04c3fSmrg compileState.desc.numSamples = fb->samples; 198101e04c3fSmrg 198201e04c3fSmrg compileState.alphaTestFunction = 19837ec681f3Smrg swr_convert_depth_func(ctx->depth_stencil->alpha_func); 198401e04c3fSmrg compileState.alphaTestFormat = ALPHA_TEST_FLOAT32; // xxx 198501e04c3fSmrg 198601e04c3fSmrg compileState.Canonicalize(); 19877ec681f3Smrg 198801e04c3fSmrg PFN_BLEND_JIT_FUNC func = NULL; 198901e04c3fSmrg auto search = ctx->blendJIT->find(compileState); 199001e04c3fSmrg if (search != ctx->blendJIT->end()) { 199101e04c3fSmrg func = search->second; 199201e04c3fSmrg } else { 199301e04c3fSmrg HANDLE hJitMgr = screen->hJitMgr; 199401e04c3fSmrg func = JitCompileBlend(hJitMgr, compileState); 199501e04c3fSmrg debug_printf("BLEND shader %p\n", func); 199601e04c3fSmrg assert(func && "Error: BlendShader = NULL"); 199701e04c3fSmrg 199801e04c3fSmrg ctx->blendJIT->insert(std::make_pair(compileState, func)); 199901e04c3fSmrg } 200001e04c3fSmrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, func); 200101e04c3fSmrg } 200201e04c3fSmrg 200301e04c3fSmrg ctx->api.pfnSwrSetBlendState(ctx->swrContext, &blendState); 200401e04c3fSmrg } 200501e04c3fSmrg 200601e04c3fSmrg if (ctx->dirty & SWR_NEW_STIPPLE) { 200701e04c3fSmrg swr_update_poly_stipple(ctx); 200801e04c3fSmrg } 200901e04c3fSmrg 20107ec681f3Smrg if (ctx->dirty & (SWR_NEW_VS | SWR_NEW_TCS | SWR_NEW_TES | SWR_NEW_SO | SWR_NEW_RASTERIZER)) { 201101e04c3fSmrg ctx->vs->soState.rasterizerDisable = 201201e04c3fSmrg ctx->rasterizer->rasterizer_discard; 201301e04c3fSmrg ctx->api.pfnSwrSetSoState(ctx->swrContext, &ctx->vs->soState); 201401e04c3fSmrg 201501e04c3fSmrg pipe_stream_output_info *stream_output = &ctx->vs->pipe.stream_output; 201601e04c3fSmrg 20177ec681f3Smrg for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) { 201801e04c3fSmrg SWR_STREAMOUT_BUFFER buffer = {0}; 20197ec681f3Smrg if (ctx->so_targets[i]) { 20207ec681f3Smrg buffer.enable = true; 20217ec681f3Smrg buffer.pBuffer = 20227ec681f3Smrg (gfxptr_t)(swr_resource_data(ctx->so_targets[i]->buffer) + 20237ec681f3Smrg ctx->so_targets[i]->buffer_offset); 20247ec681f3Smrg buffer.bufferSize = ctx->so_targets[i]->buffer_size >> 2; 20257ec681f3Smrg buffer.pitch = stream_output->stride[i]; 20267ec681f3Smrg buffer.streamOffset = 0; 20277ec681f3Smrg } 202801e04c3fSmrg 202901e04c3fSmrg ctx->api.pfnSwrSetSoBuffers(ctx->swrContext, &buffer, i); 203001e04c3fSmrg } 203101e04c3fSmrg } 203201e04c3fSmrg 20337ec681f3Smrg 203401e04c3fSmrg if (ctx->dirty & (SWR_NEW_CLIP | SWR_NEW_RASTERIZER | SWR_NEW_VS)) { 203501e04c3fSmrg // shader exporting clip distances overrides all user clip planes 203601e04c3fSmrg if (ctx->rasterizer->clip_plane_enable && 20377ec681f3Smrg !swr_get_last_fe(ctx)->num_written_clipdistance) 203801e04c3fSmrg { 203901e04c3fSmrg swr_draw_context *pDC = &ctx->swrDC; 204001e04c3fSmrg memcpy(pDC->userClipPlanes, 204101e04c3fSmrg ctx->clip.ucp, 204201e04c3fSmrg sizeof(pDC->userClipPlanes)); 204301e04c3fSmrg } 204401e04c3fSmrg } 204501e04c3fSmrg 204601e04c3fSmrg // set up backend state 204701e04c3fSmrg SWR_BACKEND_STATE backendState = {0}; 204801e04c3fSmrg if (ctx->gs) { 204901e04c3fSmrg backendState.numAttributes = ctx->gs->info.base.num_outputs - 1; 20507ec681f3Smrg } else 20517ec681f3Smrg if (ctx->tes) { 20527ec681f3Smrg backendState.numAttributes = ctx->tes->info.base.num_outputs - 1; 20537ec681f3Smrg // no case for TCS, because if TCS is active, TES must be active 20547ec681f3Smrg // as well - pipeline stages after tessellation does not support patches 20557ec681f3Smrg } else { 205601e04c3fSmrg backendState.numAttributes = ctx->vs->info.base.num_outputs - 1; 205701e04c3fSmrg if (ctx->fs->info.base.uses_primid) { 205801e04c3fSmrg backendState.numAttributes++; 205901e04c3fSmrg backendState.swizzleEnable = true; 206001e04c3fSmrg for (unsigned i = 0; i < sizeof(backendState.numComponents); i++) { 206101e04c3fSmrg backendState.swizzleMap[i].sourceAttrib = i; 206201e04c3fSmrg } 206301e04c3fSmrg backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].constantSource = 206401e04c3fSmrg SWR_CONSTANT_SOURCE_PRIM_ID; 206501e04c3fSmrg backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].componentOverrideMask = 1; 206601e04c3fSmrg } 206701e04c3fSmrg } 206801e04c3fSmrg if (ctx->rasterizer->sprite_coord_enable) 206901e04c3fSmrg backendState.numAttributes++; 207001e04c3fSmrg 207101e04c3fSmrg backendState.numAttributes = std::min((size_t)backendState.numAttributes, 207201e04c3fSmrg sizeof(backendState.numComponents)); 207301e04c3fSmrg for (unsigned i = 0; i < backendState.numAttributes; i++) 207401e04c3fSmrg backendState.numComponents[i] = 4; 207501e04c3fSmrg backendState.constantInterpolationMask = ctx->fs->constantMask | 207601e04c3fSmrg (ctx->rasterizer->flatshade ? ctx->fs->flatConstantMask : 0); 207701e04c3fSmrg backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask; 207801e04c3fSmrg 20797ec681f3Smrg struct tgsi_shader_info *pLastFE = swr_get_last_fe(ctx); 20807ec681f3Smrg 208101e04c3fSmrg backendState.readRenderTargetArrayIndex = pLastFE->writes_layer; 208201e04c3fSmrg backendState.readViewportArrayIndex = pLastFE->writes_viewport_index; 208301e04c3fSmrg backendState.vertexAttribOffset = VERTEX_ATTRIB_START_SLOT; // TODO: optimize 208401e04c3fSmrg 208501e04c3fSmrg backendState.clipDistanceMask = 20867ec681f3Smrg pLastFE->num_written_clipdistance ? 20877ec681f3Smrg pLastFE->clipdist_writemask & ctx->rasterizer->clip_plane_enable : 208801e04c3fSmrg ctx->rasterizer->clip_plane_enable; 208901e04c3fSmrg 209001e04c3fSmrg backendState.cullDistanceMask = 20917ec681f3Smrg pLastFE->culldist_writemask << pLastFE->num_written_clipdistance; 209201e04c3fSmrg 209301e04c3fSmrg // Assume old layout of SGV, POSITION, CLIPCULL, ATTRIB 209401e04c3fSmrg backendState.vertexClipCullOffset = backendState.vertexAttribOffset - 2; 209501e04c3fSmrg 209601e04c3fSmrg ctx->api.pfnSwrSetBackendState(ctx->swrContext, &backendState); 209701e04c3fSmrg 209801e04c3fSmrg /* Ensure that any in-progress attachment change StoreTiles finish */ 209901e04c3fSmrg if (swr_is_fence_pending(screen->flush_fence)) 210001e04c3fSmrg swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0); 210101e04c3fSmrg 210201e04c3fSmrg /* Finally, update the in-use status of all resources involved in draw */ 210301e04c3fSmrg swr_update_resource_status(pipe, p_draw_info); 210401e04c3fSmrg 210501e04c3fSmrg ctx->dirty = post_update_dirty_flags; 210601e04c3fSmrg} 210701e04c3fSmrg 210801e04c3fSmrg 210901e04c3fSmrgstatic struct pipe_stream_output_target * 211001e04c3fSmrgswr_create_so_target(struct pipe_context *pipe, 211101e04c3fSmrg struct pipe_resource *buffer, 211201e04c3fSmrg unsigned buffer_offset, 211301e04c3fSmrg unsigned buffer_size) 211401e04c3fSmrg{ 211501e04c3fSmrg struct pipe_stream_output_target *target; 211601e04c3fSmrg 211701e04c3fSmrg target = CALLOC_STRUCT(pipe_stream_output_target); 211801e04c3fSmrg if (!target) 211901e04c3fSmrg return NULL; 212001e04c3fSmrg 212101e04c3fSmrg target->context = pipe; 212201e04c3fSmrg target->reference.count = 1; 212301e04c3fSmrg pipe_resource_reference(&target->buffer, buffer); 212401e04c3fSmrg target->buffer_offset = buffer_offset; 212501e04c3fSmrg target->buffer_size = buffer_size; 212601e04c3fSmrg return target; 212701e04c3fSmrg} 212801e04c3fSmrg 212901e04c3fSmrgstatic void 213001e04c3fSmrgswr_destroy_so_target(struct pipe_context *pipe, 213101e04c3fSmrg struct pipe_stream_output_target *target) 213201e04c3fSmrg{ 213301e04c3fSmrg pipe_resource_reference(&target->buffer, NULL); 213401e04c3fSmrg FREE(target); 213501e04c3fSmrg} 213601e04c3fSmrg 213701e04c3fSmrgstatic void 213801e04c3fSmrgswr_set_so_targets(struct pipe_context *pipe, 213901e04c3fSmrg unsigned num_targets, 214001e04c3fSmrg struct pipe_stream_output_target **targets, 214101e04c3fSmrg const unsigned *offsets) 214201e04c3fSmrg{ 214301e04c3fSmrg struct swr_context *swr = swr_context(pipe); 214401e04c3fSmrg uint32_t i; 214501e04c3fSmrg 214601e04c3fSmrg assert(num_targets <= MAX_SO_STREAMS); 214701e04c3fSmrg 214801e04c3fSmrg for (i = 0; i < num_targets; i++) { 214901e04c3fSmrg pipe_so_target_reference( 215001e04c3fSmrg (struct pipe_stream_output_target **)&swr->so_targets[i], 215101e04c3fSmrg targets[i]); 215201e04c3fSmrg } 215301e04c3fSmrg 215401e04c3fSmrg for (/* fall-through */; i < swr->num_so_targets; i++) { 215501e04c3fSmrg pipe_so_target_reference( 215601e04c3fSmrg (struct pipe_stream_output_target **)&swr->so_targets[i], NULL); 215701e04c3fSmrg } 215801e04c3fSmrg 215901e04c3fSmrg swr->num_so_targets = num_targets; 21607ec681f3Smrg swr->swrDC.soPrims = &swr->so_primCounter; 216101e04c3fSmrg 216201e04c3fSmrg swr->dirty |= SWR_NEW_SO; 216301e04c3fSmrg} 216401e04c3fSmrg 21657ec681f3Smrgstatic void 21667ec681f3Smrgswr_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices) 21677ec681f3Smrg{ 21687ec681f3Smrg struct swr_context *swr = swr_context(pipe); 21697ec681f3Smrg 21707ec681f3Smrg swr->patch_vertices = patch_vertices; 21717ec681f3Smrg} 21727ec681f3Smrg 217301e04c3fSmrg 217401e04c3fSmrgvoid 217501e04c3fSmrgswr_state_init(struct pipe_context *pipe) 217601e04c3fSmrg{ 217701e04c3fSmrg pipe->create_blend_state = swr_create_blend_state; 217801e04c3fSmrg pipe->bind_blend_state = swr_bind_blend_state; 217901e04c3fSmrg pipe->delete_blend_state = swr_delete_blend_state; 218001e04c3fSmrg 218101e04c3fSmrg pipe->create_depth_stencil_alpha_state = swr_create_depth_stencil_state; 218201e04c3fSmrg pipe->bind_depth_stencil_alpha_state = swr_bind_depth_stencil_state; 218301e04c3fSmrg pipe->delete_depth_stencil_alpha_state = swr_delete_depth_stencil_state; 218401e04c3fSmrg 218501e04c3fSmrg pipe->create_rasterizer_state = swr_create_rasterizer_state; 218601e04c3fSmrg pipe->bind_rasterizer_state = swr_bind_rasterizer_state; 218701e04c3fSmrg pipe->delete_rasterizer_state = swr_delete_rasterizer_state; 218801e04c3fSmrg 218901e04c3fSmrg pipe->create_sampler_state = swr_create_sampler_state; 219001e04c3fSmrg pipe->bind_sampler_states = swr_bind_sampler_states; 219101e04c3fSmrg pipe->delete_sampler_state = swr_delete_sampler_state; 219201e04c3fSmrg 219301e04c3fSmrg pipe->create_sampler_view = swr_create_sampler_view; 219401e04c3fSmrg pipe->set_sampler_views = swr_set_sampler_views; 219501e04c3fSmrg pipe->sampler_view_destroy = swr_sampler_view_destroy; 219601e04c3fSmrg 219701e04c3fSmrg pipe->create_vs_state = swr_create_vs_state; 219801e04c3fSmrg pipe->bind_vs_state = swr_bind_vs_state; 219901e04c3fSmrg pipe->delete_vs_state = swr_delete_vs_state; 220001e04c3fSmrg 220101e04c3fSmrg pipe->create_fs_state = swr_create_fs_state; 220201e04c3fSmrg pipe->bind_fs_state = swr_bind_fs_state; 220301e04c3fSmrg pipe->delete_fs_state = swr_delete_fs_state; 220401e04c3fSmrg 220501e04c3fSmrg pipe->create_gs_state = swr_create_gs_state; 220601e04c3fSmrg pipe->bind_gs_state = swr_bind_gs_state; 220701e04c3fSmrg pipe->delete_gs_state = swr_delete_gs_state; 220801e04c3fSmrg 22097ec681f3Smrg pipe->create_tcs_state = swr_create_tcs_state; 22107ec681f3Smrg pipe->bind_tcs_state = swr_bind_tcs_state; 22117ec681f3Smrg pipe->delete_tcs_state = swr_delete_tcs_state; 22127ec681f3Smrg 22137ec681f3Smrg pipe->create_tes_state = swr_create_tes_state; 22147ec681f3Smrg pipe->bind_tes_state = swr_bind_tes_state; 22157ec681f3Smrg pipe->delete_tes_state = swr_delete_tes_state; 22167ec681f3Smrg 221701e04c3fSmrg pipe->set_constant_buffer = swr_set_constant_buffer; 221801e04c3fSmrg 221901e04c3fSmrg pipe->create_vertex_elements_state = swr_create_vertex_elements_state; 222001e04c3fSmrg pipe->bind_vertex_elements_state = swr_bind_vertex_elements_state; 222101e04c3fSmrg pipe->delete_vertex_elements_state = swr_delete_vertex_elements_state; 222201e04c3fSmrg 222301e04c3fSmrg pipe->set_vertex_buffers = swr_set_vertex_buffers; 222401e04c3fSmrg 222501e04c3fSmrg pipe->set_polygon_stipple = swr_set_polygon_stipple; 222601e04c3fSmrg pipe->set_clip_state = swr_set_clip_state; 222701e04c3fSmrg pipe->set_scissor_states = swr_set_scissor_states; 222801e04c3fSmrg pipe->set_viewport_states = swr_set_viewport_states; 222901e04c3fSmrg 223001e04c3fSmrg pipe->set_framebuffer_state = swr_set_framebuffer_state; 223101e04c3fSmrg 223201e04c3fSmrg pipe->set_blend_color = swr_set_blend_color; 223301e04c3fSmrg pipe->set_stencil_ref = swr_set_stencil_ref; 223401e04c3fSmrg 223501e04c3fSmrg pipe->set_sample_mask = swr_set_sample_mask; 223601e04c3fSmrg pipe->get_sample_position = swr_get_sample_position; 223701e04c3fSmrg 223801e04c3fSmrg pipe->create_stream_output_target = swr_create_so_target; 223901e04c3fSmrg pipe->stream_output_target_destroy = swr_destroy_so_target; 224001e04c3fSmrg pipe->set_stream_output_targets = swr_set_so_targets; 22417ec681f3Smrg 22427ec681f3Smrg pipe->set_patch_vertices = swr_set_patch_vertices; 224301e04c3fSmrg} 2244