Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/Draw.cpp
4565 views
/**************************************************************************1*2* Copyright 2012-2021 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/2627/*28* Draw.h --29* Functions that render 3D primitives.30*/313233#include "Draw.h"34#include "State.h"35#include "Shader.h"3637#include "Debug.h"3839#include "util/u_draw.h"40#include "util/u_memory.h"4142static unsigned43ClampedUAdd(unsigned a,44unsigned b)45{46unsigned c = a + b;47if (c < a) {48return 0xffffffff;49}50return c;51}525354/*55* We have to resolve the stream output state for empty geometry shaders.56* In particular we've remapped the output indices when translating the57* shaders so now the register_index variables in the stream output58* state are incorrect and we need to remap them back to the correct59* state.60*/61static void62ResolveState(Device *pDevice)63{64if (pDevice->bound_empty_gs && pDevice->bound_vs &&65pDevice->bound_vs->state.tokens) {66Shader *gs = pDevice->bound_empty_gs;67Shader *vs = pDevice->bound_vs;68boolean remapped = FALSE;69struct pipe_context *pipe = pDevice->pipe;70if (!gs->output_resolved) {71for (unsigned i = 0; i < gs->state.stream_output.num_outputs; ++i) {72unsigned mapping =73ShaderFindOutputMapping(vs, gs->state.stream_output.output[i].register_index);74if (mapping != gs->state.stream_output.output[i].register_index) {75gs->state.stream_output.output[i].register_index = mapping;76remapped = TRUE;77}78}79if (remapped) {80pipe->delete_gs_state(pipe, gs->handle);81gs->handle = pipe->create_gs_state(pipe, &gs->state);82}83gs->output_resolved = TRUE;84}85pipe->bind_gs_state(pipe, gs->handle);86}87}888990static struct pipe_resource *91create_null_index_buffer(struct pipe_context *ctx, uint num_indices,92unsigned *restart_index, unsigned *index_size,93unsigned *ib_offset)94{95unsigned buf_size = num_indices * sizeof(unsigned);96unsigned *buf = (unsigned*)MALLOC(buf_size);97struct pipe_resource *ibuf;9899memset(buf, 0, buf_size);100101ibuf = pipe_buffer_create_with_data(ctx,102PIPE_BIND_INDEX_BUFFER,103PIPE_USAGE_IMMUTABLE,104buf_size, buf);105*index_size = 4;106*restart_index = 0xffffffff;107*ib_offset = 0;108109FREE(buf);110111return ibuf;112}113114/*115* ----------------------------------------------------------------------116*117* Draw --118*119* The Draw function draws nonindexed primitives.120*121* ----------------------------------------------------------------------122*/123124void APIENTRY125Draw(D3D10DDI_HDEVICE hDevice, // IN126UINT VertexCount, // IN127UINT StartVertexLocation) // IN128{129LOG_ENTRYPOINT();130131Device *pDevice = CastDevice(hDevice);132133ResolveState(pDevice);134135assert(pDevice->primitive < PIPE_PRIM_MAX);136util_draw_arrays(pDevice->pipe,137pDevice->primitive,138StartVertexLocation,139VertexCount);140}141142143/*144* ----------------------------------------------------------------------145*146* DrawIndexed --147*148* The DrawIndexed function draws indexed primitives.149*150* ----------------------------------------------------------------------151*/152153void APIENTRY154DrawIndexed(D3D10DDI_HDEVICE hDevice, // IN155UINT IndexCount, // IN156UINT StartIndexLocation, // IN157INT BaseVertexLocation) // IN158{159LOG_ENTRYPOINT();160161Device *pDevice = CastDevice(hDevice);162struct pipe_draw_info info;163struct pipe_draw_start_count_bias draw;164struct pipe_resource *null_ib = NULL;165unsigned restart_index = pDevice->restart_index;166unsigned index_size = pDevice->index_size;167unsigned ib_offset = pDevice->ib_offset;168169assert(pDevice->primitive < PIPE_PRIM_MAX);170171/* XXX I don't think draw still needs this? */172if (!pDevice->index_buffer) {173null_ib =174create_null_index_buffer(pDevice->pipe,175StartIndexLocation + IndexCount,176&restart_index, &index_size, &ib_offset);177}178179ResolveState(pDevice);180181util_draw_init_info(&info);182info.index_size = index_size;183info.mode = pDevice->primitive;184draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size);185draw.count = IndexCount;186info.index.resource = null_ib ? null_ib : pDevice->index_buffer;187draw.index_bias = BaseVertexLocation;188info.primitive_restart = TRUE;189info.restart_index = restart_index;190191pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1);192193if (null_ib) {194pipe_resource_reference(&null_ib, NULL);195}196}197198199/*200* ----------------------------------------------------------------------201*202* DrawInstanced --203*204* The DrawInstanced function draws particular instances205* of nonindexed primitives.206*207* ----------------------------------------------------------------------208*/209210void APIENTRY211DrawInstanced(D3D10DDI_HDEVICE hDevice, // IN212UINT VertexCountPerInstance, // IN213UINT InstanceCount, // IN214UINT StartVertexLocation, // IN215UINT StartInstanceLocation) // IN216{217LOG_ENTRYPOINT();218219Device *pDevice = CastDevice(hDevice);220221if (!InstanceCount) {222return;223}224225ResolveState(pDevice);226227assert(pDevice->primitive < PIPE_PRIM_MAX);228util_draw_arrays_instanced(pDevice->pipe,229pDevice->primitive,230StartVertexLocation,231VertexCountPerInstance,232StartInstanceLocation,233InstanceCount);234}235236237/*238* ----------------------------------------------------------------------239*240* DrawIndexedInstanced --241*242* The DrawIndexedInstanced function draws particular243* instances of indexed primitives.244*245* ----------------------------------------------------------------------246*/247248void APIENTRY249DrawIndexedInstanced(D3D10DDI_HDEVICE hDevice, // IN250UINT IndexCountPerInstance, // IN251UINT InstanceCount, // IN252UINT StartIndexLocation, // IN253INT BaseVertexLocation, // IN254UINT StartInstanceLocation) // IN255{256LOG_ENTRYPOINT();257258Device *pDevice = CastDevice(hDevice);259struct pipe_draw_info info;260struct pipe_draw_start_count_bias draw;261struct pipe_resource *null_ib = NULL;262unsigned restart_index = pDevice->restart_index;263unsigned index_size = pDevice->index_size;264unsigned ib_offset = pDevice->ib_offset;265266assert(pDevice->primitive < PIPE_PRIM_MAX);267268if (!InstanceCount) {269return;270}271272/* XXX I don't think draw still needs this? */273if (!pDevice->index_buffer) {274null_ib =275create_null_index_buffer(pDevice->pipe,276StartIndexLocation + IndexCountPerInstance,277&restart_index, &index_size, &ib_offset);278}279280ResolveState(pDevice);281282util_draw_init_info(&info);283info.index_size = index_size;284info.mode = pDevice->primitive;285draw.start = ClampedUAdd(StartIndexLocation, ib_offset / index_size);286draw.count = IndexCountPerInstance;287info.index.resource = null_ib ? null_ib : pDevice->index_buffer;288draw.index_bias = BaseVertexLocation;289info.start_instance = StartInstanceLocation;290info.instance_count = InstanceCount;291info.primitive_restart = TRUE;292info.restart_index = restart_index;293294pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, NULL, &draw, 1);295296if (null_ib) {297pipe_resource_reference(&null_ib, NULL);298}299}300301302/*303* ----------------------------------------------------------------------304*305* DrawAuto --306*307* The DrawAuto function works similarly to the Draw function,308* except DrawAuto is used for the special case where vertex309* data is written through the stream-output unit and then310* recycled as a vertex buffer. The driver determines the number311* of primitives, in part, by how much data was written to the312* buffer through stream output.313*314* ----------------------------------------------------------------------315*/316317void APIENTRY318DrawAuto(D3D10DDI_HDEVICE hDevice) // IN319{320LOG_ENTRYPOINT();321322Device *pDevice = CastDevice(hDevice);323struct pipe_draw_info info;324struct pipe_draw_indirect_info indirect;325326327if (!pDevice->draw_so_target) {328LOG_UNSUPPORTED("DrawAuto without a set source buffer!");329return;330}331332assert(pDevice->primitive < PIPE_PRIM_MAX);333334ResolveState(pDevice);335336util_draw_init_info(&info);337info.mode = pDevice->primitive;338memset(&indirect, 0, sizeof indirect);339indirect.count_from_stream_output = pDevice->draw_so_target;340341pDevice->pipe->draw_vbo(pDevice->pipe, &info, 0, &indirect, NULL, 1);342}343344345