VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-hlp.cpp@ 85546

Last change on this file since 85546 was 83579, checked in by vboxsync, 5 years ago

Devices/Graphics: added helpers to parse and log the shader code, bugref:9639

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: DevVGA-SVGA3d-hlp.cpp 83579 2020-04-06 00:17:53Z vboxsync $ */
2/** @file
3 * DevVMWare - VMWare SVGA device helpers
4 */
5
6/*
7 * Copyright (C) 2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
19#include <VBox/AssertGuest.h>
20#include <VBox/log.h>
21
22#include <iprt/cdefs.h>
23#include <iprt/errcore.h>
24#include <iprt/types.h>
25
26#include "vmsvga/svga3d_reg.h"
27#include "vmsvga/svga3d_shaderdefs.h"
28
29typedef struct VMSVGA3DSHADERPARSECONTEXT
30{
31 uint32_t type;
32} VMSVGA3DSHADERPARSECONTEXT;
33
34static int vmsvga3dShaderParseRegOffset(VMSVGA3DSHADERPARSECONTEXT *pCtx,
35 bool fIsSrc,
36 SVGA3dShaderRegType regType,
37 uint32_t off)
38{
39 RT_NOREF(pCtx, fIsSrc);
40
41 switch (regType)
42 {
43 case SVGA3DREG_TEMP:
44 break;
45 case SVGA3DREG_INPUT:
46 break;
47 case SVGA3DREG_CONST:
48 break;
49 case SVGA3DREG_ADDR /* also SVGA3DREG_TEXTURE */:
50 break;
51 case SVGA3DREG_RASTOUT:
52 break;
53 case SVGA3DREG_ATTROUT:
54 break;
55 case SVGA3DREG_TEXCRDOUT /* also SVGA3DREG_OUTPUT */:
56 break;
57 case SVGA3DREG_CONSTINT:
58 break;
59 case SVGA3DREG_COLOROUT:
60 break;
61 case SVGA3DREG_DEPTHOUT:
62 break;
63 case SVGA3DREG_SAMPLER:
64 break;
65 case SVGA3DREG_CONST2:
66 break;
67 case SVGA3DREG_CONST3:
68 break;
69 case SVGA3DREG_CONST4:
70 break;
71 case SVGA3DREG_CONSTBOOL:
72 break;
73 case SVGA3DREG_LOOP:
74 break;
75 case SVGA3DREG_TEMPFLOAT16:
76 break;
77 case SVGA3DREG_MISCTYPE:
78 ASSERT_GUEST_RETURN( off == SVGA3DMISCREG_POSITION
79 || off == SVGA3DMISCREG_FACE, VERR_PARSE_ERROR);
80 break;
81 case SVGA3DREG_LABEL:
82 break;
83 case SVGA3DREG_PREDICATE:
84 break;
85 default:
86 ASSERT_GUEST_FAILED_RETURN(VERR_PARSE_ERROR);
87 }
88
89 return VINF_SUCCESS;
90}
91
92#if 0
93static int vmsvga3dShaderParseSrcToken(VMSVGA3DSHADERPARSECONTEXT *pCtx, uint32_t const *pToken)
94{
95 RT_NOREF(pCtx);
96
97 SVGA3dShaderSrcToken src;
98 src.value = *pToken;
99
100 SVGA3dShaderRegType const regType = (SVGA3dShaderRegType)(src.s.type_upper << 3 | src.s.type_lower);
101 Log3(("Src: type %d, r0 %d, srcMod %d, swizzle 0x%x, r1 %d, relAddr %d, num %d\n",
102 regType, src.s.reserved0, src.s.srcMod, src.s.swizzle, src.s.reserved1, src.s.relAddr, src.s.num));
103
104 return vmsvga3dShaderParseRegOffset(pCtx, true, regType, src.s.num);
105}
106#endif
107
108static int vmsvga3dShaderParseDestToken(VMSVGA3DSHADERPARSECONTEXT *pCtx, uint32_t const *pToken)
109{
110 RT_NOREF(pCtx);
111
112 SVGA3dShaderDestToken dest;
113 dest.value = *pToken;
114
115 SVGA3dShaderRegType const regType = (SVGA3dShaderRegType)(dest.s.type_upper << 3 | dest.s.type_lower);
116 Log3(("Dest: type %d, r0 %d, shfScale %d, dstMod %d, mask 0x%x, r1 %d, relAddr %d, num %d\n",
117 regType, dest.s.reserved0, dest.s.shfScale, dest.s.dstMod, dest.s.mask, dest.s.reserved1, dest.s.relAddr, dest.s.num));
118
119 return vmsvga3dShaderParseRegOffset(pCtx, false, regType, dest.s.num);
120}
121
122static int vmsvga3dShaderParseDclArgs(VMSVGA3DSHADERPARSECONTEXT *pCtx, uint32_t const *pToken)
123{
124 SVGA3DOpDclArgs a;
125 a.values[0] = pToken[0]; // declaration
126 a.values[1] = pToken[1]; // dst
127
128 return vmsvga3dShaderParseDestToken(pCtx, (uint32_t *)&a.s2.dst);
129}
130
131/* Parse the shader code
132 * https://docs.microsoft.com/en-us/windows-hardware/drivers/display/shader-code-format
133 */
134int vmsvga3dShaderParse(uint32_t cbShaderData, uint32_t const *pShaderData)
135{
136 uint32_t const *paTokensStart = (uint32_t *)pShaderData;
137 uint32_t const cTokens = cbShaderData / sizeof(uint32_t);
138
139 /* 48KB is an arbitrary limit. */
140 ASSERT_GUEST_RETURN(cTokens >= 2 && cTokens < (48 * _1K) / sizeof(paTokensStart[0]), VERR_INVALID_PARAMETER);
141
142#ifdef LOG_ENABLED
143 Log3(("Shader code:\n"));
144 const uint32_t cTokensPerLine = 8;
145 for (uint32_t iToken = 0; iToken < cTokens; ++iToken)
146 {
147 if ((iToken % cTokensPerLine) == 0)
148 {
149 if (iToken == 0)
150 Log3(("0x%08X,", paTokensStart[iToken]));
151 else
152 Log3(("\n0x%08X,", paTokensStart[iToken]));
153 }
154 else
155 Log3((" 0x%08X,", paTokensStart[iToken]));
156 }
157 Log3(("\n"));
158#endif
159
160 /* "The first token must be a version token." */
161 SVGA3dShaderVersion const *pVersion = (SVGA3dShaderVersion const *)paTokensStart;
162 ASSERT_GUEST_RETURN( pVersion->s.type == SVGA3D_VS_TYPE
163 || pVersion->s.type == SVGA3D_PS_TYPE, VERR_PARSE_ERROR);
164
165 VMSVGA3DSHADERPARSECONTEXT ctx;
166 ctx.type = pVersion->s.type;
167
168 /* Scan the tokens. Immediately return an error code on any unexpected data. */
169 const uint32_t *paTokensEnd = &paTokensStart[cTokens];
170 const uint32_t *pToken = &paTokensStart[1];
171 while (pToken < paTokensEnd)
172 {
173 SVGA3dShaderInstToken const token = *(SVGA3dShaderInstToken *)pToken;
174
175 /* Figure out the instruction length, which is how many tokens follow the instruction token. */
176 uint32_t cInstLen;
177 if (token.s1.op == SVGA3DOP_COMMENT)
178 cInstLen = token.s.comment_size;
179 else
180 cInstLen = token.s1.size;
181
182 Log3(("op %d, cInstLen %d\n", token.s1.op, cInstLen));
183
184 ASSERT_GUEST_RETURN(cInstLen < paTokensEnd - pToken, VERR_PARSE_ERROR);
185
186 if (token.s1.op == SVGA3DOP_END)
187 {
188 ASSERT_GUEST_RETURN(token.value == 0x0000FFFF, VERR_PARSE_ERROR);
189 break;
190 }
191
192 int rc;
193 switch (token.s1.op)
194 {
195 case SVGA3DOP_DCL:
196 ASSERT_GUEST_RETURN(cInstLen == 2, VERR_PARSE_ERROR);
197 rc = vmsvga3dShaderParseDclArgs(&ctx, &pToken[1]);
198 if (RT_FAILURE(rc))
199 return rc;
200 break;
201 case SVGA3DOP_NOP:
202 case SVGA3DOP_MOV:
203 case SVGA3DOP_ADD:
204 case SVGA3DOP_SUB:
205 case SVGA3DOP_MAD:
206 case SVGA3DOP_MUL:
207 case SVGA3DOP_RCP:
208 case SVGA3DOP_RSQ:
209 case SVGA3DOP_DP3:
210 case SVGA3DOP_DP4:
211 case SVGA3DOP_MIN:
212 case SVGA3DOP_MAX:
213 case SVGA3DOP_SLT:
214 case SVGA3DOP_SGE:
215 case SVGA3DOP_EXP:
216 case SVGA3DOP_LOG:
217 case SVGA3DOP_LIT:
218 case SVGA3DOP_DST:
219 case SVGA3DOP_LRP:
220 case SVGA3DOP_FRC:
221 case SVGA3DOP_M4x4:
222 case SVGA3DOP_M4x3:
223 case SVGA3DOP_M3x4:
224 case SVGA3DOP_M3x3:
225 case SVGA3DOP_M3x2:
226 case SVGA3DOP_CALL:
227 case SVGA3DOP_CALLNZ:
228 case SVGA3DOP_LOOP:
229 case SVGA3DOP_RET:
230 case SVGA3DOP_ENDLOOP:
231 case SVGA3DOP_LABEL:
232 case SVGA3DOP_POW:
233 case SVGA3DOP_CRS:
234 case SVGA3DOP_SGN:
235 case SVGA3DOP_ABS:
236 case SVGA3DOP_NRM:
237 case SVGA3DOP_SINCOS:
238 case SVGA3DOP_REP:
239 case SVGA3DOP_ENDREP:
240 case SVGA3DOP_IF:
241 case SVGA3DOP_IFC:
242 case SVGA3DOP_ELSE:
243 case SVGA3DOP_ENDIF:
244 case SVGA3DOP_BREAK:
245 case SVGA3DOP_BREAKC:
246 case SVGA3DOP_MOVA:
247 case SVGA3DOP_DEFB:
248 case SVGA3DOP_DEFI:
249 case SVGA3DOP_TEXCOORD:
250 case SVGA3DOP_TEXKILL:
251 case SVGA3DOP_TEX:
252 case SVGA3DOP_TEXBEM:
253 case SVGA3DOP_TEXBEML:
254 case SVGA3DOP_TEXREG2AR:
255 case SVGA3DOP_TEXREG2GB:
256 case SVGA3DOP_TEXM3x2PAD:
257 case SVGA3DOP_TEXM3x2TEX:
258 case SVGA3DOP_TEXM3x3PAD:
259 case SVGA3DOP_TEXM3x3TEX:
260 case SVGA3DOP_RESERVED0:
261 case SVGA3DOP_TEXM3x3SPEC:
262 case SVGA3DOP_TEXM3x3VSPEC:
263 case SVGA3DOP_EXPP:
264 case SVGA3DOP_LOGP:
265 case SVGA3DOP_CND:
266 case SVGA3DOP_DEF:
267 case SVGA3DOP_TEXREG2RGB:
268 case SVGA3DOP_TEXDP3TEX:
269 case SVGA3DOP_TEXM3x2DEPTH:
270 case SVGA3DOP_TEXDP3:
271 case SVGA3DOP_TEXM3x3:
272 case SVGA3DOP_TEXDEPTH:
273 case SVGA3DOP_CMP:
274 case SVGA3DOP_BEM:
275 case SVGA3DOP_DP2ADD:
276 case SVGA3DOP_DSX:
277 case SVGA3DOP_DSY:
278 case SVGA3DOP_TEXLDD:
279 case SVGA3DOP_SETP:
280 case SVGA3DOP_TEXLDL:
281 case SVGA3DOP_BREAKP:
282 case SVGA3DOP_PHASE:
283 case SVGA3DOP_COMMENT:
284 break;
285
286 default:
287 ASSERT_GUEST_FAILED_RETURN(VERR_PARSE_ERROR);
288 }
289
290 /* Next token. */
291 pToken += cInstLen + 1;
292 }
293
294 return VINF_SUCCESS;
295}
296
297void vmsvga3dShaderLogRel(char const *pszMsg, SVGA3dShaderType type, uint32_t cbShaderData, uint32_t const *pShaderData)
298{
299 /* Dump the shader code. */
300 static int scLogged = 0;
301 if (scLogged < 8)
302 {
303 ++scLogged;
304
305 LogRel(("VMSVGA: %s shader: %s:\n", (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", pszMsg));
306 const uint32_t cTokensPerLine = 8;
307 const uint32_t *paTokens = (uint32_t *)pShaderData;
308 const uint32_t cTokens = cbShaderData / sizeof(uint32_t);
309 for (uint32_t iToken = 0; iToken < cTokens; ++iToken)
310 {
311 if ((iToken % cTokensPerLine) == 0)
312 {
313 if (iToken == 0)
314 LogRel(("0x%08X,", paTokens[iToken]));
315 else
316 LogRel(("\n0x%08X,", paTokens[iToken]));
317 }
318 else
319 LogRel((" 0x%08X,", paTokens[iToken]));
320 }
321 LogRel(("\n"));
322 }
323}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette