blob: 1a58c8f814d1488d8ea0bbd548f6287e45d992e6 [file] [log] [blame]
José Fonsecafc550c52012-11-18 11:57:56 +00001/**************************************************************************
2 *
3 * Copyright 2012 Jose Fonseca
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sub license,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * AUTHORS,
21 * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 **************************************************************************/
27
28
29/*
30 * Auxiliary functions to compute the size of array/blob arguments.
31 */
32
Jose Fonseca9653f952015-05-19 16:32:43 +010033#pragma once
José Fonsecafc550c52012-11-18 11:57:56 +000034
35
36/* We purposedly don't include any D3D header, so that this header can be used
37 * with all D3D versions. */
38
39#include <assert.h>
40
Jose Fonseca595728c2016-08-26 16:06:24 +010041#include <algorithm>
42
José Fonsecafc550c52012-11-18 11:57:56 +000043#include "os.hpp"
44
45
46static inline size_t
47_vertexCount(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount)
48{
49 switch (PrimitiveType) {
50 case D3DPT_POINTLIST:
51 return PrimitiveCount;
52 case D3DPT_LINELIST:
53 return PrimitiveCount*2;
54 case D3DPT_LINESTRIP:
55 return PrimitiveCount + 1;
56 case D3DPT_TRIANGLELIST:
57 return PrimitiveCount * 3;
58 case D3DPT_TRIANGLESTRIP:
59 return PrimitiveCount + 2;
60 case D3DPT_TRIANGLEFAN:
José Fonseca2b36b812013-05-03 10:47:39 +010061 return PrimitiveCount + 2;
José Fonsecafc550c52012-11-18 11:57:56 +000062 default:
63 os::log("apitrace: warning: %s: unknown D3DPRIMITIVETYPE %u\n", __FUNCTION__, PrimitiveType);
64 return 0;
65 }
66}
67
68
69static inline size_t
70_vertexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, UINT VertexStride) {
71 return _vertexCount(PrimitiveType, PrimitiveCount) * VertexStride;
72}
73
74
75static inline size_t
76_indexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, D3DFORMAT IndexDataFormat) {
77 UINT IndexStride;
78 switch (IndexDataFormat) {
79 case D3DFMT_INDEX16:
80 IndexStride = 2;
81 break;
82 case D3DFMT_INDEX32:
83 IndexStride = 4;
84 break;
85 default:
86 os::log("apitrace: warning: %s: unexpected index D3DFORMAT %u\n", __FUNCTION__, IndexDataFormat);
87 return 0;
88 }
89 return _vertexCount(PrimitiveType, PrimitiveCount) * IndexStride;
90}
91
92
93/*
94 * Return the number of tokens for a given shader.
95 */
96static inline size_t
97_shaderSize(const DWORD *pFunction)
98{
99 DWORD dwLength = 0;
100
Jose Fonseca8f7873a2019-08-27 15:00:10 +0100101 // Version token
102 // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/version-token
103 DWORD dwVersion = pFunction[dwLength++];
José Fonsecafc550c52012-11-18 11:57:56 +0000104
Jose Fonseca8f7873a2019-08-27 15:00:10 +0100105 if (D3DSHADER_VERSION_MAJOR(dwVersion) >= 2) {
106 // Advance tokens using instruction length
107 // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/instruction-token
108 while (true) {
109 DWORD dwToken = pFunction[dwLength++];
110 D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode = D3DSHADER_INSTRUCTION_OPCODE_TYPE(dwToken & D3DSI_OPCODE_MASK);
111 switch (opcode) {
112 case D3DSIO_COMMENT:
113 dwLength += (dwToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
114 break;
José Fonsecafc550c52012-11-18 11:57:56 +0000115
Jose Fonseca8f7873a2019-08-27 15:00:10 +0100116 case D3DSIO_END:
117 assert(dwToken == D3DSIO_END);
118 if (dwToken == D3DSIO_END) {
119 return dwLength * sizeof *pFunction;
120 }
121 break;
122
123 default:
124 dwLength += (dwToken & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT;
125 break;
126 }
127 }
128 } else {
129 // Advance tokens using bit 31
130 while (true) {
131 DWORD dwToken = pFunction[dwLength++];
132
133 // Skip Destination/Source/Label tokens
134 if (dwToken & 0x80000000U) {
135 continue;
136 }
Jose Fonsecadebbeb42019-08-27 16:04:46 +0100137
megai268328e02019-08-22 08:38:00 +0300138 D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode = D3DSHADER_INSTRUCTION_OPCODE_TYPE(dwToken & D3DSI_OPCODE_MASK);
megai268328e02019-08-22 08:38:00 +0300139 switch (opcode) {
140 case D3DSIO_COMMENT:
141 dwLength += (dwToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
142 break;
Jose Fonsecadebbeb42019-08-27 16:04:46 +0100143
megai268328e02019-08-22 08:38:00 +0300144 case D3DSIO_DEF:
Jose Fonsecadebbeb42019-08-27 16:04:46 +0100145 // Contains raw floating point so can't be advanced with the 31 bit test.
146 // NOTE: DEFB/DEFI are SM 2 only.
megai268328e02019-08-22 08:38:00 +0300147 dwLength += 5;
148 break;
Jose Fonsecadebbeb42019-08-27 16:04:46 +0100149
150 case D3DSIO_END:
151 // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/end-token
152 if (dwToken == D3DSIO_END) {
153 return dwLength * sizeof *pFunction;
154 }
megai268328e02019-08-22 08:38:00 +0300155 break;
Jose Fonsecadebbeb42019-08-27 16:04:46 +0100156
157 default:
158 break;
José Fonsecafc550c52012-11-18 11:57:56 +0000159 }
José Fonsecafc550c52012-11-18 11:57:56 +0000160 }
161 }
162}
163
164
Jose Fonseca127cc412015-07-06 12:33:41 +0100165static inline void
166_getFormatSize(D3DFORMAT Format, size_t & BlockSize, UINT & BlockWidth, UINT & BlockHeight);
167
Jose Fonseca614c5da2016-02-19 12:32:45 +0000168#define PACKED_PITCH 0x7ffffff
169
José Fonsecafc550c52012-11-18 11:57:56 +0000170static inline size_t
Jose Fonseca614c5da2016-02-19 12:32:45 +0000171_getLockSize(D3DFORMAT Format, bool Partial, UINT Width, UINT Height, INT RowPitch = PACKED_PITCH, UINT Depth = 1, INT SlicePitch = 0) {
José Fonsecafc550c52012-11-18 11:57:56 +0000172 if (Width == 0 || Height == 0 || Depth == 0) {
173 return 0;
174 }
175
176 if (RowPitch < 0) {
177 os::log("apitrace: warning: %s: negative row pitch %i\n", __FUNCTION__, RowPitch);
178 return 0;
179 }
180
Jose Fonseca127cc412015-07-06 12:33:41 +0100181 size_t size;
182 if (Format == MAKEFOURCC('N','V','1','2') ||
183 Format == MAKEFOURCC('Y','V','1','2')) {
184 // Planar YUV
Jose Fonseca614c5da2016-02-19 12:32:45 +0000185
186 if (RowPitch == PACKED_PITCH) {
187 RowPitch = Width;
188 }
189
Jose Fonseca127cc412015-07-06 12:33:41 +0100190 size = (Height + (Height + 1)/2) * RowPitch;
Jose Fonseca595728c2016-08-26 16:06:24 +0100191 } else if (Format == MAKEFOURCC('A','T','I','1')) {
192 // 64 bits per 4x4 block, but limited to height*pitch
193
194 if (RowPitch == PACKED_PITCH) {
195 RowPitch = Width;
196 }
197
198 size = std::min(Height * RowPitch, ((Height + 3)/4) * ((Width + 3)/4) * (64 / 8));
199 } else if (Format == MAKEFOURCC('A','T','I','2')) {
200 // 128 bits per 4x4 block, but limited to height*pitch
201
202 if (RowPitch == PACKED_PITCH) {
203 RowPitch = Width;
204 }
205
206 size = std::min(Height * RowPitch, ((Height + 3)/4) * ((Width + 3)/4) * (128 / 8));
Jose Fonseca127cc412015-07-06 12:33:41 +0100207 } else {
Jose Fonseca2ec73fa2015-07-13 15:34:04 +0100208 size_t BlockSize;
209 UINT BlockWidth;
210 UINT BlockHeight;
211 _getFormatSize(Format, BlockSize, BlockWidth, BlockHeight);
212 assert(BlockHeight);
213 Height = (Height + BlockHeight - 1) / BlockHeight;
214
Jose Fonseca614c5da2016-02-19 12:32:45 +0000215 if (RowPitch == PACKED_PITCH) {
216 RowPitch = ((Width + BlockWidth - 1) / BlockWidth * BlockSize + 7) / 8;
217 }
218
Jose Fonseca127cc412015-07-06 12:33:41 +0100219 size = Height * RowPitch;
220
221 if (Partial || Height == 1) {
222 // Must take pixel size in consideration
Jose Fonseca2ec73fa2015-07-13 15:34:04 +0100223 if (BlockWidth) {
Jose Fonseca614c5da2016-02-19 12:32:45 +0000224 Width = (Width + BlockWidth - 1) / BlockWidth;
225 size = (Width * BlockSize + 7) / 8;
Jose Fonseca127cc412015-07-06 12:33:41 +0100226 if (Height > 1) {
227 size += (Height - 1) * RowPitch;
228 }
229 }
230 }
José Fonsecafc550c52012-11-18 11:57:56 +0000231 }
232
José Fonsecafc550c52012-11-18 11:57:56 +0000233 if (Depth > 1) {
Jose Fonseca127cc412015-07-06 12:33:41 +0100234 if (SlicePitch < 0) {
235 os::log("apitrace: warning: %s: negative slice pitch %i\n", __FUNCTION__, SlicePitch);
236 return 0;
237 }
238
José Fonsecafc550c52012-11-18 11:57:56 +0000239 size += (Depth - 1) * SlicePitch;
240 }
241
242 return size;
243}
244
245