This commit is contained in:
2025-10-05 22:52:20 +09:00
parent 517feee3f1
commit 6f6873dc8a
5 changed files with 1318 additions and 1 deletions

View File

@@ -0,0 +1,236 @@
#include <windows.h>
#include <d3d12.h>
#include <dxgi1_6.h>
#include <stdio.h>
#include <cuda.h>
#include <cuda_runtime.h>
// Simple test to verify that D3D12 R8/RG8 textures with ROW_MAJOR layout
// can be successfully created and used for CUDA-D3D12 interop
bool CreateD3D12Device(ID3D12Device** out_device)
{
IDXGIFactory4* factory = nullptr;
HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&factory));
if (FAILED(hr)) {
printf("[ERROR] CreateDXGIFactory2 failed: 0x%08X\n", hr);
return false;
}
IDXGIAdapter1* adapter = nullptr;
for (UINT i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
adapter->Release();
continue;
}
hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(out_device));
if (SUCCEEDED(hr)) {
printf("[OK] Created D3D12 device on: %ls\n", desc.Description);
adapter->Release();
factory->Release();
return true;
}
adapter->Release();
}
factory->Release();
printf("[ERROR] No suitable D3D12 adapter found\n");
return false;
}
ID3D12Resource* CreateYPlaneTexture(ID3D12Device* device, uint32_t width, uint32_t height)
{
D3D12_RESOURCE_DESC desc = {};
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Width = width;
desc.Height = height;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_R8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; // Linear layout for CUDA
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
D3D12_HEAP_PROPERTIES heap_props = {};
heap_props.Type = D3D12_HEAP_TYPE_DEFAULT;
ID3D12Resource* texture = nullptr;
HRESULT hr = device->CreateCommittedResource(
&heap_props,
D3D12_HEAP_FLAG_SHARED,
&desc,
D3D12_RESOURCE_STATE_COMMON,
nullptr,
IID_PPV_ARGS(&texture));
if (FAILED(hr)) {
printf("[ERROR] Failed to create Y plane texture: 0x%08X\n", hr);
return nullptr;
}
printf("[OK] Created Y plane texture (%u x %u, R8_UNORM, ROW_MAJOR)\n", width, height);
return texture;
}
ID3D12Resource* CreateUVPlaneTexture(ID3D12Device* device, uint32_t width, uint32_t height)
{
D3D12_RESOURCE_DESC desc = {};
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Width = width;
desc.Height = height / 2;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_R8G8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; // Linear layout for CUDA
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
D3D12_HEAP_PROPERTIES heap_props = {};
heap_props.Type = D3D12_HEAP_TYPE_DEFAULT;
ID3D12Resource* texture = nullptr;
HRESULT hr = device->CreateCommittedResource(
&heap_props,
D3D12_HEAP_FLAG_SHARED,
&desc,
D3D12_RESOURCE_STATE_COMMON,
nullptr,
IID_PPV_ARGS(&texture));
if (FAILED(hr)) {
printf("[ERROR] Failed to create UV plane texture: 0x%08X\n", hr);
return nullptr;
}
printf("[OK] Created UV plane texture (%u x %u, RG8_UNORM, ROW_MAJOR)\n", width, height / 2);
return texture;
}
bool TestCUDAImport(ID3D12Device* device, ID3D12Resource* texture, const char* plane_name)
{
// Create shared handle
HANDLE shared_handle = nullptr;
HRESULT hr = device->CreateSharedHandle(texture, nullptr, GENERIC_ALL, nullptr, &shared_handle);
if (FAILED(hr)) {
printf("[ERROR] CreateSharedHandle failed for %s: 0x%08X\n", plane_name, hr);
return false;
}
// Get resource size
D3D12_RESOURCE_DESC desc = texture->GetDesc();
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = device->GetResourceAllocationInfo(0, 1, &desc);
printf("[%s] Allocation size: %llu bytes\n", plane_name, alloc_info.SizeInBytes);
// Import to CUDA
cudaExternalMemoryHandleDesc mem_desc = {};
mem_desc.type = cudaExternalMemoryHandleTypeD3D12Heap;
mem_desc.handle.win32.handle = shared_handle;
mem_desc.size = alloc_info.SizeInBytes;
mem_desc.flags = cudaExternalMemoryDedicated;
cudaExternalMemory_t external_memory;
cudaError_t err = cudaImportExternalMemory(&external_memory, &mem_desc);
CloseHandle(shared_handle);
if (err != cudaSuccess) {
printf("[ERROR] cudaImportExternalMemory failed for %s: %d (%s)\n",
plane_name, err, cudaGetErrorString(err));
return false;
}
// Map to buffer
cudaExternalMemoryBufferDesc buffer_desc = {};
buffer_desc.size = mem_desc.size;
CUdeviceptr device_ptr;
err = cudaExternalMemoryGetMappedBuffer((void**)&device_ptr, external_memory, &buffer_desc);
if (err != cudaSuccess) {
printf("[ERROR] cudaExternalMemoryGetMappedBuffer failed for %s: %d (%s)\n",
plane_name, err, cudaGetErrorString(err));
cudaDestroyExternalMemory(external_memory);
return false;
}
printf("[OK] %s CUDA import successful: device_ptr=0x%llX\n", plane_name, device_ptr);
// Cleanup
cudaDestroyExternalMemory(external_memory);
return true;
}
int main()
{
printf("==== Separate Y/UV Texture Test ====\n\n");
// Test parameters
const uint32_t WIDTH = 1920;
const uint32_t HEIGHT = 1080;
// Step 1: Create D3D12 device
printf("[Step 1] Creating D3D12 device...\n");
ID3D12Device* device = nullptr;
if (!CreateD3D12Device(&device)) {
return 1;
}
// Step 2: Initialize CUDA
printf("\n[Step 2] Initializing CUDA...\n");
cudaError_t err = cudaSetDevice(0);
if (err != cudaSuccess) {
printf("[ERROR] cudaSetDevice failed: %d (%s)\n", err, cudaGetErrorString(err));
device->Release();
return 1;
}
printf("[OK] CUDA initialized\n");
// Step 3: Create Y plane texture
printf("\n[Step 3] Creating Y plane texture...\n");
ID3D12Resource* y_texture = CreateYPlaneTexture(device, WIDTH, HEIGHT);
if (!y_texture) {
device->Release();
return 1;
}
// Step 4: Create UV plane texture
printf("\n[Step 4] Creating UV plane texture...\n");
ID3D12Resource* uv_texture = CreateUVPlaneTexture(device, WIDTH, HEIGHT);
if (!uv_texture) {
y_texture->Release();
device->Release();
return 1;
}
// Step 5: Test CUDA import for Y plane
printf("\n[Step 5] Testing CUDA import for Y plane...\n");
bool y_success = TestCUDAImport(device, y_texture, "Y Plane");
// Step 6: Test CUDA import for UV plane
printf("\n[Step 6] Testing CUDA import for UV plane...\n");
bool uv_success = TestCUDAImport(device, uv_texture, "UV Plane");
// Cleanup
uv_texture->Release();
y_texture->Release();
device->Release();
// Final result
printf("\n==== Test Result ====\n");
if (y_success && uv_success) {
printf("[SUCCESS] Both Y and UV planes can be imported to CUDA!\n");
printf("This confirms that separate R8/RG8 textures with ROW_MAJOR layout work for D3D12-CUDA interop.\n");
return 0;
} else {
printf("[FAILED] CUDA import failed\n");
return 1;
}
}