Skip to content

Commit 0b81f0b

Browse files
authored
[NFC] Apply clang-tidy (#90)
This applies a set of clang-tidy rules to enforce LLVM coding standards and some common cleanups. This PR configures clang-tidy to enforce a swath of rules that comply with and enforce LLVM's coding standards. Two new CMake options are added: OFFLOADTEST_USE_CLANG_TIDY - When set to On this runs clang-tidy on non-third-party sources in the offload-test-suite as part of the build process. OFFLOADTEST_CLANG_TIDY_APPLY_FIX - When set to On passes --fix to clang-tidy to automatically apply fix-its for any issues that have fixes available (Requires OFFLOADTEST_USE_CLANG_TIDY=On). The enabled warning set is: clang-diagnostic-* - Clang compiler diagnostics. llvm-* - LLVM coding standards misc-* - All miscellaneous rules except: misc-use-anonymous-namespace, which violates LLVM coding standards which prefers static for functions. misc-include-cleaner, which did some unholy things to a few source files and caused them to fail to compile. *misc-non-private-member-variables-in-classes, which conflicts with common patterns in LLVM code. readability-identifier-naming - Apply LLVM naming conventions Additionally this PR adds the QualifierAlignment: Left option to the .clang-format configuration because the clang-tidy misc-const-correctness rule adds const to the right of the type which is less common in every codebase ever (Thank's Clang!).
1 parent b56f850 commit 0b81f0b

22 files changed

+225
-157
lines changed

.clang-format

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
BasedOnStyle: LLVM
2+
QualifierAlignment: Left

.clang-tidy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-use-anonymous-namespace,-misc-include-cleaner,-misc-non-private-member-variables-in-classes,readability-identifier-naming'
2+
WarningsAsErrors: '*'
3+
CheckOptions:
4+
- key: readability-identifier-naming.ClassCase
5+
value: CamelCase
6+
- key: readability-identifier-naming.EnumCase
7+
value: CamelCase
8+
- key: readability-identifier-naming.FunctionCase
9+
value: camelBack
10+
- key: readability-identifier-naming.MemberCase
11+
value: CamelCase
12+
- key: readability-identifier-naming.ParameterCase
13+
value: CamelCase
14+
- key: readability-identifier-naming.UnionCase
15+
value: CamelCase
16+
- key: readability-identifier-naming.VariableCase
17+
value: CamelCase
18+
- key: readability-identifier-naming.IgnoreMainLikeFunctions
19+
value: 1
20+
ExcludeHeaderFilterRegex: ".*third-party.*"

.github/workflows/windows-intel-clang-d3d12.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
Test-Clang: On
2323
TestTarget: check-hlsl-clang-d3d12
2424
OffloadTest-branch: ${{ github.event.pull_request.head.sha || github.ref }}
25-
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
25+
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DOFFLOADTEST_USE_CLANG_TIDY=On

.github/workflows/windows-intel-clang-vk.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
Test-Clang: On
2323
TestTarget: check-hlsl-clang-vk
2424
OffloadTest-branch: ${{ github.event.pull_request.head.sha || github.ref }}
25-
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
25+
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DOFFLOADTEST_USE_CLANG_TIDY=On

.github/workflows/windows-intel-clang-warp-d3d12.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ jobs:
2222
Test-Clang: On
2323
TestTarget: check-hlsl-clang-warp-d3d12
2424
OffloadTest-branch: ${{ github.event.pull_request.head.sha || github.ref }}
25-
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
25+
LLVM-ExtraCMakeArgs: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DOFFLOADTEST_USE_CLANG_TIDY=On

CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,37 @@ set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS_BUILDTREE_ONLY png_static)
9696

9797
include(Warp)
9898

