1b8e80941Smrg/**************************************************************************** 2b8e80941Smrg * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg ***************************************************************************/ 23b8e80941Smrg 24b8e80941Smrg// llvm redefines DEBUG 25b8e80941Smrg#pragma push_macro("DEBUG") 26b8e80941Smrg#undef DEBUG 27b8e80941Smrg#include "JitManager.h" 28b8e80941Smrg#pragma pop_macro("DEBUG") 29b8e80941Smrg 30b8e80941Smrg#include "common/os.h" 31b8e80941Smrg#include "jit_api.h" 32b8e80941Smrg#include "gen_state_llvm.h" 33b8e80941Smrg#include "core/multisample.h" 34b8e80941Smrg#include "core/state_funcs.h" 35b8e80941Smrg 36b8e80941Smrg#include "gallivm/lp_bld_tgsi.h" 37b8e80941Smrg#include "util/u_format.h" 38b8e80941Smrg 39b8e80941Smrg#include "util/u_memory.h" 40b8e80941Smrg#include "util/u_inlines.h" 41b8e80941Smrg#include "util/u_helpers.h" 42b8e80941Smrg#include "util/u_framebuffer.h" 43b8e80941Smrg#include "util/u_viewport.h" 44b8e80941Smrg#include "util/u_prim.h" 45b8e80941Smrg 46b8e80941Smrg#include "swr_state.h" 47b8e80941Smrg#include "swr_context.h" 48b8e80941Smrg#include "gen_swr_context_llvm.h" 49b8e80941Smrg#include "swr_screen.h" 50b8e80941Smrg#include "swr_resource.h" 51b8e80941Smrg#include "swr_tex_sample.h" 52b8e80941Smrg#include "swr_scratch.h" 53b8e80941Smrg#include "swr_shader.h" 54b8e80941Smrg#include "swr_fence.h" 55b8e80941Smrg 56b8e80941Smrg/* These should be pulled out into separate files as necessary 57b8e80941Smrg * Just initializing everything here to get going. */ 58b8e80941Smrg 59b8e80941Smrgstatic void * 60b8e80941Smrgswr_create_blend_state(struct pipe_context *pipe, 61b8e80941Smrg const struct pipe_blend_state *blend) 62b8e80941Smrg{ 63b8e80941Smrg struct swr_blend_state *state = CALLOC_STRUCT(swr_blend_state); 64b8e80941Smrg 65b8e80941Smrg memcpy(&state->pipe, blend, sizeof(*blend)); 66b8e80941Smrg 67b8e80941Smrg struct pipe_blend_state *pipe_blend = &state->pipe; 68b8e80941Smrg 69b8e80941Smrg for (int target = 0; 70b8e80941Smrg target < std::min(SWR_NUM_RENDERTARGETS, PIPE_MAX_COLOR_BUFS); 71b8e80941Smrg target++) { 72b8e80941Smrg 73b8e80941Smrg struct pipe_rt_blend_state *rt_blend = &pipe_blend->rt[target]; 74b8e80941Smrg SWR_RENDER_TARGET_BLEND_STATE &blendState = 75b8e80941Smrg state->blendState.renderTarget[target]; 76b8e80941Smrg RENDER_TARGET_BLEND_COMPILE_STATE &compileState = 77b8e80941Smrg state->compileState[target]; 78b8e80941Smrg 79b8e80941Smrg if (target != 0 && !pipe_blend->independent_blend_enable) { 80b8e80941Smrg memcpy(&compileState, 81b8e80941Smrg &state->compileState[0], 82b8e80941Smrg sizeof(RENDER_TARGET_BLEND_COMPILE_STATE)); 83b8e80941Smrg continue; 84b8e80941Smrg } 85b8e80941Smrg 86b8e80941Smrg compileState.blendEnable = rt_blend->blend_enable; 87b8e80941Smrg if (compileState.blendEnable) { 88b8e80941Smrg compileState.sourceAlphaBlendFactor = 89b8e80941Smrg swr_convert_blend_factor(rt_blend->alpha_src_factor); 90b8e80941Smrg compileState.destAlphaBlendFactor = 91b8e80941Smrg swr_convert_blend_factor(rt_blend->alpha_dst_factor); 92b8e80941Smrg compileState.sourceBlendFactor = 93b8e80941Smrg swr_convert_blend_factor(rt_blend->rgb_src_factor); 94b8e80941Smrg compileState.destBlendFactor = 95b8e80941Smrg swr_convert_blend_factor(rt_blend->rgb_dst_factor); 96b8e80941Smrg 97b8e80941Smrg compileState.colorBlendFunc = 98b8e80941Smrg swr_convert_blend_func(rt_blend->rgb_func); 99b8e80941Smrg compileState.alphaBlendFunc = 100b8e80941Smrg swr_convert_blend_func(rt_blend->alpha_func); 101b8e80941Smrg } 102b8e80941Smrg compileState.logicOpEnable = state->pipe.logicop_enable; 103b8e80941Smrg if (compileState.logicOpEnable) { 104b8e80941Smrg compileState.logicOpFunc = 105b8e80941Smrg swr_convert_logic_op(state->pipe.logicop_func); 106b8e80941Smrg } 107b8e80941Smrg 108b8e80941Smrg blendState.writeDisableRed = 109b8e80941Smrg (rt_blend->colormask & PIPE_MASK_R) ? 0 : 1; 110b8e80941Smrg blendState.writeDisableGreen = 111b8e80941Smrg (rt_blend->colormask & PIPE_MASK_G) ? 0 : 1; 112b8e80941Smrg blendState.writeDisableBlue = 113b8e80941Smrg (rt_blend->colormask & PIPE_MASK_B) ? 0 : 1; 114b8e80941Smrg blendState.writeDisableAlpha = 115b8e80941Smrg (rt_blend->colormask & PIPE_MASK_A) ? 0 : 1; 116b8e80941Smrg 117b8e80941Smrg if (rt_blend->colormask == 0) 118b8e80941Smrg compileState.blendEnable = false; 119b8e80941Smrg } 120b8e80941Smrg 121b8e80941Smrg return state; 122b8e80941Smrg} 123b8e80941Smrg 124b8e80941Smrgstatic void 125b8e80941Smrgswr_bind_blend_state(struct pipe_context *pipe, void *blend) 126b8e80941Smrg{ 127b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 128b8e80941Smrg 129b8e80941Smrg if (ctx->blend == blend) 130b8e80941Smrg return; 131b8e80941Smrg 132b8e80941Smrg ctx->blend = (swr_blend_state *)blend; 133b8e80941Smrg 134b8e80941Smrg ctx->dirty |= SWR_NEW_BLEND; 135b8e80941Smrg} 136b8e80941Smrg 137b8e80941Smrgstatic void 138b8e80941Smrgswr_delete_blend_state(struct pipe_context *pipe, void *blend) 139b8e80941Smrg{ 140b8e80941Smrg FREE(blend); 141b8e80941Smrg} 142b8e80941Smrg 143b8e80941Smrgstatic void 144b8e80941Smrgswr_set_blend_color(struct pipe_context *pipe, 145b8e80941Smrg const struct pipe_blend_color *color) 146b8e80941Smrg{ 147b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 148b8e80941Smrg 149b8e80941Smrg ctx->blend_color = *color; 150b8e80941Smrg 151b8e80941Smrg ctx->dirty |= SWR_NEW_BLEND; 152b8e80941Smrg} 153b8e80941Smrg 154b8e80941Smrgstatic void 155b8e80941Smrgswr_set_stencil_ref(struct pipe_context *pipe, 156b8e80941Smrg const struct pipe_stencil_ref *ref) 157b8e80941Smrg{ 158b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 159b8e80941Smrg 160b8e80941Smrg ctx->stencil_ref = *ref; 161b8e80941Smrg 162b8e80941Smrg ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA; 163b8e80941Smrg} 164b8e80941Smrg 165b8e80941Smrgstatic void * 166b8e80941Smrgswr_create_depth_stencil_state( 167b8e80941Smrg struct pipe_context *pipe, 168b8e80941Smrg const struct pipe_depth_stencil_alpha_state *depth_stencil) 169b8e80941Smrg{ 170b8e80941Smrg struct pipe_depth_stencil_alpha_state *state; 171b8e80941Smrg 172b8e80941Smrg state = (pipe_depth_stencil_alpha_state *)mem_dup(depth_stencil, 173b8e80941Smrg sizeof *depth_stencil); 174b8e80941Smrg 175b8e80941Smrg return state; 176b8e80941Smrg} 177b8e80941Smrg 178b8e80941Smrgstatic void 179b8e80941Smrgswr_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) 180b8e80941Smrg{ 181b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 182b8e80941Smrg 183b8e80941Smrg if (ctx->depth_stencil == (pipe_depth_stencil_alpha_state *)depth_stencil) 184b8e80941Smrg return; 185b8e80941Smrg 186b8e80941Smrg ctx->depth_stencil = (pipe_depth_stencil_alpha_state *)depth_stencil; 187b8e80941Smrg 188b8e80941Smrg ctx->dirty |= SWR_NEW_DEPTH_STENCIL_ALPHA; 189b8e80941Smrg} 190b8e80941Smrg 191b8e80941Smrgstatic void 192b8e80941Smrgswr_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) 193b8e80941Smrg{ 194b8e80941Smrg FREE(depth); 195b8e80941Smrg} 196b8e80941Smrg 197b8e80941Smrg 198b8e80941Smrgstatic void * 199b8e80941Smrgswr_create_rasterizer_state(struct pipe_context *pipe, 200b8e80941Smrg const struct pipe_rasterizer_state *rast) 201b8e80941Smrg{ 202b8e80941Smrg struct pipe_rasterizer_state *state; 203b8e80941Smrg state = (pipe_rasterizer_state *)mem_dup(rast, sizeof *rast); 204b8e80941Smrg 205b8e80941Smrg return state; 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrgstatic void 209b8e80941Smrgswr_bind_rasterizer_state(struct pipe_context *pipe, void *handle) 210b8e80941Smrg{ 211b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 212b8e80941Smrg const struct pipe_rasterizer_state *rasterizer = 213b8e80941Smrg (const struct pipe_rasterizer_state *)handle; 214b8e80941Smrg 215b8e80941Smrg if (ctx->rasterizer == (pipe_rasterizer_state *)rasterizer) 216b8e80941Smrg return; 217b8e80941Smrg 218b8e80941Smrg ctx->rasterizer = (pipe_rasterizer_state *)rasterizer; 219b8e80941Smrg 220b8e80941Smrg ctx->dirty |= SWR_NEW_RASTERIZER; 221b8e80941Smrg} 222b8e80941Smrg 223b8e80941Smrgstatic void 224b8e80941Smrgswr_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer) 225b8e80941Smrg{ 226b8e80941Smrg FREE(rasterizer); 227b8e80941Smrg} 228b8e80941Smrg 229b8e80941Smrg 230b8e80941Smrgstatic void * 231b8e80941Smrgswr_create_sampler_state(struct pipe_context *pipe, 232b8e80941Smrg const struct pipe_sampler_state *sampler) 233b8e80941Smrg{ 234b8e80941Smrg struct pipe_sampler_state *state = 235b8e80941Smrg (pipe_sampler_state *)mem_dup(sampler, sizeof *sampler); 236b8e80941Smrg 237b8e80941Smrg return state; 238b8e80941Smrg} 239b8e80941Smrg 240b8e80941Smrgstatic void 241b8e80941Smrgswr_bind_sampler_states(struct pipe_context *pipe, 242b8e80941Smrg enum pipe_shader_type shader, 243b8e80941Smrg unsigned start, 244b8e80941Smrg unsigned num, 245b8e80941Smrg void **samplers) 246b8e80941Smrg{ 247b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 248b8e80941Smrg unsigned i; 249b8e80941Smrg 250b8e80941Smrg assert(shader < PIPE_SHADER_TYPES); 251b8e80941Smrg assert(start + num <= ARRAY_SIZE(ctx->samplers[shader])); 252b8e80941Smrg 253b8e80941Smrg /* set the new samplers */ 254b8e80941Smrg ctx->num_samplers[shader] = num; 255b8e80941Smrg for (i = 0; i < num; i++) { 256b8e80941Smrg ctx->samplers[shader][start + i] = (pipe_sampler_state *)samplers[i]; 257b8e80941Smrg } 258b8e80941Smrg 259b8e80941Smrg ctx->dirty |= SWR_NEW_SAMPLER; 260b8e80941Smrg} 261b8e80941Smrg 262b8e80941Smrgstatic void 263b8e80941Smrgswr_delete_sampler_state(struct pipe_context *pipe, void *sampler) 264b8e80941Smrg{ 265b8e80941Smrg FREE(sampler); 266b8e80941Smrg} 267b8e80941Smrg 268b8e80941Smrg 269b8e80941Smrgstatic struct pipe_sampler_view * 270b8e80941Smrgswr_create_sampler_view(struct pipe_context *pipe, 271b8e80941Smrg struct pipe_resource *texture, 272b8e80941Smrg const struct pipe_sampler_view *templ) 273b8e80941Smrg{ 274b8e80941Smrg struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); 275b8e80941Smrg 276b8e80941Smrg if (view) { 277b8e80941Smrg *view = *templ; 278b8e80941Smrg view->reference.count = 1; 279b8e80941Smrg view->texture = NULL; 280b8e80941Smrg pipe_resource_reference(&view->texture, texture); 281b8e80941Smrg view->context = pipe; 282b8e80941Smrg } 283b8e80941Smrg 284b8e80941Smrg return view; 285b8e80941Smrg} 286b8e80941Smrg 287b8e80941Smrgstatic void 288b8e80941Smrgswr_set_sampler_views(struct pipe_context *pipe, 289b8e80941Smrg enum pipe_shader_type shader, 290b8e80941Smrg unsigned start, 291b8e80941Smrg unsigned num, 292b8e80941Smrg struct pipe_sampler_view **views) 293b8e80941Smrg{ 294b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 295b8e80941Smrg uint i; 296b8e80941Smrg 297b8e80941Smrg assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); 298b8e80941Smrg 299b8e80941Smrg assert(shader < PIPE_SHADER_TYPES); 300b8e80941Smrg assert(start + num <= ARRAY_SIZE(ctx->sampler_views[shader])); 301b8e80941Smrg 302b8e80941Smrg /* set the new sampler views */ 303b8e80941Smrg ctx->num_sampler_views[shader] = num; 304b8e80941Smrg for (i = 0; i < num; i++) { 305b8e80941Smrg pipe_sampler_view_reference(&ctx->sampler_views[shader][start + i], 306b8e80941Smrg views[i]); 307b8e80941Smrg } 308b8e80941Smrg 309b8e80941Smrg ctx->dirty |= SWR_NEW_SAMPLER_VIEW; 310b8e80941Smrg} 311b8e80941Smrg 312b8e80941Smrgstatic void 313b8e80941Smrgswr_sampler_view_destroy(struct pipe_context *pipe, 314b8e80941Smrg struct pipe_sampler_view *view) 315b8e80941Smrg{ 316b8e80941Smrg pipe_resource_reference(&view->texture, NULL); 317b8e80941Smrg FREE(view); 318b8e80941Smrg} 319b8e80941Smrg 320b8e80941Smrgstatic void * 321b8e80941Smrgswr_create_vs_state(struct pipe_context *pipe, 322b8e80941Smrg const struct pipe_shader_state *vs) 323b8e80941Smrg{ 324b8e80941Smrg struct swr_vertex_shader *swr_vs = new swr_vertex_shader; 325b8e80941Smrg if (!swr_vs) 326b8e80941Smrg return NULL; 327b8e80941Smrg 328b8e80941Smrg swr_vs->pipe.tokens = tgsi_dup_tokens(vs->tokens); 329b8e80941Smrg swr_vs->pipe.stream_output = vs->stream_output; 330b8e80941Smrg 331b8e80941Smrg lp_build_tgsi_info(vs->tokens, &swr_vs->info); 332b8e80941Smrg 333b8e80941Smrg swr_vs->soState = {0}; 334b8e80941Smrg 335b8e80941Smrg if (swr_vs->pipe.stream_output.num_outputs) { 336b8e80941Smrg pipe_stream_output_info *stream_output = &swr_vs->pipe.stream_output; 337b8e80941Smrg 338b8e80941Smrg swr_vs->soState.soEnable = true; 339b8e80941Smrg // soState.rasterizerDisable set on state dirty 340b8e80941Smrg // soState.streamToRasterizer not used 341b8e80941Smrg 342b8e80941Smrg for (uint32_t i = 0; i < stream_output->num_outputs; i++) { 343b8e80941Smrg unsigned attrib_slot = stream_output->output[i].register_index; 344b8e80941Smrg attrib_slot = swr_so_adjust_attrib(attrib_slot, swr_vs); 345b8e80941Smrg swr_vs->soState.streamMasks[stream_output->output[i].stream] |= 346b8e80941Smrg (1 << attrib_slot); 347b8e80941Smrg } 348b8e80941Smrg for (uint32_t i = 0; i < MAX_SO_STREAMS; i++) { 349b8e80941Smrg swr_vs->soState.streamNumEntries[i] = 350b8e80941Smrg _mm_popcnt_u32(swr_vs->soState.streamMasks[i]); 351b8e80941Smrg } 352b8e80941Smrg } 353b8e80941Smrg 354b8e80941Smrg return swr_vs; 355b8e80941Smrg} 356b8e80941Smrg 357b8e80941Smrgstatic void 358b8e80941Smrgswr_bind_vs_state(struct pipe_context *pipe, void *vs) 359b8e80941Smrg{ 360b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 361b8e80941Smrg 362b8e80941Smrg if (ctx->vs == vs) 363b8e80941Smrg return; 364b8e80941Smrg 365b8e80941Smrg ctx->vs = (swr_vertex_shader *)vs; 366b8e80941Smrg ctx->dirty |= SWR_NEW_VS; 367b8e80941Smrg} 368b8e80941Smrg 369b8e80941Smrgstatic void 370b8e80941Smrgswr_delete_vs_state(struct pipe_context *pipe, void *vs) 371b8e80941Smrg{ 372b8e80941Smrg struct swr_vertex_shader *swr_vs = (swr_vertex_shader *)vs; 373b8e80941Smrg FREE((void *)swr_vs->pipe.tokens); 374b8e80941Smrg struct swr_screen *screen = swr_screen(pipe->screen); 375b8e80941Smrg 376b8e80941Smrg /* Defer deletion of vs state */ 377b8e80941Smrg swr_fence_work_delete_vs(screen->flush_fence, swr_vs); 378b8e80941Smrg} 379b8e80941Smrg 380b8e80941Smrgstatic void * 381b8e80941Smrgswr_create_fs_state(struct pipe_context *pipe, 382b8e80941Smrg const struct pipe_shader_state *fs) 383b8e80941Smrg{ 384b8e80941Smrg struct swr_fragment_shader *swr_fs = new swr_fragment_shader; 385b8e80941Smrg if (!swr_fs) 386b8e80941Smrg return NULL; 387b8e80941Smrg 388b8e80941Smrg swr_fs->pipe.tokens = tgsi_dup_tokens(fs->tokens); 389b8e80941Smrg 390b8e80941Smrg lp_build_tgsi_info(fs->tokens, &swr_fs->info); 391b8e80941Smrg 392b8e80941Smrg return swr_fs; 393b8e80941Smrg} 394b8e80941Smrg 395b8e80941Smrg 396b8e80941Smrgstatic void 397b8e80941Smrgswr_bind_fs_state(struct pipe_context *pipe, void *fs) 398b8e80941Smrg{ 399b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 400b8e80941Smrg 401b8e80941Smrg if (ctx->fs == fs) 402b8e80941Smrg return; 403b8e80941Smrg 404b8e80941Smrg ctx->fs = (swr_fragment_shader *)fs; 405b8e80941Smrg ctx->dirty |= SWR_NEW_FS; 406b8e80941Smrg} 407b8e80941Smrg 408b8e80941Smrgstatic void 409b8e80941Smrgswr_delete_fs_state(struct pipe_context *pipe, void *fs) 410b8e80941Smrg{ 411b8e80941Smrg struct swr_fragment_shader *swr_fs = (swr_fragment_shader *)fs; 412b8e80941Smrg FREE((void *)swr_fs->pipe.tokens); 413b8e80941Smrg struct swr_screen *screen = swr_screen(pipe->screen); 414b8e80941Smrg 415b8e80941Smrg /* Defer deleton of fs state */ 416b8e80941Smrg swr_fence_work_delete_fs(screen->flush_fence, swr_fs); 417b8e80941Smrg} 418b8e80941Smrg 419b8e80941Smrgstatic void * 420b8e80941Smrgswr_create_gs_state(struct pipe_context *pipe, 421b8e80941Smrg const struct pipe_shader_state *gs) 422b8e80941Smrg{ 423b8e80941Smrg struct swr_geometry_shader *swr_gs = new swr_geometry_shader; 424b8e80941Smrg if (!swr_gs) 425b8e80941Smrg return NULL; 426b8e80941Smrg 427b8e80941Smrg swr_gs->pipe.tokens = tgsi_dup_tokens(gs->tokens); 428b8e80941Smrg 429b8e80941Smrg lp_build_tgsi_info(gs->tokens, &swr_gs->info); 430b8e80941Smrg 431b8e80941Smrg return swr_gs; 432b8e80941Smrg} 433b8e80941Smrg 434b8e80941Smrg 435b8e80941Smrgstatic void 436b8e80941Smrgswr_bind_gs_state(struct pipe_context *pipe, void *gs) 437b8e80941Smrg{ 438b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 439b8e80941Smrg 440b8e80941Smrg if (ctx->gs == gs) 441b8e80941Smrg return; 442b8e80941Smrg 443b8e80941Smrg ctx->gs = (swr_geometry_shader *)gs; 444b8e80941Smrg ctx->dirty |= SWR_NEW_GS; 445b8e80941Smrg} 446b8e80941Smrg 447b8e80941Smrgstatic void 448b8e80941Smrgswr_delete_gs_state(struct pipe_context *pipe, void *gs) 449b8e80941Smrg{ 450b8e80941Smrg struct swr_geometry_shader *swr_gs = (swr_geometry_shader *)gs; 451b8e80941Smrg FREE((void *)swr_gs->pipe.tokens); 452b8e80941Smrg struct swr_screen *screen = swr_screen(pipe->screen); 453b8e80941Smrg 454b8e80941Smrg /* Defer deleton of fs state */ 455b8e80941Smrg swr_fence_work_delete_gs(screen->flush_fence, swr_gs); 456b8e80941Smrg} 457b8e80941Smrg 458b8e80941Smrgstatic void 459b8e80941Smrgswr_set_constant_buffer(struct pipe_context *pipe, 460b8e80941Smrg enum pipe_shader_type shader, 461b8e80941Smrg uint index, 462b8e80941Smrg const struct pipe_constant_buffer *cb) 463b8e80941Smrg{ 464b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 465b8e80941Smrg struct pipe_resource *constants = cb ? cb->buffer : NULL; 466b8e80941Smrg 467b8e80941Smrg assert(shader < PIPE_SHADER_TYPES); 468b8e80941Smrg assert(index < ARRAY_SIZE(ctx->constants[shader])); 469b8e80941Smrg 470b8e80941Smrg /* note: reference counting */ 471b8e80941Smrg util_copy_constant_buffer(&ctx->constants[shader][index], cb); 472b8e80941Smrg 473b8e80941Smrg if (shader == PIPE_SHADER_VERTEX) { 474b8e80941Smrg ctx->dirty |= SWR_NEW_VSCONSTANTS; 475b8e80941Smrg } else if (shader == PIPE_SHADER_FRAGMENT) { 476b8e80941Smrg ctx->dirty |= SWR_NEW_FSCONSTANTS; 477b8e80941Smrg } else if (shader == PIPE_SHADER_GEOMETRY) { 478b8e80941Smrg ctx->dirty |= SWR_NEW_GSCONSTANTS; 479b8e80941Smrg } 480b8e80941Smrg 481b8e80941Smrg if (cb && cb->user_buffer) { 482b8e80941Smrg pipe_resource_reference(&constants, NULL); 483b8e80941Smrg } 484b8e80941Smrg} 485b8e80941Smrg 486b8e80941Smrg 487b8e80941Smrgstatic void * 488b8e80941Smrgswr_create_vertex_elements_state(struct pipe_context *pipe, 489b8e80941Smrg unsigned num_elements, 490b8e80941Smrg const struct pipe_vertex_element *attribs) 491b8e80941Smrg{ 492b8e80941Smrg struct swr_vertex_element_state *velems; 493b8e80941Smrg assert(num_elements <= PIPE_MAX_ATTRIBS); 494b8e80941Smrg velems = new swr_vertex_element_state; 495b8e80941Smrg if (velems) { 496b8e80941Smrg memset(&velems->fsState, 0, sizeof(velems->fsState)); 497b8e80941Smrg velems->fsState.bVertexIDOffsetEnable = true; 498b8e80941Smrg velems->fsState.numAttribs = num_elements; 499b8e80941Smrg for (unsigned i = 0; i < num_elements; i++) { 500b8e80941Smrg // XXX: we should do this keyed on the VS usage info 501b8e80941Smrg 502b8e80941Smrg const struct util_format_description *desc = 503b8e80941Smrg util_format_description(attribs[i].src_format); 504b8e80941Smrg 505b8e80941Smrg velems->fsState.layout[i].AlignedByteOffset = attribs[i].src_offset; 506b8e80941Smrg velems->fsState.layout[i].Format = 507b8e80941Smrg mesa_to_swr_format(attribs[i].src_format); 508b8e80941Smrg velems->fsState.layout[i].StreamIndex = 509b8e80941Smrg attribs[i].vertex_buffer_index; 510b8e80941Smrg velems->fsState.layout[i].InstanceEnable = 511b8e80941Smrg attribs[i].instance_divisor != 0; 512b8e80941Smrg velems->fsState.layout[i].ComponentControl0 = 513b8e80941Smrg desc->channel[0].type != UTIL_FORMAT_TYPE_VOID 514b8e80941Smrg ? ComponentControl::StoreSrc 515b8e80941Smrg : ComponentControl::Store0; 516b8e80941Smrg velems->fsState.layout[i].ComponentControl1 = 517b8e80941Smrg desc->channel[1].type != UTIL_FORMAT_TYPE_VOID 518b8e80941Smrg ? ComponentControl::StoreSrc 519b8e80941Smrg : ComponentControl::Store0; 520b8e80941Smrg velems->fsState.layout[i].ComponentControl2 = 521b8e80941Smrg desc->channel[2].type != UTIL_FORMAT_TYPE_VOID 522b8e80941Smrg ? ComponentControl::StoreSrc 523b8e80941Smrg : ComponentControl::Store0; 524b8e80941Smrg velems->fsState.layout[i].ComponentControl3 = 525b8e80941Smrg desc->channel[3].type != UTIL_FORMAT_TYPE_VOID 526b8e80941Smrg ? ComponentControl::StoreSrc 527b8e80941Smrg : ComponentControl::Store1Fp; 528b8e80941Smrg velems->fsState.layout[i].ComponentPacking = ComponentEnable::XYZW; 529b8e80941Smrg velems->fsState.layout[i].InstanceAdvancementState = 530b8e80941Smrg attribs[i].instance_divisor; 531b8e80941Smrg 532b8e80941Smrg /* Calculate the pitch of each stream */ 533b8e80941Smrg const SWR_FORMAT_INFO &swr_desc = GetFormatInfo( 534b8e80941Smrg mesa_to_swr_format(attribs[i].src_format)); 535b8e80941Smrg velems->stream_pitch[attribs[i].vertex_buffer_index] += swr_desc.Bpp; 536b8e80941Smrg 537b8e80941Smrg if (attribs[i].instance_divisor != 0) { 538b8e80941Smrg velems->instanced_bufs |= 1U << attribs[i].vertex_buffer_index; 539b8e80941Smrg uint32_t *min_instance_div = 540b8e80941Smrg &velems->min_instance_div[attribs[i].vertex_buffer_index]; 541b8e80941Smrg if (!*min_instance_div || 542b8e80941Smrg attribs[i].instance_divisor < *min_instance_div) 543b8e80941Smrg *min_instance_div = attribs[i].instance_divisor; 544b8e80941Smrg } 545b8e80941Smrg } 546b8e80941Smrg } 547b8e80941Smrg 548b8e80941Smrg return velems; 549b8e80941Smrg} 550b8e80941Smrg 551b8e80941Smrgstatic void 552b8e80941Smrgswr_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) 553b8e80941Smrg{ 554b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 555b8e80941Smrg struct swr_vertex_element_state *swr_velems = 556b8e80941Smrg (struct swr_vertex_element_state *)velems; 557b8e80941Smrg 558b8e80941Smrg ctx->velems = swr_velems; 559b8e80941Smrg ctx->dirty |= SWR_NEW_VERTEX; 560b8e80941Smrg} 561b8e80941Smrg 562b8e80941Smrgstatic void 563b8e80941Smrgswr_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) 564b8e80941Smrg{ 565b8e80941Smrg struct swr_vertex_element_state *swr_velems = 566b8e80941Smrg (struct swr_vertex_element_state *) velems; 567b8e80941Smrg /* XXX Need to destroy fetch shader? */ 568b8e80941Smrg delete swr_velems; 569b8e80941Smrg} 570b8e80941Smrg 571b8e80941Smrg 572b8e80941Smrgstatic void 573b8e80941Smrgswr_set_vertex_buffers(struct pipe_context *pipe, 574b8e80941Smrg unsigned start_slot, 575b8e80941Smrg unsigned num_elements, 576b8e80941Smrg const struct pipe_vertex_buffer *buffers) 577b8e80941Smrg{ 578b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 579b8e80941Smrg 580b8e80941Smrg assert(num_elements <= PIPE_MAX_ATTRIBS); 581b8e80941Smrg 582b8e80941Smrg util_set_vertex_buffers_count(ctx->vertex_buffer, 583b8e80941Smrg &ctx->num_vertex_buffers, 584b8e80941Smrg buffers, 585b8e80941Smrg start_slot, 586b8e80941Smrg num_elements); 587b8e80941Smrg 588b8e80941Smrg ctx->dirty |= SWR_NEW_VERTEX; 589b8e80941Smrg} 590b8e80941Smrg 591b8e80941Smrg 592b8e80941Smrgstatic void 593b8e80941Smrgswr_set_polygon_stipple(struct pipe_context *pipe, 594b8e80941Smrg const struct pipe_poly_stipple *stipple) 595b8e80941Smrg{ 596b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 597b8e80941Smrg 598b8e80941Smrg ctx->poly_stipple.pipe = *stipple; /* struct copy */ 599b8e80941Smrg ctx->dirty |= SWR_NEW_STIPPLE; 600b8e80941Smrg} 601b8e80941Smrg 602b8e80941Smrgstatic void 603b8e80941Smrgswr_set_clip_state(struct pipe_context *pipe, 604b8e80941Smrg const struct pipe_clip_state *clip) 605b8e80941Smrg{ 606b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 607b8e80941Smrg 608b8e80941Smrg ctx->clip = *clip; 609b8e80941Smrg /* XXX Unimplemented, but prevents crash */ 610b8e80941Smrg 611b8e80941Smrg ctx->dirty |= SWR_NEW_CLIP; 612b8e80941Smrg} 613b8e80941Smrg 614b8e80941Smrg 615b8e80941Smrgstatic void 616b8e80941Smrgswr_set_scissor_states(struct pipe_context *pipe, 617b8e80941Smrg unsigned start_slot, 618b8e80941Smrg unsigned num_viewports, 619b8e80941Smrg const struct pipe_scissor_state *scissor) 620b8e80941Smrg{ 621b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 622b8e80941Smrg 623b8e80941Smrg ctx->scissor = *scissor; 624b8e80941Smrg ctx->swr_scissor.xmin = scissor->minx; 625b8e80941Smrg ctx->swr_scissor.xmax = scissor->maxx; 626b8e80941Smrg ctx->swr_scissor.ymin = scissor->miny; 627b8e80941Smrg ctx->swr_scissor.ymax = scissor->maxy; 628b8e80941Smrg ctx->dirty |= SWR_NEW_SCISSOR; 629b8e80941Smrg} 630b8e80941Smrg 631b8e80941Smrgstatic void 632b8e80941Smrgswr_set_viewport_states(struct pipe_context *pipe, 633b8e80941Smrg unsigned start_slot, 634b8e80941Smrg unsigned num_viewports, 635b8e80941Smrg const struct pipe_viewport_state *vpt) 636b8e80941Smrg{ 637b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 638b8e80941Smrg 639b8e80941Smrg ctx->viewport = *vpt; 640b8e80941Smrg ctx->dirty |= SWR_NEW_VIEWPORT; 641b8e80941Smrg} 642b8e80941Smrg 643b8e80941Smrg 644b8e80941Smrgstatic void 645b8e80941Smrgswr_set_framebuffer_state(struct pipe_context *pipe, 646b8e80941Smrg const struct pipe_framebuffer_state *fb) 647b8e80941Smrg{ 648b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 649b8e80941Smrg 650b8e80941Smrg boolean changed = !util_framebuffer_state_equal(&ctx->framebuffer, fb); 651b8e80941Smrg 652b8e80941Smrg assert(fb->width <= KNOB_GUARDBAND_WIDTH); 653b8e80941Smrg assert(fb->height <= KNOB_GUARDBAND_HEIGHT); 654b8e80941Smrg 655b8e80941Smrg if (changed) { 656b8e80941Smrg util_copy_framebuffer_state(&ctx->framebuffer, fb); 657b8e80941Smrg 658b8e80941Smrg /* 0 and 1 both indicate no msaa. Core doesn't understand 0 samples */ 659b8e80941Smrg ctx->framebuffer.samples = std::max((ubyte)1, ctx->framebuffer.samples); 660b8e80941Smrg 661b8e80941Smrg ctx->dirty |= SWR_NEW_FRAMEBUFFER; 662b8e80941Smrg } 663b8e80941Smrg} 664b8e80941Smrg 665b8e80941Smrg 666b8e80941Smrgstatic void 667b8e80941Smrgswr_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) 668b8e80941Smrg{ 669b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 670b8e80941Smrg 671b8e80941Smrg if (sample_mask != ctx->sample_mask) { 672b8e80941Smrg ctx->sample_mask = sample_mask; 673b8e80941Smrg ctx->dirty |= SWR_NEW_RASTERIZER; 674b8e80941Smrg } 675b8e80941Smrg} 676b8e80941Smrg 677b8e80941Smrg/* 678b8e80941Smrg * MSAA fixed sample position table 679b8e80941Smrg * used by update_derived and get_sample_position 680b8e80941Smrg * (integer locations on a 16x16 grid) 681b8e80941Smrg */ 682b8e80941Smrgstatic const uint8_t swr_sample_positions[][2] = 683b8e80941Smrg{ /* 1x*/ { 8, 8}, 684b8e80941Smrg /* 2x*/ {12,12},{ 4, 4}, 685b8e80941Smrg /* 4x*/ { 6, 2},{14, 6},{ 2,10},{10,14}, 686b8e80941Smrg /* 8x*/ { 9, 5},{ 7,11},{13, 9},{ 5, 3}, 687b8e80941Smrg { 3,13},{ 1, 7},{11,15},{15, 1}, 688b8e80941Smrg /*16x*/ { 9, 9},{ 7, 5},{ 5,10},{12, 7}, 689b8e80941Smrg { 3, 6},{10,13},{13,11},{11, 3}, 690b8e80941Smrg { 6,14},{ 8, 1},{ 4, 2},{ 2,12}, 691b8e80941Smrg { 0, 8},{15, 4},{14,15},{ 1, 0} }; 692b8e80941Smrg 693b8e80941Smrgstatic void 694b8e80941Smrgswr_get_sample_position(struct pipe_context *pipe, 695b8e80941Smrg unsigned sample_count, unsigned sample_index, 696b8e80941Smrg float *out_value) 697b8e80941Smrg{ 698b8e80941Smrg /* validate sample_count */ 699b8e80941Smrg sample_count = GetNumSamples(GetSampleCount(sample_count)); 700b8e80941Smrg 701b8e80941Smrg const uint8_t *sample = swr_sample_positions[sample_count-1 + sample_index]; 702b8e80941Smrg out_value[0] = sample[0] / 16.0f; 703b8e80941Smrg out_value[1] = sample[1] / 16.0f; 704b8e80941Smrg} 705b8e80941Smrg 706b8e80941Smrg 707b8e80941Smrg/* 708b8e80941Smrg * Update resource in-use status 709b8e80941Smrg * All resources bound to color or depth targets marked as WRITE resources. 710b8e80941Smrg * VBO Vertex/index buffers and texture views marked as READ resources. 711b8e80941Smrg */ 712b8e80941Smrgvoid 713b8e80941Smrgswr_update_resource_status(struct pipe_context *pipe, 714b8e80941Smrg const struct pipe_draw_info *p_draw_info) 715b8e80941Smrg{ 716b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 717b8e80941Smrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 718b8e80941Smrg 719b8e80941Smrg /* colorbuffer targets */ 720b8e80941Smrg if (fb->nr_cbufs) 721b8e80941Smrg for (uint32_t i = 0; i < fb->nr_cbufs; ++i) 722b8e80941Smrg if (fb->cbufs[i]) 723b8e80941Smrg swr_resource_write(fb->cbufs[i]->texture); 724b8e80941Smrg 725b8e80941Smrg /* depth/stencil target */ 726b8e80941Smrg if (fb->zsbuf) 727b8e80941Smrg swr_resource_write(fb->zsbuf->texture); 728b8e80941Smrg 729b8e80941Smrg /* VBO vertex buffers */ 730b8e80941Smrg for (uint32_t i = 0; i < ctx->num_vertex_buffers; i++) { 731b8e80941Smrg struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; 732b8e80941Smrg if (!vb->is_user_buffer && vb->buffer.resource) 733b8e80941Smrg swr_resource_read(vb->buffer.resource); 734b8e80941Smrg } 735b8e80941Smrg 736b8e80941Smrg /* VBO index buffer */ 737b8e80941Smrg if (p_draw_info && p_draw_info->index_size) { 738b8e80941Smrg if (!p_draw_info->has_user_indices) 739b8e80941Smrg swr_resource_read(p_draw_info->index.resource); 740b8e80941Smrg } 741b8e80941Smrg 742b8e80941Smrg /* transform feedback buffers */ 743b8e80941Smrg for (uint32_t i = 0; i < ctx->num_so_targets; i++) { 744b8e80941Smrg struct pipe_stream_output_target *target = ctx->so_targets[i]; 745b8e80941Smrg if (target && target->buffer) 746b8e80941Smrg swr_resource_write(target->buffer); 747b8e80941Smrg } 748b8e80941Smrg 749b8e80941Smrg /* texture sampler views */ 750b8e80941Smrg for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) { 751b8e80941Smrg for (uint32_t i = 0; i < ctx->num_sampler_views[j]; i++) { 752b8e80941Smrg struct pipe_sampler_view *view = ctx->sampler_views[j][i]; 753b8e80941Smrg if (view) 754b8e80941Smrg swr_resource_read(view->texture); 755b8e80941Smrg } 756b8e80941Smrg } 757b8e80941Smrg 758b8e80941Smrg /* constant buffers */ 759b8e80941Smrg for (uint32_t j : {PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT}) { 760b8e80941Smrg for (uint32_t i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 761b8e80941Smrg struct pipe_constant_buffer *cb = &ctx->constants[j][i]; 762b8e80941Smrg if (cb->buffer) 763b8e80941Smrg swr_resource_read(cb->buffer); 764b8e80941Smrg } 765b8e80941Smrg } 766b8e80941Smrg} 767b8e80941Smrg 768b8e80941Smrgstatic void 769b8e80941Smrgswr_update_texture_state(struct swr_context *ctx, 770b8e80941Smrg enum pipe_shader_type shader_type, 771b8e80941Smrg unsigned num_sampler_views, 772b8e80941Smrg swr_jit_texture *textures) 773b8e80941Smrg{ 774b8e80941Smrg for (unsigned i = 0; i < num_sampler_views; i++) { 775b8e80941Smrg struct pipe_sampler_view *view = 776b8e80941Smrg ctx->sampler_views[shader_type][i]; 777b8e80941Smrg struct swr_jit_texture *jit_tex = &textures[i]; 778b8e80941Smrg 779b8e80941Smrg memset(jit_tex, 0, sizeof(*jit_tex)); 780b8e80941Smrg if (view) { 781b8e80941Smrg struct pipe_resource *res = view->texture; 782b8e80941Smrg struct swr_resource *swr_res = swr_resource(res); 783b8e80941Smrg SWR_SURFACE_STATE *swr = &swr_res->swr; 784b8e80941Smrg size_t *mip_offsets = swr_res->mip_offsets; 785b8e80941Smrg if (swr_res->has_depth && swr_res->has_stencil && 786b8e80941Smrg !util_format_has_depth(util_format_description(view->format))) { 787b8e80941Smrg swr = &swr_res->secondary; 788b8e80941Smrg mip_offsets = swr_res->secondary_mip_offsets; 789b8e80941Smrg } 790b8e80941Smrg 791b8e80941Smrg jit_tex->width = res->width0; 792b8e80941Smrg jit_tex->height = res->height0; 793b8e80941Smrg jit_tex->base_ptr = (uint8_t*)swr->xpBaseAddress; 794b8e80941Smrg if (view->target != PIPE_BUFFER) { 795b8e80941Smrg jit_tex->first_level = view->u.tex.first_level; 796b8e80941Smrg jit_tex->last_level = view->u.tex.last_level; 797b8e80941Smrg if (view->target == PIPE_TEXTURE_3D) 798b8e80941Smrg jit_tex->depth = res->depth0; 799b8e80941Smrg else 800b8e80941Smrg jit_tex->depth = 801b8e80941Smrg view->u.tex.last_layer - view->u.tex.first_layer + 1; 802b8e80941Smrg jit_tex->base_ptr += view->u.tex.first_layer * 803b8e80941Smrg swr->qpitch * swr->pitch; 804b8e80941Smrg } else { 805b8e80941Smrg unsigned view_blocksize = util_format_get_blocksize(view->format); 806b8e80941Smrg jit_tex->base_ptr += view->u.buf.offset; 807b8e80941Smrg jit_tex->width = view->u.buf.size / view_blocksize; 808b8e80941Smrg jit_tex->depth = 1; 809b8e80941Smrg } 810b8e80941Smrg 811b8e80941Smrg for (unsigned level = jit_tex->first_level; 812b8e80941Smrg level <= jit_tex->last_level; 813b8e80941Smrg level++) { 814b8e80941Smrg jit_tex->row_stride[level] = swr->pitch; 815b8e80941Smrg jit_tex->img_stride[level] = swr->qpitch * swr->pitch; 816b8e80941Smrg jit_tex->mip_offsets[level] = mip_offsets[level]; 817b8e80941Smrg } 818b8e80941Smrg } 819b8e80941Smrg } 820b8e80941Smrg} 821b8e80941Smrg 822b8e80941Smrgstatic void 823b8e80941Smrgswr_update_sampler_state(struct swr_context *ctx, 824b8e80941Smrg enum pipe_shader_type shader_type, 825b8e80941Smrg unsigned num_samplers, 826b8e80941Smrg swr_jit_sampler *samplers) 827b8e80941Smrg{ 828b8e80941Smrg for (unsigned i = 0; i < num_samplers; i++) { 829b8e80941Smrg const struct pipe_sampler_state *sampler = 830b8e80941Smrg ctx->samplers[shader_type][i]; 831b8e80941Smrg 832b8e80941Smrg if (sampler) { 833b8e80941Smrg samplers[i].min_lod = sampler->min_lod; 834b8e80941Smrg samplers[i].max_lod = sampler->max_lod; 835b8e80941Smrg samplers[i].lod_bias = sampler->lod_bias; 836b8e80941Smrg COPY_4V(samplers[i].border_color, sampler->border_color.f); 837b8e80941Smrg } 838b8e80941Smrg } 839b8e80941Smrg} 840b8e80941Smrg 841b8e80941Smrgstatic void 842b8e80941Smrgswr_update_constants(struct swr_context *ctx, enum pipe_shader_type shaderType) 843b8e80941Smrg{ 844b8e80941Smrg swr_draw_context *pDC = &ctx->swrDC; 845b8e80941Smrg 846b8e80941Smrg const float **constant; 847b8e80941Smrg uint32_t *num_constants; 848b8e80941Smrg struct swr_scratch_space *scratch; 849b8e80941Smrg 850b8e80941Smrg switch (shaderType) { 851b8e80941Smrg case PIPE_SHADER_VERTEX: 852b8e80941Smrg constant = pDC->constantVS; 853b8e80941Smrg num_constants = pDC->num_constantsVS; 854b8e80941Smrg scratch = &ctx->scratch->vs_constants; 855b8e80941Smrg break; 856b8e80941Smrg case PIPE_SHADER_FRAGMENT: 857b8e80941Smrg constant = pDC->constantFS; 858b8e80941Smrg num_constants = pDC->num_constantsFS; 859b8e80941Smrg scratch = &ctx->scratch->fs_constants; 860b8e80941Smrg break; 861b8e80941Smrg case PIPE_SHADER_GEOMETRY: 862b8e80941Smrg constant = pDC->constantGS; 863b8e80941Smrg num_constants = pDC->num_constantsGS; 864b8e80941Smrg scratch = &ctx->scratch->gs_constants; 865b8e80941Smrg break; 866b8e80941Smrg default: 867b8e80941Smrg debug_printf("Unsupported shader type constants\n"); 868b8e80941Smrg return; 869b8e80941Smrg } 870b8e80941Smrg 871b8e80941Smrg for (UINT i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 872b8e80941Smrg const pipe_constant_buffer *cb = &ctx->constants[shaderType][i]; 873b8e80941Smrg num_constants[i] = cb->buffer_size; 874b8e80941Smrg if (cb->buffer) { 875b8e80941Smrg constant[i] = 876b8e80941Smrg (const float *)(swr_resource_data(cb->buffer) + 877b8e80941Smrg cb->buffer_offset); 878b8e80941Smrg } else { 879b8e80941Smrg /* Need to copy these constants to scratch space */ 880b8e80941Smrg if (cb->user_buffer && cb->buffer_size) { 881b8e80941Smrg const void *ptr = 882b8e80941Smrg ((const uint8_t *)cb->user_buffer + cb->buffer_offset); 883b8e80941Smrg uint32_t size = AlignUp(cb->buffer_size, 4); 884b8e80941Smrg ptr = swr_copy_to_scratch_space(ctx, scratch, ptr, size); 885b8e80941Smrg constant[i] = (const float *)ptr; 886b8e80941Smrg } 887b8e80941Smrg } 888b8e80941Smrg } 889b8e80941Smrg} 890b8e80941Smrg 891b8e80941Smrgstatic bool 892b8e80941Smrgswr_change_rt(struct swr_context *ctx, 893b8e80941Smrg unsigned attachment, 894b8e80941Smrg const struct pipe_surface *sf) 895b8e80941Smrg{ 896b8e80941Smrg swr_draw_context *pDC = &ctx->swrDC; 897b8e80941Smrg struct SWR_SURFACE_STATE *rt = &pDC->renderTargets[attachment]; 898b8e80941Smrg 899b8e80941Smrg /* Do nothing if the render target hasn't changed */ 900b8e80941Smrg if ((!sf || !sf->texture) && (void*)(rt->xpBaseAddress) == nullptr) 901b8e80941Smrg return false; 902b8e80941Smrg 903b8e80941Smrg /* Deal with disabling RT up front */ 904b8e80941Smrg if (!sf || !sf->texture) { 905b8e80941Smrg /* If detaching attachment, mark tiles as RESOLVED so core 906b8e80941Smrg * won't try to load from non-existent target. */ 907b8e80941Smrg swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_RESOLVED); 908b8e80941Smrg *rt = {0}; 909b8e80941Smrg return true; 910b8e80941Smrg } 911b8e80941Smrg 912b8e80941Smrg const struct swr_resource *swr = swr_resource(sf->texture); 913b8e80941Smrg const SWR_SURFACE_STATE *swr_surface = &swr->swr; 914b8e80941Smrg SWR_FORMAT fmt = mesa_to_swr_format(sf->format); 915b8e80941Smrg 916b8e80941Smrg if (attachment == SWR_ATTACHMENT_STENCIL && swr->secondary.xpBaseAddress) { 917b8e80941Smrg swr_surface = &swr->secondary; 918b8e80941Smrg fmt = swr_surface->format; 919b8e80941Smrg } 920b8e80941Smrg 921b8e80941Smrg if (rt->xpBaseAddress == swr_surface->xpBaseAddress && 922b8e80941Smrg rt->format == fmt && 923b8e80941Smrg rt->lod == sf->u.tex.level && 924b8e80941Smrg rt->arrayIndex == sf->u.tex.first_layer) 925b8e80941Smrg return false; 926b8e80941Smrg 927b8e80941Smrg bool need_fence = false; 928b8e80941Smrg 929b8e80941Smrg /* StoreTile for changed target */ 930b8e80941Smrg if (rt->xpBaseAddress) { 931b8e80941Smrg /* If changing attachment to a new target, mark tiles as 932b8e80941Smrg * INVALID so they are reloaded from surface. */ 933b8e80941Smrg swr_store_render_target(&ctx->pipe, attachment, SWR_TILE_INVALID); 934b8e80941Smrg need_fence = true; 935b8e80941Smrg } else { 936b8e80941Smrg /* if no previous attachment, invalidate tiles that may be marked 937b8e80941Smrg * RESOLVED because of an old attachment */ 938b8e80941Smrg swr_invalidate_render_target(&ctx->pipe, attachment, sf->width, sf->height); 939b8e80941Smrg /* no need to set fence here */ 940b8e80941Smrg } 941b8e80941Smrg 942b8e80941Smrg /* Make new attachment */ 943b8e80941Smrg *rt = *swr_surface; 944b8e80941Smrg rt->format = fmt; 945b8e80941Smrg rt->lod = sf->u.tex.level; 946b8e80941Smrg rt->arrayIndex = sf->u.tex.first_layer; 947b8e80941Smrg 948b8e80941Smrg return need_fence; 949b8e80941Smrg} 950b8e80941Smrg 951b8e80941Smrg/* 952b8e80941Smrg * for cases where resources are shared between contexts, invalidate 953b8e80941Smrg * this ctx's resource. so it can be fetched fresh. Old ctx's resource 954b8e80941Smrg * is already stored during a flush 955b8e80941Smrg */ 956b8e80941Smrgstatic inline void 957b8e80941Smrgswr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe) 958b8e80941Smrg{ 959b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 960b8e80941Smrg 961b8e80941Smrg for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) { 962b8e80941Smrg struct pipe_surface *cb = ctx->framebuffer.cbufs[i]; 963b8e80941Smrg if (cb) { 964b8e80941Smrg struct swr_resource *res = swr_resource(cb->texture); 965b8e80941Smrg if (res->curr_pipe != pipe) { 966b8e80941Smrg /* if curr_pipe is NULL (first use), status should not be WRITE */ 967b8e80941Smrg assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); 968b8e80941Smrg if (res->status & SWR_RESOURCE_WRITE) { 969b8e80941Smrg swr_invalidate_render_target(pipe, i, cb->width, cb->height); 970b8e80941Smrg } 971b8e80941Smrg } 972b8e80941Smrg res->curr_pipe = pipe; 973b8e80941Smrg } 974b8e80941Smrg } 975b8e80941Smrg if (ctx->framebuffer.zsbuf) { 976b8e80941Smrg struct pipe_surface *zb = ctx->framebuffer.zsbuf; 977b8e80941Smrg if (zb) { 978b8e80941Smrg struct swr_resource *res = swr_resource(zb->texture); 979b8e80941Smrg if (res->curr_pipe != pipe) { 980b8e80941Smrg /* if curr_pipe is NULL (first use), status should not be WRITE */ 981b8e80941Smrg assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE)); 982b8e80941Smrg if (res->status & SWR_RESOURCE_WRITE) { 983b8e80941Smrg swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height); 984b8e80941Smrg swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height); 985b8e80941Smrg } 986b8e80941Smrg } 987b8e80941Smrg res->curr_pipe = pipe; 988b8e80941Smrg } 989b8e80941Smrg } 990b8e80941Smrg} 991b8e80941Smrg 992b8e80941Smrgstatic inline void 993b8e80941Smrgswr_user_vbuf_range(const struct pipe_draw_info *info, 994b8e80941Smrg const struct swr_vertex_element_state *velems, 995b8e80941Smrg const struct pipe_vertex_buffer *vb, 996b8e80941Smrg uint32_t i, 997b8e80941Smrg uint32_t *totelems, 998b8e80941Smrg uint32_t *base, 999b8e80941Smrg uint32_t *size) 1000b8e80941Smrg{ 1001b8e80941Smrg /* FIXME: The size is too large - we don't access the full extra stride. */ 1002b8e80941Smrg unsigned elems; 1003b8e80941Smrg if (velems->instanced_bufs & (1U << i)) { 1004b8e80941Smrg elems = info->instance_count / velems->min_instance_div[i] + 1; 1005b8e80941Smrg *totelems = info->start_instance + elems; 1006b8e80941Smrg *base = info->start_instance * vb->stride; 1007b8e80941Smrg *size = elems * vb->stride; 1008b8e80941Smrg } else if (vb->stride) { 1009b8e80941Smrg elems = info->max_index - info->min_index + 1; 1010b8e80941Smrg *totelems = (info->max_index + info->index_bias) + 1; 1011b8e80941Smrg *base = (info->min_index + info->index_bias) * vb->stride; 1012b8e80941Smrg *size = elems * vb->stride; 1013b8e80941Smrg } else { 1014b8e80941Smrg *totelems = 1; 1015b8e80941Smrg *base = 0; 1016b8e80941Smrg *size = velems->stream_pitch[i]; 1017b8e80941Smrg } 1018b8e80941Smrg} 1019b8e80941Smrg 1020b8e80941Smrgstatic void 1021b8e80941Smrgswr_update_poly_stipple(struct swr_context *ctx) 1022b8e80941Smrg{ 1023b8e80941Smrg struct swr_draw_context *pDC = &ctx->swrDC; 1024b8e80941Smrg 1025b8e80941Smrg assert(sizeof(ctx->poly_stipple.pipe.stipple) == sizeof(pDC->polyStipple)); 1026b8e80941Smrg memcpy(pDC->polyStipple, 1027b8e80941Smrg ctx->poly_stipple.pipe.stipple, 1028b8e80941Smrg sizeof(ctx->poly_stipple.pipe.stipple)); 1029b8e80941Smrg} 1030b8e80941Smrg 1031b8e80941Smrgvoid 1032b8e80941Smrgswr_update_derived(struct pipe_context *pipe, 1033b8e80941Smrg const struct pipe_draw_info *p_draw_info) 1034b8e80941Smrg{ 1035b8e80941Smrg struct swr_context *ctx = swr_context(pipe); 1036b8e80941Smrg struct swr_screen *screen = swr_screen(pipe->screen); 1037b8e80941Smrg 1038b8e80941Smrg /* When called from swr_clear (p_draw_info = null), set any null 1039b8e80941Smrg * state-objects to the dummy state objects to prevent nullptr dereference 1040b8e80941Smrg * in validation below. 1041b8e80941Smrg * 1042b8e80941Smrg * Important that this remains static for zero initialization. These 1043b8e80941Smrg * aren't meant to be proper state objects, just empty structs. They will 1044b8e80941Smrg * not be written to. 1045b8e80941Smrg * 1046b8e80941Smrg * Shaders can't be part of the union since they contain std::unordered_map 1047b8e80941Smrg */ 1048b8e80941Smrg static struct { 1049b8e80941Smrg union { 1050b8e80941Smrg struct pipe_rasterizer_state rasterizer; 1051b8e80941Smrg struct pipe_depth_stencil_alpha_state depth_stencil; 1052b8e80941Smrg struct swr_blend_state blend; 1053b8e80941Smrg } state; 1054b8e80941Smrg struct swr_vertex_shader vs; 1055b8e80941Smrg struct swr_fragment_shader fs; 1056b8e80941Smrg } swr_dummy; 1057b8e80941Smrg 1058b8e80941Smrg if (!p_draw_info) { 1059b8e80941Smrg if (!ctx->rasterizer) 1060b8e80941Smrg ctx->rasterizer = &swr_dummy.state.rasterizer; 1061b8e80941Smrg if (!ctx->depth_stencil) 1062b8e80941Smrg ctx->depth_stencil = &swr_dummy.state.depth_stencil; 1063b8e80941Smrg if (!ctx->blend) 1064b8e80941Smrg ctx->blend = &swr_dummy.state.blend; 1065b8e80941Smrg if (!ctx->vs) 1066b8e80941Smrg ctx->vs = &swr_dummy.vs; 1067b8e80941Smrg if (!ctx->fs) 1068b8e80941Smrg ctx->fs = &swr_dummy.fs; 1069b8e80941Smrg } 1070b8e80941Smrg 1071b8e80941Smrg /* Update screen->pipe to current pipe context. */ 1072b8e80941Smrg screen->pipe = pipe; 1073b8e80941Smrg 1074b8e80941Smrg /* Any state that requires dirty flags to be re-triggered sets this mask */ 1075b8e80941Smrg /* For example, user_buffer vertex and index buffers. */ 1076b8e80941Smrg unsigned post_update_dirty_flags = 0; 1077b8e80941Smrg 1078b8e80941Smrg /* bring resources that changed context up-to-date */ 1079b8e80941Smrg swr_invalidate_buffers_after_ctx_change(pipe); 1080b8e80941Smrg 1081b8e80941Smrg /* Render Targets */ 1082b8e80941Smrg if (ctx->dirty & SWR_NEW_FRAMEBUFFER) { 1083b8e80941Smrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 1084b8e80941Smrg const struct util_format_description *desc = NULL; 1085b8e80941Smrg bool need_fence = false; 1086b8e80941Smrg 1087b8e80941Smrg /* colorbuffer targets */ 1088b8e80941Smrg if (fb->nr_cbufs) { 1089b8e80941Smrg for (unsigned i = 0; i < fb->nr_cbufs; ++i) 1090b8e80941Smrg need_fence |= swr_change_rt( 1091b8e80941Smrg ctx, SWR_ATTACHMENT_COLOR0 + i, fb->cbufs[i]); 1092b8e80941Smrg } 1093b8e80941Smrg for (unsigned i = fb->nr_cbufs; i < SWR_NUM_RENDERTARGETS; ++i) 1094b8e80941Smrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_COLOR0 + i, NULL); 1095b8e80941Smrg 1096b8e80941Smrg /* depth/stencil target */ 1097b8e80941Smrg if (fb->zsbuf) 1098b8e80941Smrg desc = util_format_description(fb->zsbuf->format); 1099b8e80941Smrg if (fb->zsbuf && util_format_has_depth(desc)) 1100b8e80941Smrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, fb->zsbuf); 1101b8e80941Smrg else 1102b8e80941Smrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_DEPTH, NULL); 1103b8e80941Smrg 1104b8e80941Smrg if (fb->zsbuf && util_format_has_stencil(desc)) 1105b8e80941Smrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, fb->zsbuf); 1106b8e80941Smrg else 1107b8e80941Smrg need_fence |= swr_change_rt(ctx, SWR_ATTACHMENT_STENCIL, NULL); 1108b8e80941Smrg 1109b8e80941Smrg /* This fence ensures any attachment changes are resolved before the 1110b8e80941Smrg * next draw */ 1111b8e80941Smrg if (need_fence) 1112b8e80941Smrg swr_fence_submit(ctx, screen->flush_fence); 1113b8e80941Smrg } 1114b8e80941Smrg 1115b8e80941Smrg /* Raster state */ 1116b8e80941Smrg if (ctx->dirty & (SWR_NEW_RASTERIZER | 1117b8e80941Smrg SWR_NEW_VS | // clipping 1118b8e80941Smrg SWR_NEW_FRAMEBUFFER)) { 1119b8e80941Smrg pipe_rasterizer_state *rasterizer = ctx->rasterizer; 1120b8e80941Smrg pipe_framebuffer_state *fb = &ctx->framebuffer; 1121b8e80941Smrg 1122b8e80941Smrg SWR_RASTSTATE *rastState = &ctx->derived.rastState; 1123b8e80941Smrg rastState->cullMode = swr_convert_cull_mode(rasterizer->cull_face); 1124b8e80941Smrg rastState->frontWinding = rasterizer->front_ccw 1125b8e80941Smrg ? SWR_FRONTWINDING_CCW 1126b8e80941Smrg : SWR_FRONTWINDING_CW; 1127b8e80941Smrg rastState->scissorEnable = rasterizer->scissor; 1128b8e80941Smrg rastState->pointSize = rasterizer->point_size > 0.0f 1129b8e80941Smrg ? rasterizer->point_size 1130b8e80941Smrg : 1.0f; 1131b8e80941Smrg rastState->lineWidth = rasterizer->line_width > 0.0f 1132b8e80941Smrg ? rasterizer->line_width 1133b8e80941Smrg : 1.0f; 1134b8e80941Smrg 1135b8e80941Smrg rastState->pointParam = rasterizer->point_size_per_vertex; 1136b8e80941Smrg 1137b8e80941Smrg rastState->pointSpriteEnable = rasterizer->sprite_coord_enable; 1138b8e80941Smrg rastState->pointSpriteTopOrigin = 1139b8e80941Smrg rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT; 1140b8e80941Smrg 1141b8e80941Smrg /* If SWR_MSAA_FORCE_ENABLE is set, turn msaa on */ 1142b8e80941Smrg if (screen->msaa_force_enable && !rasterizer->multisample) { 1143b8e80941Smrg /* Force enable and use the value the surface was created with */ 1144b8e80941Smrg rasterizer->multisample = true; 1145b8e80941Smrg fb->samples = swr_resource(fb->cbufs[0]->texture)->swr.numSamples; 1146b8e80941Smrg fprintf(stderr,"msaa force enable: %d samples\n", fb->samples); 1147b8e80941Smrg } 1148b8e80941Smrg 1149b8e80941Smrg rastState->sampleCount = GetSampleCount(fb->samples); 1150b8e80941Smrg rastState->forcedSampleCount = false; 1151b8e80941Smrg rastState->bIsCenterPattern = !rasterizer->multisample; 1152b8e80941Smrg rastState->pixelLocation = SWR_PIXEL_LOCATION_CENTER; 1153b8e80941Smrg 1154b8e80941Smrg /* Only initialize sample positions if msaa is enabled */ 1155b8e80941Smrg if (rasterizer->multisample) { 1156b8e80941Smrg for (uint32_t i = 0; i < fb->samples; i++) { 1157b8e80941Smrg const uint8_t *sample = swr_sample_positions[fb->samples-1 + i]; 1158b8e80941Smrg rastState->samplePositions.SetXi(i, sample[0] << 4); 1159b8e80941Smrg rastState->samplePositions.SetYi(i, sample[1] << 4); 1160b8e80941Smrg rastState->samplePositions.SetX (i, sample[0] / 16.0f); 1161b8e80941Smrg rastState->samplePositions.SetY (i, sample[1] / 16.0f); 1162b8e80941Smrg } 1163b8e80941Smrg rastState->samplePositions.PrecalcSampleData(fb->samples); 1164b8e80941Smrg } 1165b8e80941Smrg 1166b8e80941Smrg bool do_offset = false; 1167b8e80941Smrg switch (rasterizer->fill_front) { 1168b8e80941Smrg case PIPE_POLYGON_MODE_FILL: 1169b8e80941Smrg do_offset = rasterizer->offset_tri; 1170b8e80941Smrg break; 1171b8e80941Smrg case PIPE_POLYGON_MODE_LINE: 1172b8e80941Smrg do_offset = rasterizer->offset_line; 1173b8e80941Smrg break; 1174b8e80941Smrg case PIPE_POLYGON_MODE_POINT: 1175b8e80941Smrg do_offset = rasterizer->offset_point; 1176b8e80941Smrg break; 1177b8e80941Smrg } 1178b8e80941Smrg 1179b8e80941Smrg if (do_offset) { 1180b8e80941Smrg rastState->depthBias = rasterizer->offset_units; 1181b8e80941Smrg rastState->slopeScaledDepthBias = rasterizer->offset_scale; 1182b8e80941Smrg rastState->depthBiasClamp = rasterizer->offset_clamp; 1183b8e80941Smrg } else { 1184b8e80941Smrg rastState->depthBias = 0; 1185b8e80941Smrg rastState->slopeScaledDepthBias = 0; 1186b8e80941Smrg rastState->depthBiasClamp = 0; 1187b8e80941Smrg } 1188b8e80941Smrg 1189b8e80941Smrg /* translate polygon mode, at least for the front==back case */ 1190b8e80941Smrg rastState->fillMode = swr_convert_fill_mode(rasterizer->fill_front); 1191b8e80941Smrg 1192b8e80941Smrg struct pipe_surface *zb = fb->zsbuf; 1193b8e80941Smrg if (zb && swr_resource(zb->texture)->has_depth) 1194b8e80941Smrg rastState->depthFormat = swr_resource(zb->texture)->swr.format; 1195b8e80941Smrg 1196b8e80941Smrg rastState->depthClipEnable = rasterizer->depth_clip_near; 1197b8e80941Smrg rastState->clipHalfZ = rasterizer->clip_halfz; 1198b8e80941Smrg 1199b8e80941Smrg ctx->api.pfnSwrSetRastState(ctx->swrContext, rastState); 1200b8e80941Smrg } 1201b8e80941Smrg 1202b8e80941Smrg /* Viewport */ 1203b8e80941Smrg if (ctx->dirty & (SWR_NEW_VIEWPORT | SWR_NEW_FRAMEBUFFER 1204b8e80941Smrg | SWR_NEW_RASTERIZER)) { 1205b8e80941Smrg pipe_viewport_state *state = &ctx->viewport; 1206b8e80941Smrg pipe_framebuffer_state *fb = &ctx->framebuffer; 1207b8e80941Smrg pipe_rasterizer_state *rasterizer = ctx->rasterizer; 1208b8e80941Smrg 1209b8e80941Smrg SWR_VIEWPORT *vp = &ctx->derived.vp; 1210b8e80941Smrg SWR_VIEWPORT_MATRICES *vpm = &ctx->derived.vpm; 1211b8e80941Smrg 1212b8e80941Smrg vp->x = state->translate[0] - state->scale[0]; 1213b8e80941Smrg vp->width = 2 * state->scale[0]; 1214b8e80941Smrg vp->y = state->translate[1] - fabs(state->scale[1]); 1215b8e80941Smrg vp->height = 2 * fabs(state->scale[1]); 1216b8e80941Smrg util_viewport_zmin_zmax(state, rasterizer->clip_halfz, 1217b8e80941Smrg &vp->minZ, &vp->maxZ); 1218b8e80941Smrg 1219b8e80941Smrg vpm->m00[0] = state->scale[0]; 1220b8e80941Smrg vpm->m11[0] = state->scale[1]; 1221b8e80941Smrg vpm->m22[0] = state->scale[2]; 1222b8e80941Smrg vpm->m30[0] = state->translate[0]; 1223b8e80941Smrg vpm->m31[0] = state->translate[1]; 1224b8e80941Smrg vpm->m32[0] = state->translate[2]; 1225b8e80941Smrg 1226b8e80941Smrg /* Now that the matrix is calculated, clip the view coords to screen 1227b8e80941Smrg * size. OpenGL allows for -ve x,y in the viewport. */ 1228b8e80941Smrg if (vp->x < 0.0f) { 1229b8e80941Smrg vp->width += vp->x; 1230b8e80941Smrg vp->x = 0.0f; 1231b8e80941Smrg } 1232b8e80941Smrg if (vp->y < 0.0f) { 1233b8e80941Smrg vp->height += vp->y; 1234b8e80941Smrg vp->y = 0.0f; 1235b8e80941Smrg } 1236b8e80941Smrg vp->width = std::min(vp->width, (float)fb->width - vp->x); 1237b8e80941Smrg vp->height = std::min(vp->height, (float)fb->height - vp->y); 1238b8e80941Smrg 1239b8e80941Smrg ctx->api.pfnSwrSetViewports(ctx->swrContext, 1, vp, vpm); 1240b8e80941Smrg } 1241b8e80941Smrg 1242b8e80941Smrg /* When called from swr_clear (p_draw_info = null), render targets, 1243b8e80941Smrg * rasterState and viewports (dependent on render targets) are the only 1244b8e80941Smrg * necessary validation. Defer remaining validation by setting 1245b8e80941Smrg * post_update_dirty_flags and clear all dirty flags. BackendState is 1246b8e80941Smrg * still unconditionally validated below */ 1247b8e80941Smrg if (!p_draw_info) { 1248b8e80941Smrg post_update_dirty_flags = ctx->dirty & ~(SWR_NEW_FRAMEBUFFER | 1249b8e80941Smrg SWR_NEW_RASTERIZER | 1250b8e80941Smrg SWR_NEW_VIEWPORT); 1251b8e80941Smrg ctx->dirty = 0; 1252b8e80941Smrg } 1253b8e80941Smrg 1254b8e80941Smrg /* Scissor */ 1255b8e80941Smrg if (ctx->dirty & SWR_NEW_SCISSOR) { 1256b8e80941Smrg ctx->api.pfnSwrSetScissorRects(ctx->swrContext, 1, &ctx->swr_scissor); 1257b8e80941Smrg } 1258b8e80941Smrg 1259b8e80941Smrg /* Set vertex & index buffers */ 1260b8e80941Smrg if (ctx->dirty & SWR_NEW_VERTEX) { 1261b8e80941Smrg const struct pipe_draw_info &info = *p_draw_info; 1262b8e80941Smrg 1263b8e80941Smrg /* vertex buffers */ 1264b8e80941Smrg SWR_VERTEX_BUFFER_STATE swrVertexBuffers[PIPE_MAX_ATTRIBS]; 1265b8e80941Smrg for (UINT i = 0; i < ctx->num_vertex_buffers; i++) { 1266b8e80941Smrg uint32_t size, pitch, elems, partial_inbounds; 1267b8e80941Smrg uint32_t min_vertex_index; 1268b8e80941Smrg const uint8_t *p_data; 1269b8e80941Smrg struct pipe_vertex_buffer *vb = &ctx->vertex_buffer[i]; 1270b8e80941Smrg 1271b8e80941Smrg pitch = vb->stride; 1272b8e80941Smrg if (vb->is_user_buffer) { 1273b8e80941Smrg /* Client buffer 1274b8e80941Smrg * client memory is one-time use, re-trigger SWR_NEW_VERTEX to 1275b8e80941Smrg * revalidate on each draw */ 1276b8e80941Smrg post_update_dirty_flags |= SWR_NEW_VERTEX; 1277b8e80941Smrg 1278b8e80941Smrg uint32_t base; 1279b8e80941Smrg swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size); 1280b8e80941Smrg partial_inbounds = 0; 1281b8e80941Smrg min_vertex_index = info.min_index + info.index_bias; 1282b8e80941Smrg 1283b8e80941Smrg size = AlignUp(size, 4); 1284b8e80941Smrg /* If size of client memory copy is too large, don't copy. The 1285b8e80941Smrg * draw will access user-buffer directly and then block. This is 1286b8e80941Smrg * faster than queuing many large client draws. */ 1287b8e80941Smrg if (size >= screen->client_copy_limit) { 1288b8e80941Smrg post_update_dirty_flags |= SWR_LARGE_CLIENT_DRAW; 1289b8e80941Smrg p_data = (const uint8_t *) vb->buffer.user; 1290b8e80941Smrg } else { 1291b8e80941Smrg /* Copy only needed vertices to scratch space */ 1292b8e80941Smrg const void *ptr = (const uint8_t *) vb->buffer.user + base; 1293b8e80941Smrg ptr = (uint8_t *)swr_copy_to_scratch_space( 1294b8e80941Smrg ctx, &ctx->scratch->vertex_buffer, ptr, size); 1295b8e80941Smrg p_data = (const uint8_t *)ptr - base; 1296b8e80941Smrg } 1297b8e80941Smrg } else if (vb->buffer.resource) { 1298b8e80941Smrg /* VBO */ 1299b8e80941Smrg if (!pitch) { 1300b8e80941Smrg /* If pitch=0 (ie vb->stride), buffer contains a single 1301b8e80941Smrg * constant attribute. Use the stream_pitch which was 1302b8e80941Smrg * calculated during creation of vertex_elements_state for the 1303b8e80941Smrg * size of the attribute. */ 1304b8e80941Smrg size = ctx->velems->stream_pitch[i]; 1305b8e80941Smrg elems = 1; 1306b8e80941Smrg partial_inbounds = 0; 1307b8e80941Smrg min_vertex_index = 0; 1308b8e80941Smrg } else { 1309b8e80941Smrg /* size is based on buffer->width0 rather than info.max_index 1310b8e80941Smrg * to prevent having to validate VBO on each draw. */ 1311b8e80941Smrg size = vb->buffer.resource->width0; 1312b8e80941Smrg elems = size / pitch; 1313b8e80941Smrg partial_inbounds = size % pitch; 1314b8e80941Smrg min_vertex_index = 0; 1315b8e80941Smrg } 1316b8e80941Smrg 1317b8e80941Smrg p_data = swr_resource_data(vb->buffer.resource) + vb->buffer_offset; 1318b8e80941Smrg } else 1319b8e80941Smrg p_data = NULL; 1320b8e80941Smrg 1321b8e80941Smrg swrVertexBuffers[i] = {0}; 1322b8e80941Smrg swrVertexBuffers[i].index = i; 1323b8e80941Smrg swrVertexBuffers[i].pitch = pitch; 1324b8e80941Smrg swrVertexBuffers[i].xpData = (gfxptr_t) p_data; 1325b8e80941Smrg swrVertexBuffers[i].size = size; 1326b8e80941Smrg swrVertexBuffers[i].minVertex = min_vertex_index; 1327b8e80941Smrg swrVertexBuffers[i].maxVertex = elems; 1328b8e80941Smrg swrVertexBuffers[i].partialInboundsSize = partial_inbounds; 1329b8e80941Smrg } 1330b8e80941Smrg 1331b8e80941Smrg ctx->api.pfnSwrSetVertexBuffers( 1332b8e80941Smrg ctx->swrContext, ctx->num_vertex_buffers, swrVertexBuffers); 1333b8e80941Smrg 1334b8e80941Smrg /* index buffer, if required (info passed in by swr_draw_vbo) */ 1335b8e80941Smrg SWR_FORMAT index_type = R32_UINT; /* Default for non-indexed draws */ 1336b8e80941Smrg if (info.index_size) { 1337b8e80941Smrg const uint8_t *p_data; 1338b8e80941Smrg uint32_t size, pitch; 1339b8e80941Smrg 1340b8e80941Smrg pitch = info.index_size ? info.index_size : sizeof(uint32_t); 1341b8e80941Smrg index_type = swr_convert_index_type(pitch); 1342b8e80941Smrg 1343b8e80941Smrg if (!info.has_user_indices) { 1344b8e80941Smrg /* VBO 1345b8e80941Smrg * size is based on buffer->width0 rather than info.count 1346b8e80941Smrg * to prevent having to validate VBO on each draw */ 1347b8e80941Smrg size = info.index.resource->width0; 1348b8e80941Smrg p_data = swr_resource_data(info.index.resource); 1349b8e80941Smrg } else { 1350b8e80941Smrg /* Client buffer 1351b8e80941Smrg * client memory is one-time use, re-trigger SWR_NEW_VERTEX to 1352b8e80941Smrg * revalidate on each draw */ 1353b8e80941Smrg post_update_dirty_flags |= SWR_NEW_VERTEX; 1354b8e80941Smrg 1355b8e80941Smrg size = info.count * pitch; 1356b8e80941Smrg size = AlignUp(size, 4); 1357b8e80941Smrg /* If size of client memory copy is too large, don't copy. The 1358b8e80941Smrg * draw will access user-buffer directly and then block. This is 1359b8e80941Smrg * faster than queuing many large client draws. */ 1360b8e80941Smrg if (size >= screen->client_copy_limit) { 1361b8e80941Smrg post_update_dirty_flags |= SWR_LARGE_CLIENT_DRAW; 1362b8e80941Smrg p_data = (const uint8_t *) info.index.user; 1363b8e80941Smrg } else { 1364b8e80941Smrg /* Copy indices to scratch space */ 1365b8e80941Smrg const void *ptr = info.index.user; 1366b8e80941Smrg ptr = swr_copy_to_scratch_space( 1367b8e80941Smrg ctx, &ctx->scratch->index_buffer, ptr, size); 1368b8e80941Smrg p_data = (const uint8_t *)ptr; 1369b8e80941Smrg } 1370b8e80941Smrg } 1371b8e80941Smrg 1372b8e80941Smrg SWR_INDEX_BUFFER_STATE swrIndexBuffer; 1373b8e80941Smrg swrIndexBuffer.format = swr_convert_index_type(info.index_size); 1374b8e80941Smrg swrIndexBuffer.xpIndices = (gfxptr_t) p_data; 1375b8e80941Smrg swrIndexBuffer.size = size; 1376b8e80941Smrg 1377b8e80941Smrg ctx->api.pfnSwrSetIndexBuffer(ctx->swrContext, &swrIndexBuffer); 1378b8e80941Smrg } 1379b8e80941Smrg 1380b8e80941Smrg struct swr_vertex_element_state *velems = ctx->velems; 1381b8e80941Smrg if (velems && velems->fsState.indexType != index_type) { 1382b8e80941Smrg velems->fsFunc = NULL; 1383b8e80941Smrg velems->fsState.indexType = index_type; 1384b8e80941Smrg } 1385b8e80941Smrg } 1386b8e80941Smrg 1387b8e80941Smrg /* GeometryShader */ 1388b8e80941Smrg if (ctx->dirty & (SWR_NEW_GS | 1389b8e80941Smrg SWR_NEW_VS | 1390b8e80941Smrg SWR_NEW_SAMPLER | 1391b8e80941Smrg SWR_NEW_SAMPLER_VIEW)) { 1392b8e80941Smrg if (ctx->gs) { 1393b8e80941Smrg swr_jit_gs_key key; 1394b8e80941Smrg swr_generate_gs_key(key, ctx, ctx->gs); 1395b8e80941Smrg auto search = ctx->gs->map.find(key); 1396b8e80941Smrg PFN_GS_FUNC func; 1397b8e80941Smrg if (search != ctx->gs->map.end()) { 1398b8e80941Smrg func = search->second->shader; 1399b8e80941Smrg } else { 1400b8e80941Smrg func = swr_compile_gs(ctx, key); 1401b8e80941Smrg } 1402b8e80941Smrg ctx->api.pfnSwrSetGsFunc(ctx->swrContext, func); 1403b8e80941Smrg 1404b8e80941Smrg /* JIT sampler state */ 1405b8e80941Smrg if (ctx->dirty & SWR_NEW_SAMPLER) { 1406b8e80941Smrg swr_update_sampler_state(ctx, 1407b8e80941Smrg PIPE_SHADER_GEOMETRY, 1408b8e80941Smrg key.nr_samplers, 1409b8e80941Smrg ctx->swrDC.samplersGS); 1410b8e80941Smrg } 1411b8e80941Smrg 1412b8e80941Smrg /* JIT sampler view state */ 1413b8e80941Smrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 1414b8e80941Smrg swr_update_texture_state(ctx, 1415b8e80941Smrg PIPE_SHADER_GEOMETRY, 1416b8e80941Smrg key.nr_sampler_views, 1417b8e80941Smrg ctx->swrDC.texturesGS); 1418b8e80941Smrg } 1419b8e80941Smrg 1420b8e80941Smrg ctx->api.pfnSwrSetGsState(ctx->swrContext, &ctx->gs->gsState); 1421b8e80941Smrg } else { 1422b8e80941Smrg SWR_GS_STATE state = { 0 }; 1423b8e80941Smrg ctx->api.pfnSwrSetGsState(ctx->swrContext, &state); 1424b8e80941Smrg ctx->api.pfnSwrSetGsFunc(ctx->swrContext, NULL); 1425b8e80941Smrg } 1426b8e80941Smrg } 1427b8e80941Smrg 1428b8e80941Smrg /* VertexShader */ 1429b8e80941Smrg if (ctx->dirty & (SWR_NEW_VS | 1430b8e80941Smrg SWR_NEW_RASTERIZER | // for clip planes 1431b8e80941Smrg SWR_NEW_SAMPLER | 1432b8e80941Smrg SWR_NEW_SAMPLER_VIEW | 1433b8e80941Smrg SWR_NEW_FRAMEBUFFER)) { 1434b8e80941Smrg swr_jit_vs_key key; 1435b8e80941Smrg swr_generate_vs_key(key, ctx, ctx->vs); 1436b8e80941Smrg auto search = ctx->vs->map.find(key); 1437b8e80941Smrg PFN_VERTEX_FUNC func; 1438b8e80941Smrg if (search != ctx->vs->map.end()) { 1439b8e80941Smrg func = search->second->shader; 1440b8e80941Smrg } else { 1441b8e80941Smrg func = swr_compile_vs(ctx, key); 1442b8e80941Smrg } 1443b8e80941Smrg ctx->api.pfnSwrSetVertexFunc(ctx->swrContext, func); 1444b8e80941Smrg 1445b8e80941Smrg /* JIT sampler state */ 1446b8e80941Smrg if (ctx->dirty & SWR_NEW_SAMPLER) { 1447b8e80941Smrg swr_update_sampler_state(ctx, 1448b8e80941Smrg PIPE_SHADER_VERTEX, 1449b8e80941Smrg key.nr_samplers, 1450b8e80941Smrg ctx->swrDC.samplersVS); 1451b8e80941Smrg } 1452b8e80941Smrg 1453b8e80941Smrg /* JIT sampler view state */ 1454b8e80941Smrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | SWR_NEW_FRAMEBUFFER)) { 1455b8e80941Smrg swr_update_texture_state(ctx, 1456b8e80941Smrg PIPE_SHADER_VERTEX, 1457b8e80941Smrg key.nr_sampler_views, 1458b8e80941Smrg ctx->swrDC.texturesVS); 1459b8e80941Smrg } 1460b8e80941Smrg } 1461b8e80941Smrg 1462b8e80941Smrg /* work around the fact that poly stipple also affects lines */ 1463b8e80941Smrg /* and points, since we rasterize them as triangles, too */ 1464b8e80941Smrg /* Has to be before fragment shader, since it sets SWR_NEW_FS */ 1465b8e80941Smrg if (p_draw_info) { 1466b8e80941Smrg bool new_prim_is_poly = 1467b8e80941Smrg (u_reduced_prim(p_draw_info->mode) == PIPE_PRIM_TRIANGLES) && 1468b8e80941Smrg (ctx->derived.rastState.fillMode == SWR_FILLMODE_SOLID); 1469b8e80941Smrg if (new_prim_is_poly != ctx->poly_stipple.prim_is_poly) { 1470b8e80941Smrg ctx->dirty |= SWR_NEW_FS; 1471b8e80941Smrg ctx->poly_stipple.prim_is_poly = new_prim_is_poly; 1472b8e80941Smrg } 1473b8e80941Smrg } 1474b8e80941Smrg 1475b8e80941Smrg /* FragmentShader */ 1476b8e80941Smrg if (ctx->dirty & (SWR_NEW_FS | 1477b8e80941Smrg SWR_NEW_VS | 1478b8e80941Smrg SWR_NEW_GS | 1479b8e80941Smrg SWR_NEW_RASTERIZER | 1480b8e80941Smrg SWR_NEW_SAMPLER | 1481b8e80941Smrg SWR_NEW_SAMPLER_VIEW | 1482b8e80941Smrg SWR_NEW_FRAMEBUFFER)) { 1483b8e80941Smrg swr_jit_fs_key key; 1484b8e80941Smrg swr_generate_fs_key(key, ctx, ctx->fs); 1485b8e80941Smrg auto search = ctx->fs->map.find(key); 1486b8e80941Smrg PFN_PIXEL_KERNEL func; 1487b8e80941Smrg if (search != ctx->fs->map.end()) { 1488b8e80941Smrg func = search->second->shader; 1489b8e80941Smrg } else { 1490b8e80941Smrg func = swr_compile_fs(ctx, key); 1491b8e80941Smrg } 1492b8e80941Smrg SWR_PS_STATE psState = {0}; 1493b8e80941Smrg psState.pfnPixelShader = func; 1494b8e80941Smrg psState.killsPixel = ctx->fs->info.base.uses_kill; 1495b8e80941Smrg psState.inputCoverage = SWR_INPUT_COVERAGE_NORMAL; 1496b8e80941Smrg psState.writesODepth = ctx->fs->info.base.writes_z; 1497b8e80941Smrg psState.usesSourceDepth = ctx->fs->info.base.reads_z; 1498b8e80941Smrg psState.shadingRate = SWR_SHADING_RATE_PIXEL; 1499b8e80941Smrg psState.renderTargetMask = (1 << ctx->framebuffer.nr_cbufs) - 1; 1500b8e80941Smrg psState.posOffset = SWR_PS_POSITION_SAMPLE_NONE; 1501b8e80941Smrg uint32_t barycentricsMask = 0; 1502b8e80941Smrg#if 0 1503b8e80941Smrg // when we switch to mesa-master 1504b8e80941Smrg if (ctx->fs->info.base.uses_persp_center || 1505b8e80941Smrg ctx->fs->info.base.uses_linear_center) 1506b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK; 1507b8e80941Smrg if (ctx->fs->info.base.uses_persp_centroid || 1508b8e80941Smrg ctx->fs->info.base.uses_linear_centroid) 1509b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK; 1510b8e80941Smrg if (ctx->fs->info.base.uses_persp_sample || 1511b8e80941Smrg ctx->fs->info.base.uses_linear_sample) 1512b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK; 1513b8e80941Smrg#else 1514b8e80941Smrg for (unsigned i = 0; i < ctx->fs->info.base.num_inputs; i++) { 1515b8e80941Smrg switch (ctx->fs->info.base.input_interpolate_loc[i]) { 1516b8e80941Smrg case TGSI_INTERPOLATE_LOC_CENTER: 1517b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_PER_PIXEL_MASK; 1518b8e80941Smrg break; 1519b8e80941Smrg case TGSI_INTERPOLATE_LOC_CENTROID: 1520b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_CENTROID_MASK; 1521b8e80941Smrg break; 1522b8e80941Smrg case TGSI_INTERPOLATE_LOC_SAMPLE: 1523b8e80941Smrg barycentricsMask |= SWR_BARYCENTRIC_PER_SAMPLE_MASK; 1524b8e80941Smrg break; 1525b8e80941Smrg } 1526b8e80941Smrg } 1527b8e80941Smrg#endif 1528b8e80941Smrg psState.barycentricsMask = barycentricsMask; 1529b8e80941Smrg psState.usesUAV = false; // XXX 1530b8e80941Smrg psState.forceEarlyZ = false; 1531b8e80941Smrg ctx->api.pfnSwrSetPixelShaderState(ctx->swrContext, &psState); 1532b8e80941Smrg 1533b8e80941Smrg /* JIT sampler state */ 1534b8e80941Smrg if (ctx->dirty & (SWR_NEW_SAMPLER | 1535b8e80941Smrg SWR_NEW_FS)) { 1536b8e80941Smrg swr_update_sampler_state(ctx, 1537b8e80941Smrg PIPE_SHADER_FRAGMENT, 1538b8e80941Smrg key.nr_samplers, 1539b8e80941Smrg ctx->swrDC.samplersFS); 1540b8e80941Smrg } 1541b8e80941Smrg 1542b8e80941Smrg /* JIT sampler view state */ 1543b8e80941Smrg if (ctx->dirty & (SWR_NEW_SAMPLER_VIEW | 1544b8e80941Smrg SWR_NEW_FRAMEBUFFER | 1545b8e80941Smrg SWR_NEW_FS)) { 1546b8e80941Smrg swr_update_texture_state(ctx, 1547b8e80941Smrg PIPE_SHADER_FRAGMENT, 1548b8e80941Smrg key.nr_sampler_views, 1549b8e80941Smrg ctx->swrDC.texturesFS); 1550b8e80941Smrg } 1551b8e80941Smrg } 1552b8e80941Smrg 1553b8e80941Smrg 1554b8e80941Smrg /* VertexShader Constants */ 1555b8e80941Smrg if (ctx->dirty & SWR_NEW_VSCONSTANTS) { 1556b8e80941Smrg swr_update_constants(ctx, PIPE_SHADER_VERTEX); 1557b8e80941Smrg } 1558b8e80941Smrg 1559b8e80941Smrg /* FragmentShader Constants */ 1560b8e80941Smrg if (ctx->dirty & SWR_NEW_FSCONSTANTS) { 1561b8e80941Smrg swr_update_constants(ctx, PIPE_SHADER_FRAGMENT); 1562b8e80941Smrg } 1563b8e80941Smrg 1564b8e80941Smrg /* GeometryShader Constants */ 1565b8e80941Smrg if (ctx->dirty & SWR_NEW_GSCONSTANTS) { 1566b8e80941Smrg swr_update_constants(ctx, PIPE_SHADER_GEOMETRY); 1567b8e80941Smrg } 1568b8e80941Smrg 1569b8e80941Smrg /* Depth/stencil state */ 1570b8e80941Smrg if (ctx->dirty & (SWR_NEW_DEPTH_STENCIL_ALPHA | SWR_NEW_FRAMEBUFFER)) { 1571b8e80941Smrg struct pipe_depth_state *depth = &(ctx->depth_stencil->depth); 1572b8e80941Smrg struct pipe_stencil_state *stencil = ctx->depth_stencil->stencil; 1573b8e80941Smrg SWR_DEPTH_STENCIL_STATE depthStencilState = {{0}}; 1574b8e80941Smrg SWR_DEPTH_BOUNDS_STATE depthBoundsState = {0}; 1575b8e80941Smrg 1576b8e80941Smrg /* XXX, incomplete. Need to flesh out stencil & alpha test state 1577b8e80941Smrg struct pipe_stencil_state *front_stencil = 1578b8e80941Smrg ctx->depth_stencil.stencil[0]; 1579b8e80941Smrg struct pipe_stencil_state *back_stencil = ctx->depth_stencil.stencil[1]; 1580b8e80941Smrg struct pipe_alpha_state alpha; 1581b8e80941Smrg */ 1582b8e80941Smrg if (stencil[0].enabled) { 1583b8e80941Smrg depthStencilState.stencilWriteEnable = 1; 1584b8e80941Smrg depthStencilState.stencilTestEnable = 1; 1585b8e80941Smrg depthStencilState.stencilTestFunc = 1586b8e80941Smrg swr_convert_depth_func(stencil[0].func); 1587b8e80941Smrg 1588b8e80941Smrg depthStencilState.stencilPassDepthPassOp = 1589b8e80941Smrg swr_convert_stencil_op(stencil[0].zpass_op); 1590b8e80941Smrg depthStencilState.stencilPassDepthFailOp = 1591b8e80941Smrg swr_convert_stencil_op(stencil[0].zfail_op); 1592b8e80941Smrg depthStencilState.stencilFailOp = 1593b8e80941Smrg swr_convert_stencil_op(stencil[0].fail_op); 1594b8e80941Smrg depthStencilState.stencilWriteMask = stencil[0].writemask; 1595b8e80941Smrg depthStencilState.stencilTestMask = stencil[0].valuemask; 1596b8e80941Smrg depthStencilState.stencilRefValue = ctx->stencil_ref.ref_value[0]; 1597b8e80941Smrg } 1598b8e80941Smrg if (stencil[1].enabled) { 1599b8e80941Smrg depthStencilState.doubleSidedStencilTestEnable = 1; 1600b8e80941Smrg 1601b8e80941Smrg depthStencilState.backfaceStencilTestFunc = 1602b8e80941Smrg swr_convert_depth_func(stencil[1].func); 1603b8e80941Smrg 1604b8e80941Smrg depthStencilState.backfaceStencilPassDepthPassOp = 1605b8e80941Smrg swr_convert_stencil_op(stencil[1].zpass_op); 1606b8e80941Smrg depthStencilState.backfaceStencilPassDepthFailOp = 1607b8e80941Smrg swr_convert_stencil_op(stencil[1].zfail_op); 1608b8e80941Smrg depthStencilState.backfaceStencilFailOp = 1609b8e80941Smrg swr_convert_stencil_op(stencil[1].fail_op); 1610b8e80941Smrg depthStencilState.backfaceStencilWriteMask = stencil[1].writemask; 1611b8e80941Smrg depthStencilState.backfaceStencilTestMask = stencil[1].valuemask; 1612b8e80941Smrg 1613b8e80941Smrg depthStencilState.backfaceStencilRefValue = 1614b8e80941Smrg ctx->stencil_ref.ref_value[1]; 1615b8e80941Smrg } 1616b8e80941Smrg 1617b8e80941Smrg depthStencilState.depthTestEnable = depth->enabled; 1618b8e80941Smrg depthStencilState.depthTestFunc = swr_convert_depth_func(depth->func); 1619b8e80941Smrg depthStencilState.depthWriteEnable = depth->writemask; 1620b8e80941Smrg ctx->api.pfnSwrSetDepthStencilState(ctx->swrContext, &depthStencilState); 1621b8e80941Smrg 1622b8e80941Smrg depthBoundsState.depthBoundsTestEnable = depth->bounds_test; 1623b8e80941Smrg depthBoundsState.depthBoundsTestMinValue = depth->bounds_min; 1624b8e80941Smrg depthBoundsState.depthBoundsTestMaxValue = depth->bounds_max; 1625b8e80941Smrg ctx->api.pfnSwrSetDepthBoundsState(ctx->swrContext, &depthBoundsState); 1626b8e80941Smrg } 1627b8e80941Smrg 1628b8e80941Smrg /* Blend State */ 1629b8e80941Smrg if (ctx->dirty & (SWR_NEW_BLEND | 1630b8e80941Smrg SWR_NEW_RASTERIZER | 1631b8e80941Smrg SWR_NEW_FRAMEBUFFER | 1632b8e80941Smrg SWR_NEW_DEPTH_STENCIL_ALPHA)) { 1633b8e80941Smrg struct pipe_framebuffer_state *fb = &ctx->framebuffer; 1634b8e80941Smrg 1635b8e80941Smrg SWR_BLEND_STATE blendState; 1636b8e80941Smrg memcpy(&blendState, &ctx->blend->blendState, sizeof(blendState)); 1637b8e80941Smrg blendState.constantColor[0] = ctx->blend_color.color[0]; 1638b8e80941Smrg blendState.constantColor[1] = ctx->blend_color.color[1]; 1639b8e80941Smrg blendState.constantColor[2] = ctx->blend_color.color[2]; 1640b8e80941Smrg blendState.constantColor[3] = ctx->blend_color.color[3]; 1641b8e80941Smrg blendState.alphaTestReference = 1642b8e80941Smrg *((uint32_t*)&ctx->depth_stencil->alpha.ref_value); 1643b8e80941Smrg 1644b8e80941Smrg blendState.sampleMask = ctx->sample_mask; 1645b8e80941Smrg blendState.sampleCount = GetSampleCount(fb->samples); 1646b8e80941Smrg 1647b8e80941Smrg /* If there are no color buffers bound, disable writes on RT0 1648b8e80941Smrg * and skip loop */ 1649b8e80941Smrg if (fb->nr_cbufs == 0) { 1650b8e80941Smrg blendState.renderTarget[0].writeDisableRed = 1; 1651b8e80941Smrg blendState.renderTarget[0].writeDisableGreen = 1; 1652b8e80941Smrg blendState.renderTarget[0].writeDisableBlue = 1; 1653b8e80941Smrg blendState.renderTarget[0].writeDisableAlpha = 1; 1654b8e80941Smrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, 0, NULL); 1655b8e80941Smrg } 1656b8e80941Smrg else 1657b8e80941Smrg for (int target = 0; 1658b8e80941Smrg target < std::min(SWR_NUM_RENDERTARGETS, 1659b8e80941Smrg PIPE_MAX_COLOR_BUFS); 1660b8e80941Smrg target++) { 1661b8e80941Smrg if (!fb->cbufs[target]) 1662b8e80941Smrg continue; 1663b8e80941Smrg 1664b8e80941Smrg struct swr_resource *colorBuffer = 1665b8e80941Smrg swr_resource(fb->cbufs[target]->texture); 1666b8e80941Smrg 1667b8e80941Smrg BLEND_COMPILE_STATE compileState; 1668b8e80941Smrg memset(&compileState, 0, sizeof(compileState)); 1669b8e80941Smrg compileState.format = colorBuffer->swr.format; 1670b8e80941Smrg memcpy(&compileState.blendState, 1671b8e80941Smrg &ctx->blend->compileState[target], 1672b8e80941Smrg sizeof(compileState.blendState)); 1673b8e80941Smrg 1674b8e80941Smrg const SWR_FORMAT_INFO& info = GetFormatInfo(compileState.format); 1675b8e80941Smrg if (compileState.blendState.logicOpEnable && 1676b8e80941Smrg ((info.type[0] == SWR_TYPE_FLOAT) || info.isSRGB)) { 1677b8e80941Smrg compileState.blendState.logicOpEnable = false; 1678b8e80941Smrg } 1679b8e80941Smrg 1680b8e80941Smrg if (info.type[0] == SWR_TYPE_SINT || info.type[0] == SWR_TYPE_UINT) 1681b8e80941Smrg compileState.blendState.blendEnable = false; 1682b8e80941Smrg 1683b8e80941Smrg if (compileState.blendState.blendEnable == false && 1684b8e80941Smrg compileState.blendState.logicOpEnable == false && 1685b8e80941Smrg ctx->depth_stencil->alpha.enabled == 0) { 1686b8e80941Smrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, NULL); 1687b8e80941Smrg continue; 1688b8e80941Smrg } 1689b8e80941Smrg 1690b8e80941Smrg compileState.desc.alphaTestEnable = 1691b8e80941Smrg ctx->depth_stencil->alpha.enabled; 1692b8e80941Smrg compileState.desc.independentAlphaBlendEnable = 1693b8e80941Smrg (compileState.blendState.sourceBlendFactor != 1694b8e80941Smrg compileState.blendState.sourceAlphaBlendFactor) || 1695b8e80941Smrg (compileState.blendState.destBlendFactor != 1696b8e80941Smrg compileState.blendState.destAlphaBlendFactor) || 1697b8e80941Smrg (compileState.blendState.colorBlendFunc != 1698b8e80941Smrg compileState.blendState.alphaBlendFunc); 1699b8e80941Smrg compileState.desc.alphaToCoverageEnable = 1700b8e80941Smrg ctx->blend->pipe.alpha_to_coverage; 1701b8e80941Smrg compileState.desc.sampleMaskEnable = (blendState.sampleMask != 0); 1702b8e80941Smrg compileState.desc.numSamples = fb->samples; 1703b8e80941Smrg 1704b8e80941Smrg compileState.alphaTestFunction = 1705b8e80941Smrg swr_convert_depth_func(ctx->depth_stencil->alpha.func); 1706b8e80941Smrg compileState.alphaTestFormat = ALPHA_TEST_FLOAT32; // xxx 1707b8e80941Smrg 1708b8e80941Smrg compileState.Canonicalize(); 1709b8e80941Smrg 1710b8e80941Smrg PFN_BLEND_JIT_FUNC func = NULL; 1711b8e80941Smrg auto search = ctx->blendJIT->find(compileState); 1712b8e80941Smrg if (search != ctx->blendJIT->end()) { 1713b8e80941Smrg func = search->second; 1714b8e80941Smrg } else { 1715b8e80941Smrg HANDLE hJitMgr = screen->hJitMgr; 1716b8e80941Smrg func = JitCompileBlend(hJitMgr, compileState); 1717b8e80941Smrg debug_printf("BLEND shader %p\n", func); 1718b8e80941Smrg assert(func && "Error: BlendShader = NULL"); 1719b8e80941Smrg 1720b8e80941Smrg ctx->blendJIT->insert(std::make_pair(compileState, func)); 1721b8e80941Smrg } 1722b8e80941Smrg ctx->api.pfnSwrSetBlendFunc(ctx->swrContext, target, func); 1723b8e80941Smrg } 1724b8e80941Smrg 1725b8e80941Smrg ctx->api.pfnSwrSetBlendState(ctx->swrContext, &blendState); 1726b8e80941Smrg } 1727b8e80941Smrg 1728b8e80941Smrg if (ctx->dirty & SWR_NEW_STIPPLE) { 1729b8e80941Smrg swr_update_poly_stipple(ctx); 1730b8e80941Smrg } 1731b8e80941Smrg 1732b8e80941Smrg if (ctx->dirty & (SWR_NEW_VS | SWR_NEW_SO | SWR_NEW_RASTERIZER)) { 1733b8e80941Smrg ctx->vs->soState.rasterizerDisable = 1734b8e80941Smrg ctx->rasterizer->rasterizer_discard; 1735b8e80941Smrg ctx->api.pfnSwrSetSoState(ctx->swrContext, &ctx->vs->soState); 1736b8e80941Smrg 1737b8e80941Smrg pipe_stream_output_info *stream_output = &ctx->vs->pipe.stream_output; 1738b8e80941Smrg 1739b8e80941Smrg for (uint32_t i = 0; i < ctx->num_so_targets; i++) { 1740b8e80941Smrg SWR_STREAMOUT_BUFFER buffer = {0}; 1741b8e80941Smrg if (!ctx->so_targets[i]) 1742b8e80941Smrg continue; 1743b8e80941Smrg buffer.enable = true; 1744b8e80941Smrg buffer.pBuffer = 1745b8e80941Smrg (gfxptr_t)(swr_resource_data(ctx->so_targets[i]->buffer) + 1746b8e80941Smrg ctx->so_targets[i]->buffer_offset); 1747b8e80941Smrg buffer.bufferSize = ctx->so_targets[i]->buffer_size >> 2; 1748b8e80941Smrg buffer.pitch = stream_output->stride[i]; 1749b8e80941Smrg buffer.streamOffset = 0; 1750b8e80941Smrg 1751b8e80941Smrg ctx->api.pfnSwrSetSoBuffers(ctx->swrContext, &buffer, i); 1752b8e80941Smrg } 1753b8e80941Smrg } 1754b8e80941Smrg 1755b8e80941Smrg if (ctx->dirty & (SWR_NEW_CLIP | SWR_NEW_RASTERIZER | SWR_NEW_VS)) { 1756b8e80941Smrg // shader exporting clip distances overrides all user clip planes 1757b8e80941Smrg if (ctx->rasterizer->clip_plane_enable && 1758b8e80941Smrg !ctx->vs->info.base.num_written_clipdistance) 1759b8e80941Smrg { 1760b8e80941Smrg swr_draw_context *pDC = &ctx->swrDC; 1761b8e80941Smrg memcpy(pDC->userClipPlanes, 1762b8e80941Smrg ctx->clip.ucp, 1763b8e80941Smrg sizeof(pDC->userClipPlanes)); 1764b8e80941Smrg } 1765b8e80941Smrg } 1766b8e80941Smrg 1767b8e80941Smrg // set up backend state 1768b8e80941Smrg SWR_BACKEND_STATE backendState = {0}; 1769b8e80941Smrg if (ctx->gs) { 1770b8e80941Smrg backendState.numAttributes = ctx->gs->info.base.num_outputs - 1; 1771b8e80941Smrg } else { 1772b8e80941Smrg backendState.numAttributes = ctx->vs->info.base.num_outputs - 1; 1773b8e80941Smrg if (ctx->fs->info.base.uses_primid) { 1774b8e80941Smrg backendState.numAttributes++; 1775b8e80941Smrg backendState.swizzleEnable = true; 1776b8e80941Smrg for (unsigned i = 0; i < sizeof(backendState.numComponents); i++) { 1777b8e80941Smrg backendState.swizzleMap[i].sourceAttrib = i; 1778b8e80941Smrg } 1779b8e80941Smrg backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].constantSource = 1780b8e80941Smrg SWR_CONSTANT_SOURCE_PRIM_ID; 1781b8e80941Smrg backendState.swizzleMap[ctx->vs->info.base.num_outputs - 1].componentOverrideMask = 1; 1782b8e80941Smrg } 1783b8e80941Smrg } 1784b8e80941Smrg if (ctx->rasterizer->sprite_coord_enable) 1785b8e80941Smrg backendState.numAttributes++; 1786b8e80941Smrg 1787b8e80941Smrg backendState.numAttributes = std::min((size_t)backendState.numAttributes, 1788b8e80941Smrg sizeof(backendState.numComponents)); 1789b8e80941Smrg for (unsigned i = 0; i < backendState.numAttributes; i++) 1790b8e80941Smrg backendState.numComponents[i] = 4; 1791b8e80941Smrg backendState.constantInterpolationMask = ctx->fs->constantMask | 1792b8e80941Smrg (ctx->rasterizer->flatshade ? ctx->fs->flatConstantMask : 0); 1793b8e80941Smrg backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask; 1794b8e80941Smrg 1795b8e80941Smrg struct tgsi_shader_info *pLastFE = 1796b8e80941Smrg ctx->gs ? 1797b8e80941Smrg &ctx->gs->info.base : 1798b8e80941Smrg &ctx->vs->info.base; 1799b8e80941Smrg backendState.readRenderTargetArrayIndex = pLastFE->writes_layer; 1800b8e80941Smrg backendState.readViewportArrayIndex = pLastFE->writes_viewport_index; 1801b8e80941Smrg backendState.vertexAttribOffset = VERTEX_ATTRIB_START_SLOT; // TODO: optimize 1802b8e80941Smrg 1803b8e80941Smrg backendState.clipDistanceMask = 1804b8e80941Smrg ctx->vs->info.base.num_written_clipdistance ? 1805b8e80941Smrg ctx->vs->info.base.clipdist_writemask & ctx->rasterizer->clip_plane_enable : 1806b8e80941Smrg ctx->rasterizer->clip_plane_enable; 1807b8e80941Smrg 1808b8e80941Smrg backendState.cullDistanceMask = 1809b8e80941Smrg ctx->vs->info.base.culldist_writemask << ctx->vs->info.base.num_written_clipdistance; 1810b8e80941Smrg 1811b8e80941Smrg // Assume old layout of SGV, POSITION, CLIPCULL, ATTRIB 1812b8e80941Smrg backendState.vertexClipCullOffset = backendState.vertexAttribOffset - 2; 1813b8e80941Smrg 1814b8e80941Smrg ctx->api.pfnSwrSetBackendState(ctx->swrContext, &backendState); 1815b8e80941Smrg 1816b8e80941Smrg /* Ensure that any in-progress attachment change StoreTiles finish */ 1817b8e80941Smrg if (swr_is_fence_pending(screen->flush_fence)) 1818b8e80941Smrg swr_fence_finish(pipe->screen, NULL, screen->flush_fence, 0); 1819b8e80941Smrg 1820b8e80941Smrg /* Finally, update the in-use status of all resources involved in draw */ 1821b8e80941Smrg swr_update_resource_status(pipe, p_draw_info); 1822b8e80941Smrg 1823b8e80941Smrg ctx->dirty = post_update_dirty_flags; 1824b8e80941Smrg} 1825b8e80941Smrg 1826b8e80941Smrg 1827b8e80941Smrgstatic struct pipe_stream_output_target * 1828b8e80941Smrgswr_create_so_target(struct pipe_context *pipe, 1829b8e80941Smrg struct pipe_resource *buffer, 1830b8e80941Smrg unsigned buffer_offset, 1831b8e80941Smrg unsigned buffer_size) 1832b8e80941Smrg{ 1833b8e80941Smrg struct pipe_stream_output_target *target; 1834b8e80941Smrg 1835b8e80941Smrg target = CALLOC_STRUCT(pipe_stream_output_target); 1836b8e80941Smrg if (!target) 1837b8e80941Smrg return NULL; 1838b8e80941Smrg 1839b8e80941Smrg target->context = pipe; 1840b8e80941Smrg target->reference.count = 1; 1841b8e80941Smrg pipe_resource_reference(&target->buffer, buffer); 1842b8e80941Smrg target->buffer_offset = buffer_offset; 1843b8e80941Smrg target->buffer_size = buffer_size; 1844b8e80941Smrg return target; 1845b8e80941Smrg} 1846b8e80941Smrg 1847b8e80941Smrgstatic void 1848b8e80941Smrgswr_destroy_so_target(struct pipe_context *pipe, 1849b8e80941Smrg struct pipe_stream_output_target *target) 1850b8e80941Smrg{ 1851b8e80941Smrg pipe_resource_reference(&target->buffer, NULL); 1852b8e80941Smrg FREE(target); 1853b8e80941Smrg} 1854b8e80941Smrg 1855b8e80941Smrgstatic void 1856b8e80941Smrgswr_set_so_targets(struct pipe_context *pipe, 1857b8e80941Smrg unsigned num_targets, 1858b8e80941Smrg struct pipe_stream_output_target **targets, 1859b8e80941Smrg const unsigned *offsets) 1860b8e80941Smrg{ 1861b8e80941Smrg struct swr_context *swr = swr_context(pipe); 1862b8e80941Smrg uint32_t i; 1863b8e80941Smrg 1864b8e80941Smrg assert(num_targets <= MAX_SO_STREAMS); 1865b8e80941Smrg 1866b8e80941Smrg for (i = 0; i < num_targets; i++) { 1867b8e80941Smrg pipe_so_target_reference( 1868b8e80941Smrg (struct pipe_stream_output_target **)&swr->so_targets[i], 1869b8e80941Smrg targets[i]); 1870b8e80941Smrg } 1871b8e80941Smrg 1872b8e80941Smrg for (/* fall-through */; i < swr->num_so_targets; i++) { 1873b8e80941Smrg pipe_so_target_reference( 1874b8e80941Smrg (struct pipe_stream_output_target **)&swr->so_targets[i], NULL); 1875b8e80941Smrg } 1876b8e80941Smrg 1877b8e80941Smrg swr->num_so_targets = num_targets; 1878b8e80941Smrg 1879b8e80941Smrg swr->dirty |= SWR_NEW_SO; 1880b8e80941Smrg} 1881b8e80941Smrg 1882b8e80941Smrg 1883b8e80941Smrgvoid 1884b8e80941Smrgswr_state_init(struct pipe_context *pipe) 1885b8e80941Smrg{ 1886b8e80941Smrg pipe->create_blend_state = swr_create_blend_state; 1887b8e80941Smrg pipe->bind_blend_state = swr_bind_blend_state; 1888b8e80941Smrg pipe->delete_blend_state = swr_delete_blend_state; 1889b8e80941Smrg 1890b8e80941Smrg pipe->create_depth_stencil_alpha_state = swr_create_depth_stencil_state; 1891b8e80941Smrg pipe->bind_depth_stencil_alpha_state = swr_bind_depth_stencil_state; 1892b8e80941Smrg pipe->delete_depth_stencil_alpha_state = swr_delete_depth_stencil_state; 1893b8e80941Smrg 1894b8e80941Smrg pipe->create_rasterizer_state = swr_create_rasterizer_state; 1895b8e80941Smrg pipe->bind_rasterizer_state = swr_bind_rasterizer_state; 1896b8e80941Smrg pipe->delete_rasterizer_state = swr_delete_rasterizer_state; 1897b8e80941Smrg 1898b8e80941Smrg pipe->create_sampler_state = swr_create_sampler_state; 1899b8e80941Smrg pipe->bind_sampler_states = swr_bind_sampler_states; 1900b8e80941Smrg pipe->delete_sampler_state = swr_delete_sampler_state; 1901b8e80941Smrg 1902b8e80941Smrg pipe->create_sampler_view = swr_create_sampler_view; 1903b8e80941Smrg pipe->set_sampler_views = swr_set_sampler_views; 1904b8e80941Smrg pipe->sampler_view_destroy = swr_sampler_view_destroy; 1905b8e80941Smrg 1906b8e80941Smrg pipe->create_vs_state = swr_create_vs_state; 1907b8e80941Smrg pipe->bind_vs_state = swr_bind_vs_state; 1908b8e80941Smrg pipe->delete_vs_state = swr_delete_vs_state; 1909b8e80941Smrg 1910b8e80941Smrg pipe->create_fs_state = swr_create_fs_state; 1911b8e80941Smrg pipe->bind_fs_state = swr_bind_fs_state; 1912b8e80941Smrg pipe->delete_fs_state = swr_delete_fs_state; 1913b8e80941Smrg 1914b8e80941Smrg pipe->create_gs_state = swr_create_gs_state; 1915b8e80941Smrg pipe->bind_gs_state = swr_bind_gs_state; 1916b8e80941Smrg pipe->delete_gs_state = swr_delete_gs_state; 1917b8e80941Smrg 1918b8e80941Smrg pipe->set_constant_buffer = swr_set_constant_buffer; 1919b8e80941Smrg 1920b8e80941Smrg pipe->create_vertex_elements_state = swr_create_vertex_elements_state; 1921b8e80941Smrg pipe->bind_vertex_elements_state = swr_bind_vertex_elements_state; 1922b8e80941Smrg pipe->delete_vertex_elements_state = swr_delete_vertex_elements_state; 1923b8e80941Smrg 1924b8e80941Smrg pipe->set_vertex_buffers = swr_set_vertex_buffers; 1925b8e80941Smrg 1926b8e80941Smrg pipe->set_polygon_stipple = swr_set_polygon_stipple; 1927b8e80941Smrg pipe->set_clip_state = swr_set_clip_state; 1928b8e80941Smrg pipe->set_scissor_states = swr_set_scissor_states; 1929b8e80941Smrg pipe->set_viewport_states = swr_set_viewport_states; 1930b8e80941Smrg 1931b8e80941Smrg pipe->set_framebuffer_state = swr_set_framebuffer_state; 1932b8e80941Smrg 1933b8e80941Smrg pipe->set_blend_color = swr_set_blend_color; 1934b8e80941Smrg pipe->set_stencil_ref = swr_set_stencil_ref; 1935b8e80941Smrg 1936b8e80941Smrg pipe->set_sample_mask = swr_set_sample_mask; 1937b8e80941Smrg pipe->get_sample_position = swr_get_sample_position; 1938b8e80941Smrg 1939b8e80941Smrg pipe->create_stream_output_target = swr_create_so_target; 1940b8e80941Smrg pipe->stream_output_target_destroy = swr_destroy_so_target; 1941b8e80941Smrg pipe->set_stream_output_targets = swr_set_so_targets; 1942b8e80941Smrg} 1943