Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/win_clang_rel_x64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ jobs:
set "PATH=%CD%\..\depot_tools;%PATH%"
set "DEPOT_TOOLS_WIN_TOOLCHAIN=0"
cd test
gn gen out\Fuzzer --args="is_debug=false gpgmm_use_fuzzing_engine=true use_libfuzzer=true is_asan=true gpgmm_enable_assert_on_warning=true gpgmm_enable_device_leak_checks=true"
gn gen out\Fuzzer --args="is_debug=false gpgmm_use_fuzzing_engine=true use_libfuzzer=true is_asan=true"

- name: Build fuzzer for main branch (with patch)
shell: cmd
Expand All @@ -172,7 +172,22 @@ jobs:
ninja -C out\Fuzzer

- name: Run gpgmm_d3d12_resource_allocator_fuzzer (with patch)
timeout-minutes: 3
shell: cmd
run: |
cd test
out\Fuzzer\gpgmm_d3d12_resource_allocator_fuzzer.exe -max_total_time=120
out\Fuzzer\gpgmm_d3d12_resource_allocator_fuzzer.exe -max_total_time=120 -timeout=10

# Workaround libFuzzer never exiting when max_total_time by using -runs instead.
# Step timeout may need to be increased to not expire before the process exits.
- name: Run gpgmm_d3d12_residency_manager_fuzzer (with patch)
timeout-minutes: 5
shell: cmd
run: |
cd test
out\Fuzzer\gpgmm_d3d12_residency_manager_fuzzer.exe -runs=20000 -timeout=10

- uses: actions/upload-artifact@v3
with:
name: fuzzer-test-reproducer
path: test/(crash|oom|leak|timeout)-.*
26 changes: 24 additions & 2 deletions src/fuzzers/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,26 @@ import("//testing/libfuzzer/fuzzer_test.gni")

if (is_win) {
fuzzer_test("gpgmm_d3d12_resource_allocator_fuzzer") {
sources = [ "D3D12ResourceAllocatorFuzzer.cpp" ]
sources = [
"D3D12Fuzzer.cpp",
"D3D12Fuzzer.h",
"D3D12ResourceAllocatorFuzzer.cpp",
]

deps = [ "${gpgmm_root_dir}:gpgmm" ]

libs = [
"d3d12.lib",
"dxgi.lib",
]
}

fuzzer_test("gpgmm_d3d12_residency_manager_fuzzer") {
sources = [
"D3D12Fuzzer.cpp",
"D3D12Fuzzer.h",
"D3D12ResidencyManagerFuzzer.cpp",
]

deps = [ "${gpgmm_root_dir}:gpgmm" ]

Expand All @@ -41,6 +60,9 @@ group("fuzzers") {
deps = []

if (is_win) {
deps += [ ":gpgmm_d3d12_resource_allocator_fuzzer" ]
deps += [
":gpgmm_d3d12_residency_manager_fuzzer",
":gpgmm_d3d12_resource_allocator_fuzzer",
]
}
}
84 changes: 84 additions & 0 deletions src/fuzzers/D3D12Fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2021 The GPGMM Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "D3D12Fuzzer.h"

uint64_t UInt8ToUInt64(const uint8_t* src) {
uint64_t dst;
memcpy(&dst, src, sizeof(uint64_t));
return dst;
}

HRESULT CreateAllocatorDesc(gpgmm::d3d12::ALLOCATOR_DESC* allocatorDesc) {
gpgmm::d3d12::ALLOCATOR_DESC allocatorDescOut = {};

// Populate the device
ComPtr<ID3D12Device> d3dDevice;
if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3dDevice)))) {
return E_FAIL;
}

allocatorDescOut.Device = d3dDevice;

// Populate the adapter
LUID adapterLUID = d3dDevice->GetAdapterLuid();
ComPtr<IDXGIFactory1> dxgiFactory;
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) {
return E_FAIL;
}

ComPtr<IDXGIFactory4> dxgiFactory4;
if (FAILED(dxgiFactory.As(&dxgiFactory4))) {
return E_FAIL;
}

