1/* 2 * Copyright © 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Neil Roberts <neil@linux.intel.com> 25 */ 26 27/** @file brw_conditional_render.c 28 * 29 * Support for conditional rendering based on query objects 30 * (GL_NV_conditional_render, GL_ARB_conditional_render_inverted) on Gfx7+. 31 */ 32 33#include "main/condrender.h" 34 35#include "brw_context.h" 36#include "brw_defines.h" 37#include "brw_batch.h" 38 39static void 40set_predicate_enable(struct brw_context *brw, 41 bool value) 42{ 43 if (value) 44 brw->predicate.state = BRW_PREDICATE_STATE_RENDER; 45 else 46 brw->predicate.state = BRW_PREDICATE_STATE_DONT_RENDER; 47} 48 49static void 50set_predicate_for_overflow_query(struct brw_context *brw, 51 struct brw_query_object *query, 52 int stream_start, int count) 53{ 54 if (!can_do_mi_math_and_lrr(brw->screen)) { 55 brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY; 56 return; 57 } 58 59 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT; 60 61 /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM 62 * command when loading the values into the predicate source registers for 63 * conditional rendering. 64 */ 65 brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE); 66 67 hsw_overflow_result_to_gpr0(brw, query, count); 68 brw_load_register_reg64(brw, MI_PREDICATE_SRC0, HSW_CS_GPR(0)); 69 brw_load_register_imm64(brw, MI_PREDICATE_SRC1, 0ull); 70} 71 72static void 73set_predicate_for_occlusion_query(struct brw_context *brw, 74 struct brw_query_object *query) 75{ 76 if (!brw->predicate.supported) { 77 brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY; 78 return; 79 } 80 81 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT; 82 83 /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM 84 * command when loading the values into the predicate source registers for 85 * conditional rendering. 86 */ 87 brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE); 88 89 brw_load_register_mem64(brw, MI_PREDICATE_SRC0, query->bo, 0 /* offset */); 90 brw_load_register_mem64(brw, MI_PREDICATE_SRC1, query->bo, 8 /* offset */); 91} 92 93static void 94set_predicate_for_result(struct brw_context *brw, 95 struct brw_query_object *query, 96 bool inverted) 97{ 98 int load_op; 99 100 assert(query->bo != NULL); 101 102 switch (query->Base.Target) { 103 case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB: 104 set_predicate_for_overflow_query(brw, query, 0, 1); 105 break; 106 case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB: 107 set_predicate_for_overflow_query(brw, query, 0, MAX_VERTEX_STREAMS); 108 break; 109 default: 110 set_predicate_for_occlusion_query(brw, query); 111 } 112 113 if (brw->predicate.state == BRW_PREDICATE_STATE_USE_BIT) { 114 if (inverted) 115 load_op = MI_PREDICATE_LOADOP_LOAD; 116 else 117 load_op = MI_PREDICATE_LOADOP_LOADINV; 118 119 BEGIN_BATCH(1); 120 OUT_BATCH(GFX7_MI_PREDICATE | 121 load_op | 122 MI_PREDICATE_COMBINEOP_SET | 123 MI_PREDICATE_COMPAREOP_SRCS_EQUAL); 124 ADVANCE_BATCH(); 125 } 126} 127 128static void 129brw_begin_conditional_render(struct gl_context *ctx, 130 struct gl_query_object *q, 131 GLenum mode) 132{ 133 struct brw_context *brw = brw_context(ctx); 134 struct brw_query_object *query = (struct brw_query_object *) q; 135 bool inverted; 136 137 switch (mode) { 138 case GL_QUERY_WAIT: 139 case GL_QUERY_NO_WAIT: 140 case GL_QUERY_BY_REGION_WAIT: 141 case GL_QUERY_BY_REGION_NO_WAIT: 142 inverted = false; 143 break; 144 case GL_QUERY_WAIT_INVERTED: 145 case GL_QUERY_NO_WAIT_INVERTED: 146 case GL_QUERY_BY_REGION_WAIT_INVERTED: 147 case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 148 inverted = true; 149 break; 150 default: 151 unreachable("Unexpected conditional render mode"); 152 } 153 154 /* If there are already samples from a BLT operation or if the query object 155 * is ready then we can avoid looking at the values in the buffer and just 156 * decide whether to draw using the CPU without stalling. 157 */ 158 if (query->Base.Result || query->Base.Ready) 159 set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted); 160 else 161 set_predicate_for_result(brw, query, inverted); 162} 163 164static void 165brw_end_conditional_render(struct gl_context *ctx, 166 struct gl_query_object *q) 167{ 168 struct brw_context *brw = brw_context(ctx); 169 170 /* When there is no longer a conditional render in progress it should 171 * always render. 172 */ 173 brw->predicate.state = BRW_PREDICATE_STATE_RENDER; 174} 175 176void 177brw_init_conditional_render_functions(struct dd_function_table *functions) 178{ 179 functions->BeginConditionalRender = brw_begin_conditional_render; 180 functions->EndConditionalRender = brw_end_conditional_render; 181} 182 183bool 184brw_check_conditional_render(struct brw_context *brw) 185{ 186 if (brw->predicate.state == BRW_PREDICATE_STATE_STALL_FOR_QUERY) { 187 perf_debug("Conditional rendering is implemented in software and may " 188 "stall.\n"); 189 return _mesa_check_conditional_render(&brw->ctx); 190 } 191 192 return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER; 193} 194