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 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 40static void 41set_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 50static void 51set_predicate_for_overflow_query(struct brw_context *brw, 52 struct brw_query_object *query, 53 int stream_start, int count) 54{ 55 if (!can_do_mi_math_and_lrr(brw->screen)) { 56 brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY; 57 return; 58 } 59 60 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT; 61 62 /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM 63 * command when loading the values into the predicate source registers for 64 * conditional rendering. 65 */ 66 brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE); 67 68 hsw_overflow_result_to_gpr0(brw, query, count); 69 brw_load_register_reg64(brw, MI_PREDICATE_SRC0, HSW_CS_GPR(0)); 70 brw_load_register_imm64(brw, MI_PREDICATE_SRC1, 0ull); 71} 72 73static void 74set_predicate_for_occlusion_query(struct brw_context *brw, 75 struct brw_query_object *query) 76{ 77 if (!brw->predicate.supported) { 78 brw->predicate.state = BRW_PREDICATE_STATE_STALL_FOR_QUERY; 79 return; 80 } 81 82 brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT; 83 84 /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM 85 * command when loading the values into the predicate source registers for 86 * conditional rendering. 87 */ 88 brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE); 89 90 brw_load_register_mem64(brw, MI_PREDICATE_SRC0, query->bo, 0 /* offset */); 91 brw_load_register_mem64(brw, MI_PREDICATE_SRC1, query->bo, 8 /* offset */); 92} 93 94static void 95set_predicate_for_result(struct brw_context *brw, 96 struct brw_query_object *query, 97 bool inverted) 98{ 99 int load_op; 100 101 assert(query->bo != NULL); 102 103 switch (query->Base.Target) { 104 case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB: 105 set_predicate_for_overflow_query(brw, query, 0, 1); 106 break; 107 case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB: 108 set_predicate_for_overflow_query(brw, query, 0, MAX_VERTEX_STREAMS); 109 break; 110 default: 111 set_predicate_for_occlusion_query(brw, query); 112 } 113 114 if (brw->predicate.state == BRW_PREDICATE_STATE_USE_BIT) { 115 if (inverted) 116 load_op = MI_PREDICATE_LOADOP_LOAD; 117 else 118 load_op = MI_PREDICATE_LOADOP_LOADINV; 119 120 BEGIN_BATCH(1); 121 OUT_BATCH(GEN7_MI_PREDICATE | 122 load_op | 123 MI_PREDICATE_COMBINEOP_SET | 124 MI_PREDICATE_COMPAREOP_SRCS_EQUAL); 125 ADVANCE_BATCH(); 126 } 127} 128 129static void 130brw_begin_conditional_render(struct gl_context *ctx, 131 struct gl_query_object *q, 132 GLenum mode) 133{ 134 struct brw_context *brw = brw_context(ctx); 135 struct brw_query_object *query = (struct brw_query_object *) q; 136 bool inverted; 137 138 switch (mode) { 139 case GL_QUERY_WAIT: 140 case GL_QUERY_NO_WAIT: 141 case GL_QUERY_BY_REGION_WAIT: 142 case GL_QUERY_BY_REGION_NO_WAIT: 143 inverted = false; 144 break; 145 case GL_QUERY_WAIT_INVERTED: 146 case GL_QUERY_NO_WAIT_INVERTED: 147 case GL_QUERY_BY_REGION_WAIT_INVERTED: 148 case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 149 inverted = true; 150 break; 151 default: 152 unreachable("Unexpected conditional render mode"); 153 } 154 155 /* If there are already samples from a BLT operation or if the query object 156 * is ready then we can avoid looking at the values in the buffer and just 157 * decide whether to draw using the CPU without stalling. 158 */ 159 if (query->Base.Result || query->Base.Ready) 160 set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted); 161 else 162 set_predicate_for_result(brw, query, inverted); 163} 164 165static void 166brw_end_conditional_render(struct gl_context *ctx, 167 struct gl_query_object *q) 168{ 169 struct brw_context *brw = brw_context(ctx); 170 171 /* When there is no longer a conditional render in progress it should 172 * always render. 173 */ 174 brw->predicate.state = BRW_PREDICATE_STATE_RENDER; 175} 176 177void 178brw_init_conditional_render_functions(struct dd_function_table *functions) 179{ 180 functions->BeginConditionalRender = brw_begin_conditional_render; 181 functions->EndConditionalRender = brw_end_conditional_render; 182} 183 184bool 185brw_check_conditional_render(struct brw_context *brw) 186{ 187 if (brw->predicate.state == BRW_PREDICATE_STATE_STALL_FOR_QUERY) { 188 perf_debug("Conditional rendering is implemented in software and may " 189 "stall.\n"); 190 return _mesa_check_conditional_render(&brw->ctx); 191 } 192 193 return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER; 194} 195