ComPtr<IDXGIAdapter3> dxgiAdapter;
if (FAILED(dxgiFactory4->EnumAdapterByLuid(adapterLUID, IID_PPV_ARGS(&dxgiAdapter)))) {
return E_FAIL;
}

allocatorDescOut.Adapter = dxgiAdapter;

// Configure options
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
if (FAILED(d3dDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options,
sizeof(options)))) {
return E_FAIL;
}

allocatorDescOut.ResourceHeapTier = options.ResourceHeapTier;
allocatorDescOut.MinLogLevel = D3D12_MESSAGE_SEVERITY_MESSAGE;

if (allocatorDesc != nullptr) {
*allocatorDesc = allocatorDescOut;
}

return S_OK;
}

D3D12_RESOURCE_DESC CreateBufferDesc(uint64_t width, uint64_t alignment) {
D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resourceDesc.Alignment = 0;
resourceDesc.Width = width;
resourceDesc.Height = 1;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
return resourceDesc;
}
26 changes: 26 additions & 0 deletions src/fuzzers/D3D12Fuzzer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2021 The GPGMM Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef FUZZER_D3D12FUZZER_H_
#define FUZZER_D3D12FUZZER_H_

#include <gpgmm_d3d12.h>

uint64_t UInt8ToUInt64(const uint8_t* src);

HRESULT CreateAllocatorDesc(gpgmm::d3d12::ALLOCATOR_DESC* allocatorDesc);

D3D12_RESOURCE_DESC CreateBufferDesc(uint64_t width, uint64_t alignment = 0);

#endif // FUZZER_D3D12FUZZER_H_
115 changes: 115 additions & 0 deletions src/fuzzers/D3D12ResidencyManagerFuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2021 The GPGMM Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>

#include "testing/libfuzzer/libfuzzer_exports.h"

#include "D3D12Fuzzer.h"
#include "gpgmm/common/SizeClass.h"

namespace {

ComPtr<gpgmm::d3d12::ResourceAllocator> gResourceAllocator;
ComPtr<gpgmm::d3d12::ResidencyManager> gResidencyManager;
std::vector<ComPtr<gpgmm::d3d12::ResourceAllocation>> gAllocationsBelowBudget = {};

uint64_t GetBudgetLeft(gpgmm::d3d12::ResidencyManager* const residencyManager,
const DXGI_MEMORY_SEGMENT_GROUP& memorySegmentGroup) {
if (residencyManager == nullptr) {
return 0;
}
DXGI_QUERY_VIDEO_MEMORY_INFO* segment =
gResidencyManager->GetVideoMemoryInfo(memorySegmentGroup);
return (segment->Budget > segment->CurrentUsage) ? (segment->Budget - segment->CurrentUsage)
: 0;
}

} // namespace

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
gpgmm::d3d12::ALLOCATOR_DESC allocatorDesc = {};
if (FAILED(CreateAllocatorDesc(&allocatorDesc))) {
return 0;
}

allocatorDesc.Flags |= gpgmm::d3d12::ALLOCATOR_FLAG_ALWAYS_IN_BUDGET;

gpgmm::d3d12::RESIDENCY_DESC residencyDesc = {};

ComPtr<IDXGIAdapter3> adapter3;
if (FAILED(allocatorDesc.Adapter.As(&adapter3))) {
return 0;
}

residencyDesc.Adapter = adapter3;
residencyDesc.Device = allocatorDesc.Device;
residencyDesc.MinLogLevel = D3D12_MESSAGE_SEVERITY_MESSAGE;

// Create ResidencyManager
D3D12_FEATURE_DATA_ARCHITECTURE arch = {};
if (FAILED(residencyDesc.Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &arch,
sizeof(arch)))) {
return 0;
}

residencyDesc.IsUMA = arch.UMA;

if (FAILED(gpgmm::d3d12::ResidencyManager::CreateResidencyManager(residencyDesc,
&gResidencyManager))) {
return 0;
}

