1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2012-2021 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 23bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 24bf215546Sopenharmony_ci * of the Software. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/* 29bf215546Sopenharmony_ci * Draw.h -- 30bf215546Sopenharmony_ci * Functions that render 3D primitives. 31bf215546Sopenharmony_ci */ 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "Draw.h" 35bf215546Sopenharmony_ci#include "State.h" 36bf215546Sopenharmony_ci#include "Shader.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "Debug.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#include "util/u_draw.h" 41bf215546Sopenharmony_ci#include "util/u_memory.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic unsigned 44bf215546Sopenharmony_ciClampedUAdd(unsigned a, 45bf215546Sopenharmony_ci unsigned b) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci unsigned c = a + b; 48bf215546Sopenharmony_ci if (c < a) { 49bf215546Sopenharmony_ci return 0xffffffff; 50bf215546Sopenharmony_ci } 51bf215546Sopenharmony_ci return c; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/* 56bf215546Sopenharmony_ci * We have to resolve the stream output state for empty geometry shaders. 57bf215546Sopenharmony_ci * In particular we've remapped the output indices when translating the 58bf215546Sopenharmony_ci * shaders so now the register_index variables in the stream output 59bf215546Sopenharmony_ci * state are incorrect and we need to remap them back to the correct 60bf215546Sopenharmony_ci * state. 61bf215546Sopenharmony_ci */ 62bf215546Sopenharmony_cistatic void 63bf215546Sopenharmony_ciResolveState(Device *pDevice) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci if (pDevice->bound_empty_gs && pDevice->bound_vs && 66bf215546Sopenharmony_ci pDevice->bound_vs->state.tokens) { 67bf215546Sopenharmony_ci Shader *gs = pDevice->bound_empty_gs; 68bf215546Sopenharmony_ci Shader *vs = pDevice->bound_vs; 69bf215546Sopenharmony_ci boolean remapped = FALSE; 70bf215546Sopenharmony_ci struct pipe_context *pipe = pDevice->pipe; 71bf215546Sopenharmony_ci if (!gs->output_resolved) { 72bf215546Sopenharmony_ci for (unsigned i = 0; i < gs->state.stream_output.num_outputs; ++i) { 73bf215546Sopenharmony_ci unsigned mapping = 74bf215546Sopenharmony_ci ShaderFindOutputMapping(vs, gs->state.stream_output.output[i].register_index); 75bf215546Sopenharmony_ci if (mapping != gs->state.stream_output.output[i].register_index) { 76bf215546Sopenharmony_ci gs->state.stream_output.output[i].register_index = mapping; 77bf215546Sopenharmony_ci remapped = TRUE; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci if (remapped) { 81bf215546Sopenharmony_ci pipe->delete_gs_state(pipe, gs->handle); 82bf215546Sopenharmony_ci gs->handle = pipe->create_gs_state(pipe, &gs->state); 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci gs->output_resolved = TRUE; 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci pipe->bind_gs_state(pipe, gs->handle); 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic struct pipe_resource * 92bf215546Sopenharmony_cicreate_null_index_buffer(struct pipe_context *ctx, uint num_indices, 93bf215546Sopenharmony_ci unsigned *restart_index, unsigned *index_size, 94bf215546Sopenharmony_ci unsigned *ib_offset) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci unsigned buf_size = num_indices * sizeof(unsigned); 97bf215546Sopenharmony_ci unsigned *buf = (unsigned*)MALLOC(buf_size); 98bf215546Sopenharmony_ci struct pipe_resource *ibuf; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci memset(buf, 0, buf_size); 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci ibuf = pipe_buffer_create_with_data(ctx, 103bf215546Sopenharmony_ci PIPE_BIND_INDEX_BUFFER, 104bf215546Sopenharmony_ci PIPE_USAGE_IMMUTABLE, 105bf215546Sopenharmony_ci buf_size, buf); 106bf215546Sopenharmony_ci *index_size = 4; 107bf215546Sopenharmony_ci *restart_index = 0xffffffff; 108bf215546Sopenharmony_ci *ib_offset = 0; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci FREE(buf); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci return ibuf; 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci/* 116bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 117bf215546Sopenharmony_ci * 118bf215546Sopenharmony_ci * Draw -- 119bf215546Sopenharmony_ci * 120bf215546Sopenharmony_ci * The Draw function draws nonindexed primitives. 121bf215546Sopenharmony_ci * 122bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 123bf215546Sopenharmony_ci */ 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_civoid APIENTRY 126bf215546Sopenharmony_ciDraw(D3D10DDI_HDEVICE hDevice, // IN 127bf215546Sopenharmony_ci UINT VertexCount, // IN 128bf215546Sopenharmony_ci UINT StartVertexLocation) // IN 129bf215546Sopenharmony_ci{ 130bf215546Sopenharmony_ci LOG_ENTRYPOINT(); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci Device *pDevice = CastDevice(hDevice); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci ResolveState(pDevice); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci assert(pDevice->primitive < PIPE_PRIM_MAX); 137bf215546Sopenharmony_ci util_draw_arrays(pDevice->pipe, 138bf215546Sopenharmony_ci pDevice->primitive, 139bf215546Sopenharmony_ci StartVertexLocation, 140bf215546Sopenharmony_ci VertexCount); 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci/* 145bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 146bf215546Sopenharmony_ci * 147bf215546Sopenharmony_ci * DrawIndexed -- 148bf215546Sopenharmony_ci * 149bf215546Sopenharmony_ci * The DrawIndexed function draws indexed primitives. 150bf215546Sopenharmony_ci * 151bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 152bf215546Sopenharmony_ci */ 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_civoid APIENTRY 155bf215546Sopenharmony_ciDrawIndexed(D3D10DDI_HDEVICE hDevice, // IN 156bf215546Sopenharmony_ci UINT IndexCount, // IN 157bf215546Sopenharmony_ci UINT StartIndexLocation, // IN 158bf215546Sopenharmony_ci INT BaseVertexLocation) // IN 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci LOG_ENTRYPOINT(); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci Device *pDevice = CastDevice(hDevice); 163bf215546Sopenharmony_ci struct pipe_draw_info info; 164bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 165bf215546Sopenharmony_ci struct pipe_resource *null_ib = NULL; 166bf215546Sopenharmony_ci unsigned restart_index = pDevice->restart_index; 167bf215546Sopenharmony_ci unsigned index_size = pDevice->index_size; 168bf215546Sopenharmony_ci unsigned ib_offset = pDevice->ib_offset; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci assert(pDevice->primitive < PIPE_PRIM_MAX); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci /* XXX I don't think draw still needs this? */ 173bf215546Sopenharmony_ci if (!pDevice->index_buffer) { 174bf215546Sopenharmony_ci null_ib = 175bf215546Sopenharmony_ci create_null_index_buffer(pDevice->pipe, 176bf215546Sopenharmony_ci StartIndexLocation + IndexCount, 177bf215546Sopenharmony_ci &restart_index, &index_size, &ib_offset); 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci ResolveState(pDevice); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci util_draw_init_info(&info); 183bf215546Sopenharmony_ci info.index_size = index_size; 184bf215546Sopenharmony_ci info.mode = pDevice->primitive; 185bf215546Sopenharmony_ci draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size); 186bf215546Sopenharmony_ci draw.count = IndexCount; 187bf215546Sopenharmony_ci info.index.resource = null_ib ? null_ib : pDevice->index_buffer; 188bf215546Sopenharmony_ci draw.index_bias = BaseVertexLocation; 189bf215546Sopenharmony_ci info.primitive_restart = TRUE; 190bf215546Sopenharmony_ci info.restart_index = restart_index; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci if (null_ib) { 195bf215546Sopenharmony_ci pipe_resource_reference(&null_ib, NULL); 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci/* 201bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 202bf215546Sopenharmony_ci * 203bf215546Sopenharmony_ci * DrawInstanced -- 204bf215546Sopenharmony_ci * 205bf215546Sopenharmony_ci * The DrawInstanced function draws particular instances 206bf215546Sopenharmony_ci * of nonindexed primitives. 207bf215546Sopenharmony_ci * 208bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 209bf215546Sopenharmony_ci */ 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_civoid APIENTRY 212bf215546Sopenharmony_ciDrawInstanced(D3D10DDI_HDEVICE hDevice, // IN 213bf215546Sopenharmony_ci UINT VertexCountPerInstance, // IN 214bf215546Sopenharmony_ci UINT InstanceCount, // IN 215bf215546Sopenharmony_ci UINT StartVertexLocation, // IN 216bf215546Sopenharmony_ci UINT StartInstanceLocation) // IN 217bf215546Sopenharmony_ci{ 218bf215546Sopenharmony_ci LOG_ENTRYPOINT(); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci Device *pDevice = CastDevice(hDevice); 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci if (!InstanceCount) { 223bf215546Sopenharmony_ci return; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci ResolveState(pDevice); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci assert(pDevice->primitive < PIPE_PRIM_MAX); 229bf215546Sopenharmony_ci util_draw_arrays_instanced(pDevice->pipe, 230bf215546Sopenharmony_ci pDevice->primitive, 231bf215546Sopenharmony_ci StartVertexLocation, 232bf215546Sopenharmony_ci VertexCountPerInstance, 233bf215546Sopenharmony_ci StartInstanceLocation, 234bf215546Sopenharmony_ci InstanceCount); 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci/* 239bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 240bf215546Sopenharmony_ci * 241bf215546Sopenharmony_ci * DrawIndexedInstanced -- 242bf215546Sopenharmony_ci * 243bf215546Sopenharmony_ci * The DrawIndexedInstanced function draws particular 244bf215546Sopenharmony_ci * instances of indexed primitives. 245bf215546Sopenharmony_ci * 246bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 247bf215546Sopenharmony_ci */ 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_civoid APIENTRY 250bf215546Sopenharmony_ciDrawIndexedInstanced(D3D10DDI_HDEVICE hDevice, // IN 251bf215546Sopenharmony_ci UINT IndexCountPerInstance, // IN 252bf215546Sopenharmony_ci UINT InstanceCount, // IN 253bf215546Sopenharmony_ci UINT StartIndexLocation, // IN 254bf215546Sopenharmony_ci INT BaseVertexLocation, // IN 255bf215546Sopenharmony_ci UINT StartInstanceLocation) // IN 256bf215546Sopenharmony_ci{ 257bf215546Sopenharmony_ci LOG_ENTRYPOINT(); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci Device *pDevice = CastDevice(hDevice); 260bf215546Sopenharmony_ci struct pipe_draw_info info; 261bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 262bf215546Sopenharmony_ci struct pipe_resource *null_ib = NULL; 263bf215546Sopenharmony_ci unsigned restart_index = pDevice->restart_index; 264bf215546Sopenharmony_ci unsigned index_size = pDevice->index_size; 265bf215546Sopenharmony_ci unsigned ib_offset = pDevice->ib_offset; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci assert(pDevice->primitive < PIPE_PRIM_MAX); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci if (!InstanceCount) { 270bf215546Sopenharmony_ci return; 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci /* XXX I don't think draw still needs this? */ 274bf215546Sopenharmony_ci if (!pDevice->index_buffer) { 275bf215546Sopenharmony_ci null_ib = 276bf215546Sopenharmony_ci create_null_index_buffer(pDevice->pipe, 277bf215546Sopenharmony_ci StartIndexLocation + IndexCountPerInstance, 278bf215546Sopenharmony_ci &restart_index, &index_size, &ib_offset); 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci ResolveState(pDevice); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci util_draw_init_info(&info); 284bf215546Sopenharmony_ci info.index_size = index_size; 285bf215546Sopenharmony_ci info.mode = pDevice->primitive; 286bf215546Sopenharmony_ci draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size); 287bf215546Sopenharmony_ci draw.count = IndexCountPerInstance; 288bf215546Sopenharmony_ci info.index.resource = null_ib ? null_ib : pDevice->index_buffer; 289bf215546Sopenharmony_ci draw.index_bias = BaseVertexLocation; 290bf215546Sopenharmony_ci info.start_instance = StartInstanceLocation; 291bf215546Sopenharmony_ci info.instance_count = InstanceCount; 292bf215546Sopenharmony_ci info.primitive_restart = TRUE; 293bf215546Sopenharmony_ci info.restart_index = restart_index; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (null_ib) { 298bf215546Sopenharmony_ci pipe_resource_reference(&null_ib, NULL); 299bf215546Sopenharmony_ci } 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci/* 304bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 305bf215546Sopenharmony_ci * 306bf215546Sopenharmony_ci * DrawAuto -- 307bf215546Sopenharmony_ci * 308bf215546Sopenharmony_ci * The DrawAuto function works similarly to the Draw function, 309bf215546Sopenharmony_ci * except DrawAuto is used for the special case where vertex 310bf215546Sopenharmony_ci * data is written through the stream-output unit and then 311bf215546Sopenharmony_ci * recycled as a vertex buffer. The driver determines the number 312bf215546Sopenharmony_ci * of primitives, in part, by how much data was written to the 313bf215546Sopenharmony_ci * buffer through stream output. 314bf215546Sopenharmony_ci * 315bf215546Sopenharmony_ci * ---------------------------------------------------------------------- 316bf215546Sopenharmony_ci */ 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_civoid APIENTRY 319bf215546Sopenharmony_ciDrawAuto(D3D10DDI_HDEVICE hDevice) // IN 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci LOG_ENTRYPOINT(); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci Device *pDevice = CastDevice(hDevice); 324bf215546Sopenharmony_ci struct pipe_draw_info info; 325bf215546Sopenharmony_ci struct pipe_draw_indirect_info indirect; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci if (!pDevice->draw_so_target) { 329bf215546Sopenharmony_ci LOG_UNSUPPORTED("DrawAuto without a set source buffer!"); 330bf215546Sopenharmony_ci return; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci assert(pDevice->primitive < PIPE_PRIM_MAX); 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci ResolveState(pDevice); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci util_draw_init_info(&info); 338bf215546Sopenharmony_ci info.mode = pDevice->primitive; 339bf215546Sopenharmony_ci memset(&indirect, 0, sizeof indirect); 340bf215546Sopenharmony_ci indirect.count_from_stream_output = pDevice->draw_so_target; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, &indirect, NULL, 1); 343bf215546Sopenharmony_ci} 344