vc4_draw.c revision 848b8605
1/* 2 * Copyright (c) 2014 Scott Mansell 3 * Copyright © 2014 Broadcom 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include <stdio.h> 26 27#include "util/u_format.h" 28#include "util/u_pack_color.h" 29#include "indices/u_primconvert.h" 30 31#include "vc4_context.h" 32#include "vc4_resource.h" 33 34/** 35 * Does the initial bining command list setup for drawing to a given FBO. 36 */ 37static void 38vc4_start_draw(struct vc4_context *vc4) 39{ 40 if (vc4->needs_flush) 41 return; 42 43 uint32_t width = vc4->framebuffer.width; 44 uint32_t height = vc4->framebuffer.height; 45 uint32_t tilew = align(width, 64) / 64; 46 uint32_t tileh = align(height, 64) / 64; 47 48 /* Tile alloc memory setup: We use an initial alloc size of 32b. The 49 * hardware then aligns that to 256b (we use 4096, because all of our 50 * BO allocations align to that anyway), then for some reason the 51 * simulator wants an extra page available, even if you have overflow 52 * memory set up. 53 */ 54 uint32_t tile_alloc_size = 32 * tilew * tileh; 55 tile_alloc_size = align(tile_alloc_size, 4096); 56 tile_alloc_size += 4096; 57 uint32_t tile_state_size = 48 * tilew * tileh; 58 if (!vc4->tile_alloc || vc4->tile_alloc->size < tile_alloc_size) { 59 vc4_bo_unreference(&vc4->tile_alloc); 60 vc4->tile_alloc = vc4_bo_alloc(vc4->screen, tile_alloc_size, 61 "tile_alloc"); 62 } 63 if (!vc4->tile_state || vc4->tile_state->size < tile_state_size) { 64 vc4_bo_unreference(&vc4->tile_state); 65 vc4->tile_state = vc4_bo_alloc(vc4->screen, tile_state_size, 66 "tile_state"); 67 } 68 69 // Tile state data is 48 bytes per tile, I think it can be thrown away 70 // as soon as binning is finished. 71 cl_start_reloc(&vc4->bcl, 2); 72 cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG); 73 cl_reloc(vc4, &vc4->bcl, vc4->tile_alloc, 0); 74 cl_u32(&vc4->bcl, vc4->tile_alloc->size); 75 cl_reloc(vc4, &vc4->bcl, vc4->tile_state, 0); 76 cl_u8(&vc4->bcl, tilew); 77 cl_u8(&vc4->bcl, tileh); 78 cl_u8(&vc4->bcl, 79 VC4_BIN_CONFIG_AUTO_INIT_TSDA | 80 VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_32 | 81 VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32); 82 83 cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING); 84 85 vc4->needs_flush = true; 86 vc4->draw_call_queued = true; 87} 88 89static void 90vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) 91{ 92 struct vc4_context *vc4 = vc4_context(pctx); 93 94 if (info->mode >= PIPE_PRIM_QUADS) { 95 util_primconvert_save_index_buffer(vc4->primconvert, &vc4->indexbuf); 96 util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base); 97 util_primconvert_draw_vbo(vc4->primconvert, info); 98 return; 99 } 100 101 vc4_start_draw(vc4); 102 vc4_update_compiled_shaders(vc4, info->mode); 103 104 vc4_emit_state(pctx); 105 106 /* the actual draw call. */ 107 struct vc4_vertex_stateobj *vtx = vc4->vtx; 108 struct vc4_vertexbuf_stateobj *vertexbuf = &vc4->vertexbuf; 109 cl_u8(&vc4->bcl, VC4_PACKET_GL_SHADER_STATE); 110 assert(vtx->num_elements <= 8); 111 /* Note that number of attributes == 0 in the packet means 8 112 * attributes. This field also contains the offset into shader_rec. 113 */ 114 cl_u32(&vc4->bcl, vtx->num_elements & 0x7); 115 116 /* Note that the primitive type fields match with OpenGL/gallium 117 * definitions, up to but not including QUADS. 118 */ 119 if (info->indexed) { 120 struct vc4_resource *rsc = vc4_resource(vc4->indexbuf.buffer); 121 122 assert(vc4->indexbuf.index_size == 1 || 123 vc4->indexbuf.index_size == 2); 124 125 cl_start_reloc(&vc4->bcl, 1); 126 cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE); 127 cl_u8(&vc4->bcl, 128 info->mode | 129 (vc4->indexbuf.index_size == 2 ? 130 VC4_INDEX_BUFFER_U16: 131 VC4_INDEX_BUFFER_U8)); 132 cl_u32(&vc4->bcl, info->count); 133 cl_reloc(vc4, &vc4->bcl, rsc->bo, vc4->indexbuf.offset); 134 cl_u32(&vc4->bcl, info->max_index); 135 } else { 136 cl_u8(&vc4->bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE); 137 cl_u8(&vc4->bcl, info->mode); 138 cl_u32(&vc4->bcl, info->count); 139 cl_u32(&vc4->bcl, info->start); 140 } 141 142// Shader Record 143 144 vc4_write_uniforms(vc4, vc4->prog.fs, 145 &vc4->constbuf[PIPE_SHADER_FRAGMENT], 146 &vc4->fragtex, 147 0); 148 vc4_write_uniforms(vc4, vc4->prog.vs, 149 &vc4->constbuf[PIPE_SHADER_VERTEX], 150 &vc4->verttex, 151 0); 152 vc4_write_uniforms(vc4, vc4->prog.vs, 153 &vc4->constbuf[PIPE_SHADER_VERTEX], 154 &vc4->verttex, 155 1); 156 157 cl_start_shader_reloc(&vc4->shader_rec, 3 + vtx->num_elements); 158 cl_u16(&vc4->shader_rec, VC4_SHADER_FLAG_ENABLE_CLIPPING); 159 cl_u8(&vc4->shader_rec, 0); /* fs num uniforms (unused) */ 160 cl_u8(&vc4->shader_rec, vc4->prog.fs->num_inputs); 161 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0); 162 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */ 163 164 cl_u16(&vc4->shader_rec, 0); /* vs num uniforms */ 165 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* vs attribute array bitfield */ 166 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */ 167 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo, 0); 168 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */ 169 170 cl_u16(&vc4->shader_rec, 0); /* cs num uniforms */ 171 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* cs attribute array bitfield */ 172 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */ 173 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo, 174 vc4->prog.vs->coord_shader_offset); 175 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */ 176 177 for (int i = 0; i < vtx->num_elements; i++) { 178 struct pipe_vertex_element *elem = &vtx->pipe[i]; 179 struct pipe_vertex_buffer *vb = 180 &vertexbuf->vb[elem->vertex_buffer_index]; 181 struct vc4_resource *rsc = vc4_resource(vb->buffer); 182 183 cl_reloc(vc4, &vc4->shader_rec, rsc->bo, 184 vb->buffer_offset + elem->src_offset); 185 cl_u8(&vc4->shader_rec, 186 util_format_get_blocksize(elem->src_format) - 1); 187 cl_u8(&vc4->shader_rec, vb->stride); 188 cl_u8(&vc4->shader_rec, i * 16); /* VS VPM offset */ 189 cl_u8(&vc4->shader_rec, i * 16); /* CS VPM offset */ 190 } 191 192 if (vc4->zsa && vc4->zsa->base.depth.enabled) { 193 vc4->resolve |= PIPE_CLEAR_DEPTH; 194 } 195 vc4->resolve |= PIPE_CLEAR_COLOR0; 196 197 vc4->shader_rec_count++; 198} 199 200static uint32_t 201pack_rgba(enum pipe_format format, const float *rgba) 202{ 203 union util_color uc; 204 util_pack_color(rgba, format, &uc); 205 return uc.ui[0]; 206} 207 208static void 209vc4_clear(struct pipe_context *pctx, unsigned buffers, 210 const union pipe_color_union *color, double depth, unsigned stencil) 211{ 212 struct vc4_context *vc4 = vc4_context(pctx); 213 214 /* We can't flag new buffers for clearing once we've queued draws. We 215 * could avoid this by using the 3d engine to clear. 216 */ 217 if (vc4->draw_call_queued) 218 vc4_flush(pctx); 219 220 if (buffers & PIPE_CLEAR_COLOR0) { 221 vc4->clear_color[0] = vc4->clear_color[1] = 222 pack_rgba(vc4->framebuffer.cbufs[0]->format, 223 color->f); 224 } 225 226 if (buffers & PIPE_CLEAR_DEPTH) 227 vc4->clear_depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth); 228 229 vc4->cleared |= buffers; 230 vc4->resolve |= buffers; 231 232 vc4_start_draw(vc4); 233} 234 235static void 236vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps, 237 const union pipe_color_union *color, 238 unsigned x, unsigned y, unsigned w, unsigned h) 239{ 240 fprintf(stderr, "unimpl: clear RT\n"); 241} 242 243static void 244vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps, 245 unsigned buffers, double depth, unsigned stencil, 246 unsigned x, unsigned y, unsigned w, unsigned h) 247{ 248 fprintf(stderr, "unimpl: clear DS\n"); 249} 250 251void 252vc4_draw_init(struct pipe_context *pctx) 253{ 254 pctx->draw_vbo = vc4_draw_vbo; 255 pctx->clear = vc4_clear; 256 pctx->clear_render_target = vc4_clear_render_target; 257 pctx->clear_depth_stencil = vc4_clear_depth_stencil; 258} 259