1 /*
2  * Copyright © 2011 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 
24 #include "brw_context.h"
25 #include "brw_state.h"
26 #include "brw_defines.h"
27 #include "brw_util.h"
28 #include "program/prog_parameter.h"
29 #include "program/prog_statevars.h"
30 #include "intel_batchbuffer.h"
31 
32 static void
upload_vs_state(struct brw_context * brw)33 upload_vs_state(struct brw_context *brw)
34 {
35    struct intel_context *intel = &brw->intel;
36    uint32_t floating_point_mode = 0;
37    const int max_threads_shift = brw->intel.is_haswell ?
38       HSW_VS_MAX_THREADS_SHIFT : GEN6_VS_MAX_THREADS_SHIFT;
39 
40    gen7_emit_vs_workaround_flush(intel);
41 
42    /* BRW_NEW_VS_BINDING_TABLE */
43    BEGIN_BATCH(2);
44    OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_VS << 16 | (2 - 2));
45    OUT_BATCH(brw->vs.bind_bo_offset);
46    ADVANCE_BATCH();
47 
48    /* CACHE_NEW_SAMPLER */
49    BEGIN_BATCH(2);
50    OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_VS << 16 | (2 - 2));
51    OUT_BATCH(brw->sampler.offset);
52    ADVANCE_BATCH();
53 
54    if (brw->vs.push_const_size == 0) {
55       /* Disable the push constant buffers. */
56       BEGIN_BATCH(7);
57       OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (7 - 2));
58       OUT_BATCH(0);
59       OUT_BATCH(0);
60       OUT_BATCH(0);
61       OUT_BATCH(0);
62       OUT_BATCH(0);
63       OUT_BATCH(0);
64       ADVANCE_BATCH();
65    } else {
66       BEGIN_BATCH(7);
67       OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (7 - 2));
68       OUT_BATCH(brw->vs.push_const_size);
69       OUT_BATCH(0);
70       /* Pointer to the VS constant buffer.  Covered by the set of
71        * state flags from gen6_prepare_wm_contants
72        */
73       OUT_BATCH(brw->vs.push_const_offset);
74       OUT_BATCH(0);
75       OUT_BATCH(0);
76       OUT_BATCH(0);
77       ADVANCE_BATCH();
78    }
79 
80    /* Use ALT floating point mode for ARB vertex programs, because they
81     * require 0^0 == 1.
82     */
83    if (intel->ctx.Shader.CurrentVertexProgram == NULL)
84       floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT;
85 
86    BEGIN_BATCH(6);
87    OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2));
88    OUT_BATCH(brw->vs.prog_offset);
89    OUT_BATCH(floating_point_mode |
90 	     ((ALIGN(brw->sampler.count, 4)/4) << GEN6_VS_SAMPLER_COUNT_SHIFT));
91 
92    if (brw->vs.prog_data->total_scratch) {
93       OUT_RELOC(brw->vs.scratch_bo,
94 		I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
95 		ffs(brw->vs.prog_data->total_scratch) - 11);
96    } else {
97       OUT_BATCH(0);
98    }
99 
100    OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) |
101 	     (brw->vs.prog_data->urb_read_length << GEN6_VS_URB_READ_LENGTH_SHIFT) |
102 	     (0 << GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT));
103 
104    OUT_BATCH(((brw->max_vs_threads - 1) << max_threads_shift) |
105 	     GEN6_VS_STATISTICS_ENABLE |
106 	     GEN6_VS_ENABLE);
107    ADVANCE_BATCH();
108 }
109 
110 const struct brw_tracked_state gen7_vs_state = {
111    .dirty = {
112       .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
113       .brw   = (BRW_NEW_CONTEXT |
114 		BRW_NEW_VERTEX_PROGRAM |
115 		BRW_NEW_VS_BINDING_TABLE |
116 		BRW_NEW_BATCH),
117       .cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER
118    },
119    .emit = upload_vs_state,
120 };
121