0001
0002
0003
0004
0005
0006 #include "gem/i915_gem_internal.h"
0007
0008 #include "i915_drv.h"
0009 #include "intel_renderstate.h"
0010 #include "intel_context.h"
0011 #include "intel_gpu_commands.h"
0012 #include "intel_ring.h"
0013
0014 static const struct intel_renderstate_rodata *
0015 render_state_get_rodata(const struct intel_engine_cs *engine)
0016 {
0017 if (engine->class != RENDER_CLASS)
0018 return NULL;
0019
0020 switch (GRAPHICS_VER(engine->i915)) {
0021 case 6:
0022 return &gen6_null_state;
0023 case 7:
0024 return &gen7_null_state;
0025 case 8:
0026 return &gen8_null_state;
0027 case 9:
0028 return &gen9_null_state;
0029 }
0030
0031 return NULL;
0032 }
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #define OUT_BATCH(batch, i, val) \
0044 do { \
0045 if ((i) >= PAGE_SIZE / sizeof(u32)) \
0046 goto out; \
0047 (batch)[(i)++] = (val); \
0048 } while (0)
0049
0050 static int render_state_setup(struct intel_renderstate *so,
0051 struct drm_i915_private *i915)
0052 {
0053 const struct intel_renderstate_rodata *rodata = so->rodata;
0054 unsigned int i = 0, reloc_index = 0;
0055 int ret = -EINVAL;
0056 u32 *d;
0057
0058 d = i915_gem_object_pin_map(so->vma->obj, I915_MAP_WB);
0059 if (IS_ERR(d))
0060 return PTR_ERR(d);
0061
0062 while (i < rodata->batch_items) {
0063 u32 s = rodata->batch[i];
0064
0065 if (i * 4 == rodata->reloc[reloc_index]) {
0066 u64 r = s + so->vma->node.start;
0067
0068 s = lower_32_bits(r);
0069 if (HAS_64BIT_RELOC(i915)) {
0070 if (i + 1 >= rodata->batch_items ||
0071 rodata->batch[i + 1] != 0)
0072 goto out;
0073
0074 d[i++] = s;
0075 s = upper_32_bits(r);
0076 }
0077
0078 reloc_index++;
0079 }
0080
0081 d[i++] = s;
0082 }
0083
0084 if (rodata->reloc[reloc_index] != -1) {
0085 drm_err(&i915->drm, "only %d relocs resolved\n", reloc_index);
0086 goto out;
0087 }
0088
0089 so->batch_offset = i915_ggtt_offset(so->vma);
0090 so->batch_size = rodata->batch_items * sizeof(u32);
0091
0092 while (i % CACHELINE_DWORDS)
0093 OUT_BATCH(d, i, MI_NOOP);
0094
0095 so->aux_offset = i * sizeof(u32);
0096
0097 if (HAS_POOLED_EU(i915)) {
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 u32 eu_pool_config = 0x00777000;
0115
0116 OUT_BATCH(d, i, GEN9_MEDIA_POOL_STATE);
0117 OUT_BATCH(d, i, GEN9_MEDIA_POOL_ENABLE);
0118 OUT_BATCH(d, i, eu_pool_config);
0119 OUT_BATCH(d, i, 0);
0120 OUT_BATCH(d, i, 0);
0121 OUT_BATCH(d, i, 0);
0122 }
0123
0124 OUT_BATCH(d, i, MI_BATCH_BUFFER_END);
0125 so->aux_size = i * sizeof(u32) - so->aux_offset;
0126 so->aux_offset += so->batch_offset;
0127
0128
0129
0130
0131 so->aux_size = ALIGN(so->aux_size, 8);
0132
0133 ret = 0;
0134 out:
0135 __i915_gem_object_flush_map(so->vma->obj, 0, i * sizeof(u32));
0136 __i915_gem_object_release_map(so->vma->obj);
0137 return ret;
0138 }
0139
0140 #undef OUT_BATCH
0141
0142 int intel_renderstate_init(struct intel_renderstate *so,
0143 struct intel_context *ce)
0144 {
0145 struct intel_engine_cs *engine = ce->engine;
0146 struct drm_i915_gem_object *obj = NULL;
0147 int err;
0148
0149 memset(so, 0, sizeof(*so));
0150
0151 so->rodata = render_state_get_rodata(engine);
0152 if (so->rodata) {
0153 if (so->rodata->batch_items * 4 > PAGE_SIZE)
0154 return -EINVAL;
0155
0156 obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
0157 if (IS_ERR(obj))
0158 return PTR_ERR(obj);
0159
0160 so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL);
0161 if (IS_ERR(so->vma)) {
0162 err = PTR_ERR(so->vma);
0163 goto err_obj;
0164 }
0165 }
0166
0167 i915_gem_ww_ctx_init(&so->ww, true);
0168 retry:
0169 err = intel_context_pin_ww(ce, &so->ww);
0170 if (err)
0171 goto err_fini;
0172
0173
0174 if (!err && !so->rodata)
0175 return 0;
0176
0177 err = i915_gem_object_lock(so->vma->obj, &so->ww);
0178 if (err)
0179 goto err_context;
0180
0181 err = i915_vma_pin_ww(so->vma, &so->ww, 0, 0, PIN_GLOBAL | PIN_HIGH);
0182 if (err)
0183 goto err_context;
0184
0185 err = render_state_setup(so, engine->i915);
0186 if (err)
0187 goto err_unpin;
0188
0189 return 0;
0190
0191 err_unpin:
0192 i915_vma_unpin(so->vma);
0193 err_context:
0194 intel_context_unpin(ce);
0195 err_fini:
0196 if (err == -EDEADLK) {
0197 err = i915_gem_ww_ctx_backoff(&so->ww);
0198 if (!err)
0199 goto retry;
0200 }
0201 i915_gem_ww_ctx_fini(&so->ww);
0202 err_obj:
0203 if (obj)
0204 i915_gem_object_put(obj);
0205 so->vma = NULL;
0206 return err;
0207 }
0208
0209 int intel_renderstate_emit(struct intel_renderstate *so,
0210 struct i915_request *rq)
0211 {
0212 struct intel_engine_cs *engine = rq->engine;
0213 int err;
0214
0215 if (!so->vma)
0216 return 0;
0217
0218 err = i915_request_await_object(rq, so->vma->obj, false);
0219 if (err == 0)
0220 err = i915_vma_move_to_active(so->vma, rq, 0);
0221 if (err)
0222 return err;
0223
0224 err = engine->emit_bb_start(rq,
0225 so->batch_offset, so->batch_size,
0226 I915_DISPATCH_SECURE);
0227 if (err)
0228 return err;
0229
0230 if (so->aux_size > 8) {
0231 err = engine->emit_bb_start(rq,
0232 so->aux_offset, so->aux_size,
0233 I915_DISPATCH_SECURE);
0234 if (err)
0235 return err;
0236 }
0237
0238 return 0;
0239 }
0240
0241 void intel_renderstate_fini(struct intel_renderstate *so,
0242 struct intel_context *ce)
0243 {
0244 if (so->vma) {
0245 i915_vma_unpin(so->vma);
0246 i915_vma_close(so->vma);
0247 }
0248
0249 intel_context_unpin(ce);
0250 i915_gem_ww_ctx_fini(&so->ww);
0251
0252 if (so->vma)
0253 i915_gem_object_put(so->vma->obj);
0254 }