99+
# This must be after the third-party targets are generated so that we only apply
100+
# it to code in the offload-test-suite.
101+
option(OFFLOADTEST_USE_CLANG_TIDY "Use clang-tidy on offload test codebase" Off)
102+
option(OFFLOADTEST_CLANG_TIDY_APPLY_FIX "Automatically apply clang-tidy fixes" Off)
103+
104+
if (OFFLOADTEST_USE_CLANG_TIDY)
105+
find_program(CLANG_TIDY clang-tidy)
106+
if (NOT CLANG_TIDY)
107+
message(
108+
FATAL_ERROR
109+
"Clang-tidy not found in PATH, please specify CLANG_TIDY to CMake.")
110+
endif ()
111+
if (APPLE)
112+
if (CMAKE_OSX_SYSROOT)
113+
set(CLANG_TIDY_ARGS --extra-arg=-isysroot${CMAKE_OSX_SYSROOT})
114+
elseif(NOT CMAKE_CROSSCOMPILING)
115+
# xcrun -sdk macosx --show-sdk-path
116+
execute_process(COMMAND xcrun -sdk macosx --show-sdk-path
117+
OUTPUT_VARIABLE SYSROOT
118+
ERROR_QUIET
119+
OUTPUT_STRIP_TRAILING_WHITESPACE)
120+
set(CLANG_TIDY_ARGS --extra-arg=-isysroot${SYSROOT})
121+
endif()
122+
endif()
123+
if (OFFLOADTEST_CLANG_TIDY_APPLY_FIX)
124+
set(CLANG_TIDY_ARGS ${CLANG_TIDY_ARGS} --fix)
125+
endif ()
126+
set(CMAKE_C_CLANG_TIDY ${CLANG_TIDY} ${CLANG_TIDY_ARGS})
127+
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY} ${CLANG_TIDY_ARGS})
128+
endif ()
129+
99130
add_subdirectory(lib)
100131
add_subdirectory(tools)
101132

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ compiler to use by passing:
3636
-DDXC_DIR=<path to folder containing dxc & dxv>
3737
```
3838

39+
## Enabling clang-tidy
40+
41+
The offload test suite's code is clang-tidy clean for a limited ruleset.
42+
If you have clang-tidy installed locally you can enable clang-tidy by adding `-DOFFLOADTEST_USE_CLANG_TIDY=On` to your CMake invocation.
43+
You can also add `-DOFFLOADTEST_CLANG_TIDY_APPLY_FIX=On` to enable automatically applying the clang-tidy fix-its for any warnings that have automated fixes.
44+
3945
# YAML Pipeline Format
4046

4147
This framework provides a YAML representation for describing GPU pipelines and buffers. The format is implemented by the `API/Pipeline.{h|cpp}` sources. The following is an example pipeline YAML description:

docs/WSL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ Alternatively, build and install the DirectX-Headers from the [original repo](ht
2020
- Fix: Use a newer version of DXC that includes the validator binary `dxv`
2121
- `double free or corruption (!prev)` may occur when `api-query` and `offloader` exit, which then follows with an infinite stall instead of program termination
2222
- A workaround is implemented which avoids this issue on normal program exit (i.e., `return 0;` from main)
23-
- This issue appears to occur whenever `DeviceContext::Devices` from `lib/API/Device.cpp` contains more than one device.
24-
When `api-query` or `offloader` exit, some memory resources are failing to automatically free themselves.
25-
Valgrind output suggests the core issue stems from the implementation of `Microsoft::WRL::ComPtr::InternalRelease` in WSL.
23+
- This issue appears to occur whenever `DeviceContext::Devices` from `lib/API/Device.cpp` contains more than one device.
24+
When `api-query` or `offloader` exit, some memory resources are failing to automatically free themselves.
25+
Valgrind output suggests the core issue stems from the implementation of `Microsoft::WRL::ComPtr::InternalRelease` in WSL.
2626
Manually clearing `DeviceContext::Devices` before a program exit appears to eliminate the issue for the exit
27-
- An additional workaround that would cover all possible program exit points is to only select one `DXDevice` by editing `lib/API/DX/Device.cpp` to `break;` at the end of the first iteration of the for-loop in the function `InitializeDXDevices()`
27+
- An additional workaround that would cover all possible program exit points is to only select one `DXDevice` by editing `lib/API/DX/Device.cpp` to `break;` at the end of the first iteration of the for-loop in the function `initializeDXDevices()`
2828
- Before implementing this workaround, you can run `api-query` to list all GPU devices available. Afterwards, edit the `AdapterIndex` of the for-loop to select the index of the desired GPU
2929

include/API/Device.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#ifndef OFFLOADTEST_API_DEVICE_H
1313
#define OFFLOADTEST_API_DEVICE_H
1414

15+
#include "Config.h"
16+
1517
#include "API/API.h"
1618
#include "API/Capabilities.h"
1719
#include "llvm/ADT/StringRef.h"
@@ -54,6 +56,18 @@ class Device {
5456
static DeviceIterator begin();
5557
static DeviceIterator end();
5658
static inline DeviceRange devices() { return DeviceRange(begin(), end()); }
59+
60+
#ifdef OFFLOADTEST_ENABLE_D3D12
61+
static llvm::Error initializeDXDevices();
62+
#endif
63+
64+
#ifdef OFFLOADTEST_ENABLE_VULKAN
65+
static llvm::Error initializeVXDevices();
66+
#endif
67+
68+
#ifdef OFFLOADTEST_ENABLE_METAL
69+
static llvm::Error initializeMtlDevices();
70+
#endif
5771
};
5872

5973
} // namespace offloadtest

lib/API/DX/Device.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class DXDevice : public offloadtest::Device {
158158
llvm::StringRef getAPIName() const override { return "DirectX"; }
159159
GPUAPI getAPI() const override { return GPUAPI::DirectX; }
160160

161-
static llvm::Expected<DXDevice> Create(ComPtr<IDXCoreAdapter> Adapter) {
161+
static llvm::Expected<DXDevice> create(ComPtr<IDXCoreAdapter> Adapter) {
162162
ComPtr<ID3D12Device> Device;
163163
if (auto Err =
164164
HR::toError(D3D12CreateDevice(Adapter.Get(), D3D_FEATURE_LEVEL_11_0,
@@ -234,7 +234,7 @@ class DXDevice : public offloadtest::Device {
234234
HasRootSigPart = true;
235235

236236
if (HasRootSigPart) {
237-
llvm::StringRef Binary = P.Shaders[0].Shader->getBuffer();
237+
const llvm::StringRef Binary = P.Shaders[0].Shader->getBuffer();
238238
if (auto Err = HR::toError(
239239
Device->CreateRootSignature(0, Binary.data(), Binary.size(),
240240
IID_PPV_ARGS(&State.RootSig)),
@@ -244,15 +244,15 @@ class DXDevice : public offloadtest::Device {
244244
}
245245

246246
std::vector<D3D12_ROOT_PARAMETER> RootParams;
247-
uint32_t DescriptorCount = P.getDescriptorCount();
248-
std::unique_ptr<D3D12_DESCRIPTOR_RANGE[]> Ranges =
247+
const uint32_t DescriptorCount = P.getDescriptorCount();
248+
const std::unique_ptr<D3D12_DESCRIPTOR_RANGE[]> Ranges =
249249
std::unique_ptr<D3D12_DESCRIPTOR_RANGE[]>(
250250
new D3D12_DESCRIPTOR_RANGE[DescriptorCount]);
251251

252252
uint32_t RangeIdx = 0;
253253
for (const auto &D : P.Sets) {
254254
uint32_t DescriptorIdx = 0;
255-
uint32_t StartRangeIdx = RangeIdx;
255+
const uint32_t StartRangeIdx = RangeIdx;
256256
for (const auto &R : D.Resources) {
257257
switch (getDXKind(R.Kind)) {
258258
case SRV:
@@ -291,7 +291,7 @@ class DXDevice : public offloadtest::Device {
291291
D3D12SerializeRootSignature(&Desc, D3D_ROOT_SIGNATURE_VERSION_1,
292292
&Signature, &Error),
293293
"Failed to seialize root signature.")) {
294-
std::string Msg =
294+
const std::string Msg =
295295
std::string(reinterpret_cast<char *>(Error->GetBufferPointer()),
296296
Error->GetBufferSize() / sizeof(char));
297297
return joinErrors(
@@ -322,8 +322,7 @@ class DXDevice : public offloadtest::Device {
322322
return llvm::Error::success();
323323
}
324324

325-
llvm::Error createPSO(Pipeline &P, llvm::StringRef DXIL,
326-
InvocationState &State) {
325+
llvm::Error createPSO(llvm::StringRef DXIL, InvocationState &State) {
327326
const D3D12_COMPUTE_PIPELINE_STATE_DESC Desc = {
328327
State.RootSig.Get(),
329328
{DXIL.data(), DXIL.size()},
@@ -428,7 +427,7 @@ class DXDevice : public offloadtest::Device {
428427
ComPtr<ID3D12Resource> Buffer) {
429428
const uint32_t EltSize = R.getElementSize();
430429
const uint32_t NumElts = R.size() / EltSize;
431-
DXGI_FORMAT EltFormat =
430+
DXGI_FORMAT const EltFormat =
432431
R.isRaw() ? getRawDXFormat(R)
433432
: getDXFormat(R.BufferPtr->Format, R.BufferPtr->Channels);
434433
const D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {
@@ -530,7 +529,7 @@ class DXDevice : public offloadtest::Device {
530529
ComPtr<ID3D12Resource> Buffer) {
531530
const uint32_t EltSize = R.getElementSize();
532531
const uint32_t NumElts = R.size() / EltSize;
533-
DXGI_FORMAT EltFormat =
532+
DXGI_FORMAT const EltFormat =
534533
R.isRaw() ? getRawDXFormat(R)
535534
: getDXFormat(R.BufferPtr->Format, R.BufferPtr->Channels);
536535
const D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {
@@ -556,7 +555,7 @@ class DXDevice : public offloadtest::Device {
556555
}
557556

558557
llvm::Expected<ResourceSet> createCBV(Resource &R, InvocationState &IS) {
559-
size_t CBVSize = getCBVSize(R.size());
558+
const size_t CBVSize = getCBVSize(R.size());
560559
llvm::outs() << "Creating CBV: { Size = " << CBVSize << ", Register = b"
561560
<< R.DXBinding.Register << ", Space = " << R.DXBinding.Space
562561
<< " }\n";
@@ -617,7 +616,7 @@ class DXDevice : public offloadtest::Device {
617616

618617
void bindCBV(Resource &R, InvocationState &IS, const uint32_t HeapIdx,
619618
ComPtr<ID3D12Resource> Buffer) {
620-
size_t CBVSize = getCBVSize(R.size());
619+
const size_t CBVSize = getCBVSize(R.size());
621620
const D3D12_CONSTANT_BUFFER_VIEW_DESC CBVDesc = {
622621
Buffer->GetGPUVirtualAddress(), static_cast<uint32_t>(CBVSize)};
623622

@@ -754,7 +753,7 @@ class DXDevice : public offloadtest::Device {
754753
llvm::Error waitForSignal(InvocationState &IS) {
755754
// This is a hack but it works since this is all single threaded code.
756755
static uint64_t FenceCounter = 0;
757-
uint64_t CurrentCounter = FenceCounter + 1;
756+
const uint64_t CurrentCounter = FenceCounter + 1;
758757

759758
if (auto Err = HR::toError(IS.Queue->Signal(IS.Fence.Get(), CurrentCounter),
760759
"Failed to add signal."))
@@ -802,7 +801,7 @@ class DXDevice : public offloadtest::Device {
802801
IS.CmdList->SetPipelineState(IS.PSO.Get());
803802
IS.CmdList->SetComputeRootSignature(IS.RootSig.Get());
804803

805-
uint32_t Inc = Device->GetDescriptorHandleIncrementSize(
804+
const uint32_t Inc = Device->GetDescriptorHandleIncrementSize(
806805
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
807806
CD3DX12_GPU_DESCRIPTOR_HANDLE Handle;
808807

@@ -816,12 +815,13 @@ class DXDevice : public offloadtest::Device {
816815
uint32_t ConstantOffset = 0u;
817816
uint32_t RootParamIndex = 0u;
818817
uint32_t DescriptorTableIndex = 0u;
819-
auto RootDescIt = IS.RootResources.begin();
818+
auto *RootDescIt = IS.RootResources.begin();
820819
for (const auto &Param : P.Settings.DX.RootParams) {
821820
switch (Param.Kind) {
822821
case dx::RootParamKind::Constant: {
823822
auto &Constant = std::get<dx::RootConstant>(Param.Data);
824-
uint32_t NumValues = Constant.BufferPtr->size() / sizeof(uint32_t);
823+
const uint32_t NumValues =
824+
Constant.BufferPtr->size() / sizeof(uint32_t);
825825
IS.CmdList->SetComputeRoot32BitConstants(
826826
RootParamIndex++, NumValues, Constant.BufferPtr->Data.get(),
827827
ConstantOffset);
@@ -865,7 +865,7 @@ class DXDevice : public offloadtest::Device {
865865
}
866866
}
867867

868-
llvm::ArrayRef<int> DispatchSize =
868+
const llvm::ArrayRef<int> DispatchSize =
869869
llvm::ArrayRef<int>(P.Shaders[0].DispatchSize);
870870

871871
IS.CmdList->Dispatch(DispatchSize[0], DispatchSize[1], DispatchSize[2]);
@@ -886,7 +886,7 @@ class DXDevice : public offloadtest::Device {
886886
CopyBackResource(R);
887887
}
888888

889-
llvm::Error readBack(Pipeline &P, InvocationState &IS) {
889+
llvm::Error readBack(InvocationState &IS) {
890890
auto MemCpyBack = [](ResourcePair &R) -> llvm::Error {
891891
if (!R.first->isReadWrite())
892892
return llvm::Error::success();
@@ -946,7 +946,7 @@ class DXDevice : public offloadtest::Device {
946946
if (auto Err = createDescriptorHeap(P, State))
947947
return Err;
948948
llvm::outs() << "Descriptor heap created.\n";
949-
if (auto Err = createPSO(P, P.Shaders[0].Shader->getBuffer(), State))
949+
if (auto Err = createPSO(P.Shaders[0].Shader->getBuffer(), State))
950950
return Err;
951951
llvm::outs() << "PSO created.\n";
952952
if (auto Err = createCommandStructures(State))
@@ -963,7 +963,7 @@ class DXDevice : public offloadtest::Device {
963963
if (auto Err = executeCommandList(State))
964964
return Err;
965965
llvm::outs() << "Compute commands executed.\n";
966-
if (auto Err = readBack(P, State))
966+
if (auto Err = readBack(State))
967967
return Err;
968968
llvm::outs() << "Read data back.\n";
969969

@@ -972,7 +972,7 @@ class DXDevice : public offloadtest::Device {
972972
};
973973
} // namespace
974974

975-
llvm::Error InitializeDXDevices() {
975+
llvm::Error Device::initializeDXDevices() {
976976
#ifdef _WIN32
977977
#ifndef NDEBUG
978978
ComPtr<ID3D12Debug1> Debug1;
@@ -1010,7 +1010,7 @@ llvm::Error InitializeDXDevices() {
10101010
"Failed to acquire adapter")) {
10111011
return Err;
10121012
}
1013-
auto ExDevice = DXDevice::Create(Adapter);
1013+
auto ExDevice = DXDevice::create(Adapter);
10141014
if (!ExDevice)
10151015
return ExDevice.takeError();
10161016
auto ShPtr = std::make_shared<DXDevice>(*ExDevice);

0 commit comments

Comments
 (0)