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 (at) 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 Gen7+. 31 */ 32 33 #include "main/imports.h" 34 #include "main/condrender.h" 35 36 #include "brw_context.h" 37 #include "brw_defines.h" 38 #include "intel_batchbuffer.h" 39 40 static void 41 set_predicate_enable(struct brw_context *brw, 42 bool value) 43 { 44 if (value) 45 brw->predicate.state = BRW_PREDICATE_STATE_RENDER; 46 else 47 brw->predicate.state = BRW_PREDICATE_STATE_DONT_RENDER; 48 } 49 50 static void 51 set_predicate_for_result(struct brw_context *brw, 52 struct brw_query_object *query, 53 bool inverted) 54 { 55 int load_op; 56 57 assert(query->bo != NULL); 58 59 /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM 60 * command when loading the values into the predicate source registers for 61 * conditional rendering. 62 */ 63 brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE); 64 65 brw_load_register_mem64(brw, 66 MI_PREDICATE_SRC0, 67 query->bo, 68 I915_GEM_DOMAIN_INSTRUCTION, 69 0, /* write domain */ 70 0 /* offset */); 71 brw_load_register_mem64(brw, 72 MI_PREDICATE_SRC1, 73 query->bo, 74 I915_GEM_DOMAIN_INSTRUCTION, 75 0, /* write domain */ 76 8 /* offset */); 77 78 if (inverted) 79 load_op = MI_PREDICATE_LOADOP_LOAD; 80 else 81 load_op = MI_PREDICATE_LOADOP_LOADINV; 82 83 BEGIN_BATCH(1); 84 OUT_BATCH(GEN7_MI_PREDICATE | 85 load_op | 86 MI_PREDICATE_COMBINEOP_SET | 87 MI_PREDICATE_COMPAREOP_SRCS_EQUAL); 88 ADVANCE_BATCH(); 89 90 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT; 91 } 92 93 static void 94 brw_begin_conditional_render(struct gl_context *ctx, 95 struct gl_query_object *q, 96 GLenum mode) 97 { 98 struct brw_context *brw = brw_context(ctx); 99 struct brw_query_object *query = (struct brw_query_object *) q; 100 bool inverted; 101 102 if (!brw->predicate.supported) 103 return; 104 105 switch (mode) { 106 case GL_QUERY_WAIT: 107 case GL_QUERY_NO_WAIT: 108 case GL_QUERY_BY_REGION_WAIT: 109 case GL_QUERY_BY_REGION_NO_WAIT: 110 inverted = false; 111 break; 112 case GL_QUERY_WAIT_INVERTED: 113 case GL_QUERY_NO_WAIT_INVERTED: 114 case GL_QUERY_BY_REGION_WAIT_INVERTED: 115 case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 116 inverted = true; 117 break; 118 default: 119 unreachable("Unexpected conditional render mode"); 120 } 121 122 /* If there are already samples from a BLT operation or if the query object 123 * is ready then we can avoid looking at the values in the buffer and just 124 * decide whether to draw using the CPU without stalling. 125 */ 126 if (query->Base.Result || query->Base.Ready) 127 set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted); 128 else 129 set_predicate_for_result(brw, query, inverted); 130 } 131 132 static void 133 brw_end_conditional_render(struct gl_context *ctx, 134 struct gl_query_object *q) 135 { 136 struct brw_context *brw = brw_context(ctx); 137 138 /* When there is no longer a conditional render in progress it should 139 * always render. 140 */ 141 brw->predicate.state = BRW_PREDICATE_STATE_RENDER; 142 } 143 144 void 145 brw_init_conditional_render_functions(struct dd_function_table *functions) 146 { 147 functions->BeginConditionalRender = brw_begin_conditional_render; 148 functions->EndConditionalRender = brw_end_conditional_render; 149 } 150 151 bool 152 brw_check_conditional_render(struct brw_context *brw) 153 { 154 if (brw->predicate.supported) { 155 /* In some cases it is possible to determine that the primitives should 156 * be skipped without needing the predicate enable bit and still without 157 * stalling. 158 */ 159 return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER; 160 } else if (brw->ctx.Query.CondRenderQuery) { 161 perf_debug("Conditional rendering is implemented in software and may " 162 "stall.\n"); 163 return _mesa_check_conditional_render(&brw->ctx); 164 } else { 165 return true; 166 } 167 } 168