WIP
This commit is contained in:
236
vav2/platforms/windows/tests/separate-texture-test/src/main.cpp
Normal file
236
vav2/platforms/windows/tests/separate-texture-test/src/main.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user