1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 #include "shared/source/command_stream/command_stream_receiver.h"
10 #include "shared/source/command_stream/linear_stream.h"
11 #include "shared/source/helpers/pipeline_select_helper.h"
12 #include "shared/source/helpers/ptr_math.h"
13 #include "shared/source/os_interface/hw_info_config.h"
14 #include "shared/test/common/cmd_parse/gen_cmd_parse.h"
15 #include "shared/test/common/helpers/default_hw_info.h"
16 
17 #include "gtest/gtest.h"
18 
19 namespace NEO {
20 
21 struct HardwareParse {
HardwareParseHardwareParse22     HardwareParse() {
23         itorMediaInterfaceDescriptorLoad = cmdList.end();
24         itorMediaVfeState = cmdList.end();
25         itorPipelineSelect = cmdList.end();
26         itorStateBaseAddress = cmdList.end();
27         itorWalker = cmdList.end();
28         itorGpgpuCsrBaseAddress = cmdList.end();
29     }
30 
SetUpHardwareParse31     void SetUp() {
32     }
33 
TearDownHardwareParse34     void TearDown() {
35         cmdList.clear();
36         lriList.clear();
37         pipeControlList.clear();
38     }
39 
40     template <typename CmdType>
getCommandsListHardwareParse41     GenCmdList getCommandsList() {
42         GenCmdList list;
43         for (auto it = cmdList.begin(); it != cmdList.end(); it++) {
44             auto cmd = genCmdCast<CmdType *>(*it);
45             if (cmd) {
46                 list.push_back(*it);
47             }
48         }
49         return list;
50     }
51 
52     template <typename FamilyType>
53     void findCsrBaseAddress();
54 
55     template <typename FamilyType>
56     void findHardwareCommands();
57 
58     template <typename FamilyType>
59     void findHardwareCommands(IndirectHeap *dsh);
60 
61     template <typename FamilyType>
62     void parseCommands(NEO::LinearStream &commandStream, size_t startOffset = 0) {
63         ASSERT_LE(startOffset, commandStream.getUsed());
64         auto sizeToParse = commandStream.getUsed() - startOffset;
65         ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
66             cmdList,
67             ptrOffset(commandStream.getCpuBase(), startOffset),
68             sizeToParse));
69     }
70 
71     template <typename FamilyType>
parseCommandsHardwareParse72     void parseCommands(NEO::CommandStreamReceiver &commandStreamReceiver, NEO::LinearStream &commandStream) {
73         auto &commandStreamCSR = commandStreamReceiver.getCS();
74 
75         parseCommands<FamilyType>(commandStreamCSR, startCSRCS);
76         startCSRCS = commandStreamCSR.getUsed();
77 
78         if (previousCS != &commandStream) {
79             startCS = 0;
80         }
81         parseCommands<FamilyType>(commandStream, startCS);
82         startCS = commandStream.getUsed();
83         previousCS = &commandStream;
84 
85         sizeUsed = commandStream.getUsed();
86         findHardwareCommands<FamilyType>(&commandStreamReceiver.getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0));
87     }
88 
89     template <typename FamilyType>
getSurfaceStateHardwareParse90     const typename FamilyType::RENDER_SURFACE_STATE &getSurfaceState(IndirectHeap *ssh, uint32_t index) {
91         typedef typename FamilyType::BINDING_TABLE_STATE BINDING_TABLE_STATE;
92         typedef typename FamilyType::INTERFACE_DESCRIPTOR_DATA INTERFACE_DESCRIPTOR_DATA;
93         typedef typename FamilyType::RENDER_SURFACE_STATE RENDER_SURFACE_STATE;
94         typedef typename FamilyType::STATE_BASE_ADDRESS STATE_BASE_ADDRESS;
95 
96         const auto &interfaceDescriptorData = *(INTERFACE_DESCRIPTOR_DATA *)cmdInterfaceDescriptorData;
97 
98         auto cmdSBA = (STATE_BASE_ADDRESS *)cmdStateBaseAddress;
99         auto surfaceStateHeap = cmdSBA->getSurfaceStateBaseAddress();
100         if (ssh && (ssh->getHeapGpuBase() == surfaceStateHeap)) {
101             surfaceStateHeap = reinterpret_cast<uint64_t>(ssh->getCpuBase());
102         }
103         EXPECT_NE(0u, surfaceStateHeap);
104 
105         auto bindingTablePointer = interfaceDescriptorData.getBindingTablePointer();
106 
107         const auto &bindingTableState = reinterpret_cast<BINDING_TABLE_STATE *>(surfaceStateHeap + bindingTablePointer)[index];
108         auto surfaceStatePointer = bindingTableState.getSurfaceStatePointer();
109 
110         return *(RENDER_SURFACE_STATE *)(surfaceStateHeap + surfaceStatePointer);
111     }
112 
113     template <typename FamilyType>
getSamplerStateHardwareParse114     const typename FamilyType::SAMPLER_STATE &getSamplerState(uint32_t index) {
115         typedef typename FamilyType::INTERFACE_DESCRIPTOR_DATA INTERFACE_DESCRIPTOR_DATA;
116         typedef typename FamilyType::SAMPLER_STATE SAMPLER_STATE;
117         typedef typename FamilyType::STATE_BASE_ADDRESS STATE_BASE_ADDRESS;
118 
119         const auto &interfaceDescriptorData = *(INTERFACE_DESCRIPTOR_DATA *)cmdInterfaceDescriptorData;
120 
121         auto cmdSBA = (STATE_BASE_ADDRESS *)cmdStateBaseAddress;
122         auto dynamicStateHeap = cmdSBA->getDynamicStateBaseAddress();
123         EXPECT_NE(0, dynamicStateHeap);
124 
125         const auto samplerState = reinterpret_cast<SAMPLER_STATE *>(dynamicStateHeap + interfaceDescriptorData.getSamplerStatePointer());
126         return samplerState[index];
127     }
128 
129     template <typename FamilyType>
130     const void *getStatelessArgumentPointer(const KernelInfo &kernelInfo, uint32_t indexArg, IndirectHeap &ioh, uint32_t rootDeviceIndex);
131 
132     template <typename CmdType>
getCommandHardwareParse133     CmdType *getCommand(GenCmdList::iterator itorStart, GenCmdList::iterator itorEnd) {
134         auto itorCmd = find<CmdType *>(itorStart, itorEnd);
135         return itorCmd != cmdList.end()
136                    ? genCmdCast<CmdType *>(*itorCmd)
137                    : nullptr;
138     }
139 
140     template <typename CmdType>
getCommandHardwareParse141     CmdType *getCommand() {
142         return getCommand<CmdType>(cmdList.begin(), cmdList.end());
143     }
144 
145     template <typename FamilyType>
getNumberOfPipelineSelectsThatEnablePipelineSelectHardwareParse146     int getNumberOfPipelineSelectsThatEnablePipelineSelect() {
147         typedef typename FamilyType::PIPELINE_SELECT PIPELINE_SELECT;
148         int numberOfGpgpuSelects = 0;
149         int numberOf3dSelects = 0;
150         auto itorCmd = find<PIPELINE_SELECT *>(cmdList.begin(), cmdList.end());
151         while (itorCmd != cmdList.end()) {
152             auto cmd = getCommand<PIPELINE_SELECT>(itorCmd, cmdList.end());
153             if (cmd->getPipelineSelection() == PIPELINE_SELECT::PIPELINE_SELECTION_GPGPU &&
154                 pipelineSelectEnablePipelineSelectMaskBits == (pipelineSelectEnablePipelineSelectMaskBits & cmd->getMaskBits())) {
155                 numberOfGpgpuSelects++;
156             }
157             if (cmd->getPipelineSelection() == PIPELINE_SELECT::PIPELINE_SELECTION_3D &&
158                 pipelineSelectEnablePipelineSelectMaskBits == (pipelineSelectEnablePipelineSelectMaskBits & cmd->getMaskBits())) {
159                 numberOf3dSelects++;
160             }
161             itorCmd = find<PIPELINE_SELECT *>(++itorCmd, cmdList.end());
162         }
163         const auto &hwInfoConfig = *HwInfoConfig::get(defaultHwInfo->platform.eProductFamily);
164         if (hwInfoConfig.is3DPipelineSelectWARequired()) {
165             auto maximalNumberOf3dSelectsRequired = 2;
166             EXPECT_LE(numberOf3dSelects, maximalNumberOf3dSelectsRequired);
167             EXPECT_EQ(numberOf3dSelects, numberOfGpgpuSelects);
168             auto numberOfGpgpuSelectsAddedByWa = numberOf3dSelects - 1;
169             numberOfGpgpuSelects -= numberOfGpgpuSelectsAddedByWa;
170         } else {
171             EXPECT_EQ(0, numberOf3dSelects);
172         }
173         return numberOfGpgpuSelects;
174     }
175 
176     template <typename CmdType>
getCommandCountHardwareParse177     uint32_t getCommandCount() {
178         GenCmdList::iterator cmdItor = cmdList.begin();
179         uint32_t cmdCount = 0;
180 
181         do {
182             cmdItor = find<CmdType *>(cmdItor, cmdList.end());
183             if (cmdItor != cmdList.end()) {
184                 ++cmdCount;
185                 ++cmdItor;
186             }
187         } while (cmdItor != cmdList.end());
188 
189         return cmdCount;
190     }
191 
192     template <typename FamilyType>
getCommandNameHardwareParse193     static const char *getCommandName(void *cmd) {
194         return FamilyType::PARSE::getCommandName(cmd);
195     }
196 
197     // The starting point of parsing commandBuffers.  This is important
198     // because as buffers get reused, we only want to parse the deltas.
199     LinearStream *previousCS = nullptr;
200     size_t startCS = 0u;
201     size_t startCSRCS = 0u;
202 
203     size_t sizeUsed = 0u;
204     GenCmdList cmdList;
205     GenCmdList lriList;
206     GenCmdList pipeControlList;
207     GenCmdList::iterator itorMediaInterfaceDescriptorLoad;
208     GenCmdList::iterator itorMediaVfeState;
209     GenCmdList::iterator itorPipelineSelect;
210     GenCmdList::iterator itorStateBaseAddress;
211     GenCmdList::iterator itorWalker;
212     GenCmdList::iterator itorBBStartAfterWalker;
213     GenCmdList::iterator itorGpgpuCsrBaseAddress;
214 
215     void *cmdInterfaceDescriptorData = nullptr;
216     void *cmdMediaInterfaceDescriptorLoad = nullptr;
217     void *cmdMediaVfeState = nullptr;
218     void *cmdPipelineSelect = nullptr;
219     void *cmdStateBaseAddress = nullptr;
220     void *cmdWalker = nullptr;
221     void *cmdBBStartAfterWalker = nullptr;
222     void *cmdGpgpuCsrBaseAddress = nullptr;
223 
224     bool parsePipeControl = false;
225 };
226 
227 } // namespace NEO
228