if (FAILED(gpgmm::d3d12::ResourceAllocator::CreateAllocator(
allocatorDesc, gResidencyManager.Get(), &gResourceAllocator))) {
return 0;
}

gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

const DXGI_MEMORY_SEGMENT_GROUP bufferMemorySegment =
gResidencyManager->GetMemorySegmentGroup(allocationDesc.HeapType);

constexpr uint64_t kBufferMemorySize = GPGMM_MB_TO_BYTES(1);
const D3D12_RESOURCE_DESC bufferDesc = CreateBufferDesc(kBufferMemorySize);

// Keep allocating until we reach the budget.
uint64_t memoryUnderBudget = GetBudgetLeft(gResidencyManager.Get(), bufferMemorySegment);
while (gResourceAllocator->GetInfo().UsedMemoryUsage + kBufferMemorySize < memoryUnderBudget) {
ComPtr<gpgmm::d3d12::ResourceAllocation> allocation;
if (FAILED(gResourceAllocator->CreateResource({}, bufferDesc, D3D12_RESOURCE_STATE_COMMON,
nullptr, &allocation))) {
return 0;
}

gAllocationsBelowBudget.push_back(std::move(allocation));
}

return 0;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 8) {
return 0;
}

gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<gpgmm::d3d12::ResourceAllocation> allocationOverBudget;
gResourceAllocator->CreateResource(allocationDesc, CreateBufferDesc(UInt8ToUInt64(data)),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocationOverBudget);
return 0;
}
65 changes: 4 additions & 61 deletions src/fuzzers/D3D12ResourceAllocatorFuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,19 @@

#include "testing/libfuzzer/libfuzzer_exports.h"

#include <gpgmm_d3d12.h>
#include "D3D12Fuzzer.h"

namespace {

ComPtr<gpgmm::d3d12::ResourceAllocator> gResourceAllocator;

uint64_t UInt8ToUInt64(const uint8_t* src) {
uint64_t dst;
memcpy(&dst, src, sizeof(uint64_t));
return dst;
}

} // namespace

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
gpgmm::d3d12::ALLOCATOR_DESC allocatorDesc = {};

// Populate the device
ComPtr<ID3D12Device> d3dDevice;
if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3dDevice)))) {
return 0;
}

allocatorDesc.Device = d3dDevice;

// Populate the adapter
LUID adapterLUID = d3dDevice->GetAdapterLuid();
ComPtr<IDXGIFactory1> dxgiFactory;
if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) {
return 0;
}

ComPtr<IDXGIFactory4> dxgiFactory4;
if (FAILED(dxgiFactory.As(&dxgiFactory4))) {
return 0;
}

ComPtr<IDXGIAdapter3> dxgiAdapter;
if (FAILED(dxgiFactory4->EnumAdapterByLuid(adapterLUID, IID_PPV_ARGS(&dxgiAdapter)))) {
return 0;
}

allocatorDesc.Adapter = dxgiAdapter;

// Populate the options.
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
if (FAILED(d3dDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options,
sizeof(options)))) {
if (FAILED(CreateAllocatorDesc(&allocatorDesc))) {
return 0;
}
allocatorDesc.ResourceHeapTier = options.ResourceHeapTier;

allocatorDesc.MinLogLevel = D3D12_MESSAGE_SEVERITY_MESSAGE;

if (FAILED(
gpgmm::d3d12::ResourceAllocator::CreateAllocator(allocatorDesc, &gResourceAllocator))) {
Expand All @@ -83,28 +43,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return 0;
}

if (gResourceAllocator == nullptr) {
return 0;
}

D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resourceDesc.Alignment = 0;
resourceDesc.Width = UInt8ToUInt64(data);
resourceDesc.Height = 1;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;

gpgmm::d3d12::ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<gpgmm::d3d12::ResourceAllocation> allocation;
gResourceAllocator->CreateResource(allocationDesc, resourceDesc, D3D12_RESOURCE_STATE_COMMON,
nullptr, &allocation);
gResourceAllocator->CreateResource(allocationDesc, CreateBufferDesc(UInt8ToUInt64(data)),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation);
return 0;
}