1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
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 shall be included in
13 * all copies or substantial portions of the 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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "nvidia-3d.h"
25 #include "nvidia-3d-types-priv.h"
26 #include "nvos.h"
27 #include "nvidia-3d-fermi.h"
28 #include "nvidia-3d-kepler.h"
29 #include "nvidia-push-utils.h"
30
nv3dAllocChannelObject(const Nv3dAllocChannelObjectParams * pParams,Nv3dChannelPtr p3dChannel)31 NvBool nv3dAllocChannelObject(
32 const Nv3dAllocChannelObjectParams *pParams,
33 Nv3dChannelPtr p3dChannel)
34 {
35 NvPushChannelPtr pPushChannel = pParams->pPushChannel;
36 NvPushDevicePtr pPushDevice = pPushChannel->pDevice;
37 const NvU32 classNumber = p3dChannel->p3dDevice->classNumber;
38 const NvU32 numChannels =
39 pPushDevice->clientSli ? pPushDevice->numSubDevices : 1;
40 int sd;
41
42 /*
43 * nv3dAllocChannel() should have been called to assign p3dDevice.
44 */
45 nvAssert(p3dChannel->p3dDevice != NULL);
46 nvAssert(p3dChannel->p3dDevice->pPushDevice ==
47 pParams->pPushChannel->pDevice);
48
49 for (sd = 0; sd < numChannels; sd++) {
50
51 if (nvPushIsAModel(pPushDevice)) {
52 nvAssert(sd == 0);
53 } else {
54 const NvPushImports *pImports = pPushDevice->pImports;
55 nvAssert(pPushChannel->channelHandle[sd] != 0);
56 nvAssert(pParams->handle[sd] != 0);
57 NvU32 ret = pImports->rmApiAlloc(pPushDevice,
58 pPushChannel->channelHandle[sd],
59 pParams->handle[sd],
60 classNumber,
61 NULL);
62 if (ret != NVOS_STATUS_SUCCESS) {
63 return FALSE;
64 }
65 }
66
67 p3dChannel->handle[sd] = pParams->handle[sd];
68 }
69
70 p3dChannel->pPushChannel = pPushChannel;
71
72 return TRUE;
73 }
74
nv3dFreeChannelObject(Nv3dChannelPtr p3dChannel)75 void nv3dFreeChannelObject(Nv3dChannelPtr p3dChannel)
76 {
77 int sd;
78
79 p3dChannel->pPushChannel = NULL;
80
81 // No need to actually free the object here. It gets destroyed during
82 // channel teardown.
83 for (sd = 0; sd < ARRAY_LEN(p3dChannel->handle); sd++) {
84 p3dChannel->handle[sd] = 0;
85 }
86 }
87
nv3dUploadDataInline(Nv3dChannelRec * p3dChannel,NvU64 gpuBaseAddress,size_t offset,const void * data,size_t bytes)88 void nv3dUploadDataInline(
89 Nv3dChannelRec *p3dChannel,
90 NvU64 gpuBaseAddress,
91 size_t offset,
92 const void *data,
93 size_t bytes)
94 {
95 const Nv3dHal *pHal = p3dChannel->p3dDevice->hal;
96
97 pHal->uploadDataInline(p3dChannel, gpuBaseAddress, offset, data, bytes);
98 }
99
nv3dClearProgramCache(Nv3dChannelRec * p3dChannel)100 void nv3dClearProgramCache(Nv3dChannelRec *p3dChannel)
101 {
102 Nv3dShaderStage stage;
103
104 for (stage = 0;
105 stage < ARRAY_LEN(p3dChannel->currentProgramIndex);
106 stage++) {
107 p3dChannel->currentProgramIndex[stage] = -1;
108 }
109 }
110
nv3dLoadTextures(Nv3dChannelRec * p3dChannel,int firstTex,const Nv3dRenderTexInfo * texInfo,int numTex)111 void nv3dLoadTextures(
112 Nv3dChannelRec *p3dChannel,
113 int firstTex,
114 const Nv3dRenderTexInfo *texInfo,
115 int numTex)
116 {
117 /* Limit number of texture/samplers on the stack to 4 (256 bytes) */
118 #define MAX_TEX_CHUNK 4
119 Nv3dTexture textures[MAX_TEX_CHUNK];
120 const Nv3dHal *pHal = p3dChannel->p3dDevice->hal;
121 const NvU64 gpuBaseAddress = nv3dGetTextureGpuAddress(p3dChannel, 0);
122
123 nvAssert(numTex >= 1);
124
125 // Invalidate the texture/sampler caches. This will cause a wait for idle
126 // if there's rendering still in progress. This is necessary in case the
127 // texture parameters we're about to overwrite are in use.
128 _nv3dInvalidateTexturesFermi(p3dChannel);
129
130 while (numTex) {
131 const NvU32 chunkNumTex = NV_MIN(numTex, MAX_TEX_CHUNK);
132 const size_t startOffset = sizeof(Nv3dTexture) * firstTex;
133 const size_t bytes = sizeof(Nv3dTexture) * chunkNumTex;
134 int i;
135
136 NVMISC_MEMSET(textures, 0, sizeof(textures));
137
138 nvAssert(firstTex + numTex <= p3dChannel->numTextures);
139
140 // Write texture header to HW format
141 for (i = 0; i < chunkNumTex; i++) {
142 pHal->assignNv3dTexture(texInfo[i], &textures[i]);
143 }
144
145 nv3dUploadDataInline(p3dChannel, gpuBaseAddress, startOffset,
146 textures, bytes);
147
148 numTex -= chunkNumTex;
149 firstTex += chunkNumTex;
150 texInfo += chunkNumTex;
151 }
152 }
153
nv3dBindTextures(Nv3dChannelPtr p3dChannel,int programIndex,const int * textureBindingIndices)154 void nv3dBindTextures(
155 Nv3dChannelPtr p3dChannel,
156 int programIndex,
157 const int *textureBindingIndices)
158 {
159 nvAssert(programIndex < p3dChannel->programs.num);
160
161 _nv3dBindTexturesKepler(p3dChannel, programIndex, textureBindingIndices);
162 }
163