summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-03-25 11:48:10 -0400
committerGitHub <noreply@github.com>2019-03-25 11:48:10 -0400
commit2f4029a753f72833c30c4e6bad28c06b20540384 (patch)
treeca771b5e00c6126351079b2df920d014e4ed6a1e
parent5bdc3ef07373be62363deb64dedd4163589430b6 (diff)
Adapter selection for Renderer (#923)
* * Make adapter used selectable on the command line * Added 'adapter' to Renderer::Desc with dx11, dx12, vk honoring it * GL will check that the renderer matches, but cannot select a specific device * Share functionality on dx adapter selection in D3DUtil Note - that on tests that use OpenGL and the adapter doesn't match it will ignore the test (and display a message that the appropriate device couldn't be started) * Small function name improvement. * Variable rename to match type. * Fix typo in Dx12 device selection. * * Add checking if an adapter is warp * Improve some comments
-rw-r--r--tools/gfx/d3d-util.cpp147
-rw-r--r--tools/gfx/d3d-util.h18
-rw-r--r--tools/gfx/render-d3d11.cpp25
-rw-r--r--tools/gfx/render-d3d12.cpp105
-rw-r--r--tools/gfx/render-gl.cpp13
-rw-r--r--tools/gfx/render-vk.cpp33
-rw-r--r--tools/gfx/render.cpp13
-rw-r--r--tools/gfx/render.h8
-rw-r--r--tools/render-test/options.cpp10
-rw-r--r--tools/render-test/options.h2
-rw-r--r--tools/render-test/render-test-main.cpp13
-rw-r--r--tools/slang-test/options.cpp9
-rw-r--r--tools/slang-test/options.h3
-rw-r--r--tools/slang-test/slang-test-main.cpp22
14 files changed, 336 insertions, 85 deletions
diff --git a/tools/gfx/d3d-util.cpp b/tools/gfx/d3d-util.cpp
index f479af186..cdbf0bfdb 100644
--- a/tools/gfx/d3d-util.cpp
+++ b/tools/gfx/d3d-util.cpp
@@ -3,6 +3,8 @@
#include <d3dcompiler.h>
+#include <dxgi1_4.h>
+
// We will use the C standard library just for printing error messages.
#include <stdio.h>
@@ -304,4 +306,149 @@ bool D3DUtil::isTypeless(DXGI_FORMAT format)
}
}
+/* static */HMODULE D3DUtil::getDxgiModule()
+{
+ static HMODULE s_dxgiModule = LoadLibraryA("dxgi.dll");
+ if (!s_dxgiModule)
+ {
+ fprintf(stderr, "error: failed load 'dxgi.dll'\n");
+ return nullptr;
+ }
+
+ return s_dxgiModule;
+}
+
+/* static */SlangResult D3DUtil::createFactory(DeviceCheckFlags flags, ComPtr<IDXGIFactory>& outFactory)
+{
+ auto dxgiModule = getDxgiModule();
+ if (!dxgiModule)
+ {
+ return SLANG_FAIL;
+ }
+
+ typedef HRESULT(WINAPI *PFN_DXGI_CREATE_FACTORY)(REFIID riid, void **ppFactory);
+ typedef HRESULT(WINAPI *PFN_DXGI_CREATE_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void **ppFactory);
+
+ {
+ auto createFactory2 = (PFN_DXGI_CREATE_FACTORY_2)::GetProcAddress(dxgiModule, "CreateDXGIFactory2");
+ if (createFactory2)
+ {
+ UINT dxgiFlags = 0;
+
+ if (flags & DeviceCheckFlag::UseDebug)
+ {
+ dxgiFlags |= DXGI_CREATE_FACTORY_DEBUG;
+ }
+
+ ComPtr<IDXGIFactory4> factory;
+ SLANG_RETURN_ON_FAIL(createFactory2(dxgiFlags, IID_PPV_ARGS(factory.writeRef())));
+
+ outFactory = factory;
+ return SLANG_OK;
+ }
+ }
+
+ {
+ auto createFactory = (PFN_DXGI_CREATE_FACTORY)::GetProcAddress(dxgiModule, "CreateDXGIFactory");
+ if (!createFactory)
+ {
+ fprintf(stderr, "error: failed load symbol '%s'\n", "CreateDXGIFactory");
+ return SLANG_FAIL;
+ }
+ return createFactory(IID_PPV_ARGS(outFactory.writeRef()));
+ }
+}
+
+/* static */SlangResult D3DUtil::findAdapters(DeviceCheckFlags flags, const Slang::UnownedStringSlice& adapaterName, List<ComPtr<IDXGIAdapter>>& outDxgiAdapters)
+{
+ ComPtr<IDXGIFactory> factory;
+ SLANG_RETURN_ON_FAIL(createFactory(flags, factory));
+ return findAdapters(flags, adapaterName, factory, outDxgiAdapters);
+}
+
+static bool _isMatch(IDXGIAdapter* adapter, const Slang::UnownedStringSlice& lowerAdapaterName)
+{
+ if (lowerAdapaterName.size() == 0)
+ {
+ return true;
+ }
+
+ DXGI_ADAPTER_DESC desc;
+ adapter->GetDesc(&desc);
+
+ String descName = String::FromWString(desc.Description).ToLower();
+
+ return descName.IndexOf(lowerAdapaterName) != UInt(-1);
+}
+
+/* static */bool D3DUtil::isWarp(IDXGIFactory* dxgiFactory, IDXGIAdapter* adapterIn)
+{
+ ComPtr<IDXGIFactory4> dxgiFactory4;
+ if (SLANG_SUCCEEDED(dxgiFactory->QueryInterface(IID_PPV_ARGS(dxgiFactory4.writeRef()))))
+ {
+ ComPtr<IDXGIAdapter> warpAdapter;
+ dxgiFactory4->EnumWarpAdapter(IID_PPV_ARGS(warpAdapter.writeRef()));
+
+ return adapterIn == warpAdapter;
+ }
+
+ return false;
+}
+
+/* static */SlangResult D3DUtil::findAdapters(DeviceCheckFlags flags, const UnownedStringSlice& adapterName, IDXGIFactory* dxgiFactory, List<ComPtr<IDXGIAdapter>>& outDxgiAdapters)
+{
+ String lowerAdapterName = String(adapterName).ToLower();
+
+ outDxgiAdapters.Clear();
+
+ ComPtr<IDXGIAdapter> warpAdapter;
+ if ((flags & DeviceCheckFlag::UseHardwareDevice) == 0)
+ {
+ ComPtr<IDXGIFactory4> dxgiFactory4;
+ if (SLANG_SUCCEEDED(dxgiFactory->QueryInterface(IID_PPV_ARGS(dxgiFactory4.writeRef()))))
+ {
+ dxgiFactory4->EnumWarpAdapter(IID_PPV_ARGS(warpAdapter.writeRef()));
+ if (_isMatch(warpAdapter, lowerAdapterName.getUnownedSlice()))
+ {
+ outDxgiAdapters.Add(warpAdapter);
+ }
+ }
+ }
+
+ for (UINT adapterIndex = 0; true; adapterIndex++)
+ {
+ ComPtr<IDXGIAdapter> dxgiAdapter;
+ if (dxgiFactory->EnumAdapters(adapterIndex, dxgiAdapter.writeRef()) == DXGI_ERROR_NOT_FOUND)
+ break;
+
+ // Skip if warp (as we will have already added it)
+ if (dxgiAdapter == warpAdapter)
+ {
+ continue;
+ }
+ if (!_isMatch(dxgiAdapter, lowerAdapterName.getUnownedSlice()))
+ {
+ continue;
+ }
+
+ // Get if it's software
+ UINT deviceFlags = 0;
+ ComPtr<IDXGIAdapter1> dxgiAdapter1;
+ if (SLANG_SUCCEEDED(dxgiAdapter->QueryInterface(IID_PPV_ARGS(dxgiAdapter1.writeRef()))))
+ {
+ DXGI_ADAPTER_DESC1 desc;
+ dxgiAdapter1->GetDesc1(&desc);
+ deviceFlags = desc.Flags;
+ }
+
+ // If the right type then add it
+ if ((deviceFlags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 && (flags & DeviceCheckFlag::UseHardwareDevice) != 0)
+ {
+ outDxgiAdapters.Add(dxgiAdapter);
+ }
+ }
+
+ return SLANG_OK;
+}
+
} // renderer_test
diff --git a/tools/gfx/d3d-util.h b/tools/gfx/d3d-util.h
index 04bfae63d..0c05bed46 100644
--- a/tools/gfx/d3d-util.h
+++ b/tools/gfx/d3d-util.h
@@ -8,10 +8,13 @@
#include "../../slang-com-ptr.h"
#include "../../source/core/list.h"
+#include "flag-combiner.h"
+
#include "render.h"
#include <D3Dcommon.h>
#include <DXGIFormat.h>
+#include <dxgi.h>
namespace gfx {
@@ -56,6 +59,21 @@ class D3DUtil
/// Append text in in, into wide char array
static void appendWideChars(const char* in, Slang::List<wchar_t>& out);
+
+
+ static SlangResult createFactory(DeviceCheckFlags flags, Slang::ComPtr<IDXGIFactory>& outFactory);
+
+ /// Get the dxgiModule
+ static HMODULE getDxgiModule();
+
+ /// Find adapters
+ static SlangResult findAdapters(DeviceCheckFlags flags, const Slang::UnownedStringSlice& adapaterName, IDXGIFactory* dxgiFactory, Slang::List<Slang::ComPtr<IDXGIAdapter>>& dxgiAdapters);
+ /// Find adapters
+ static SlangResult findAdapters(DeviceCheckFlags flags, const Slang::UnownedStringSlice& adapaterName, Slang::List<Slang::ComPtr<IDXGIAdapter>>& dxgiAdapters);
+
+ /// True if the adapter is warp
+ static bool isWarp(IDXGIFactory* dxgiFactory, IDXGIAdapter* adapter);
+
};
} // renderer_test
diff --git a/tools/gfx/render-d3d11.cpp b/tools/gfx/render-d3d11.cpp
index 8b961c8f2..afb8c3e5f 100644
--- a/tools/gfx/render-d3d11.cpp
+++ b/tools/gfx/render-d3d11.cpp
@@ -472,12 +472,33 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
for (int i = 0; i < numCombinations; ++i)
{
const auto deviceCheckFlags = combiner.getCombination(i);
- const D3D_DRIVER_TYPE driverType = (deviceCheckFlags & DeviceCheckFlag::UseHardwareDevice) ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_REFERENCE;
+
+ // If we have an adapter set on the desc, look it up. We only need to do so for hardware
+ ComPtr<IDXGIAdapter> adapter;
+ if (desc.adapter.Length() && (deviceCheckFlags & DeviceCheckFlag::UseHardwareDevice))
+ {
+ List<ComPtr<IDXGIAdapter>> dxgiAdapters;
+ D3DUtil::findAdapters(deviceCheckFlags, desc.adapter.getUnownedSlice(), dxgiAdapters);
+ if (dxgiAdapters.Count() == 0)
+ {
+ continue;
+ }
+ adapter = dxgiAdapters[0];
+ }
+
+ // The adapter can be nullptr - that just means 'default', but when so we need to select the driver type
+ D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_UNKNOWN;
+ if (adapter == nullptr)
+ {
+ // If we don't have an adapter, select directly
+ driverType = (deviceCheckFlags & DeviceCheckFlag::UseHardwareDevice) ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_REFERENCE;
+ }
+
const int startFeatureIndex = (deviceCheckFlags & DeviceCheckFlag::UseFullFeatureLevel) ? 0 : 1;
const UINT deviceFlags = (deviceCheckFlags & DeviceCheckFlag::UseDebug) ? D3D11_CREATE_DEVICE_DEBUG : 0;
res = D3D11CreateDeviceAndSwapChain_(
- nullptr, // adapter (use default)
+ adapter,
driverType,
nullptr, // software
deviceFlags,
diff --git a/tools/gfx/render-d3d12.cpp b/tools/gfx/render-d3d12.cpp
index 3c5d19c1b..32eaf71e5 100644
--- a/tools/gfx/render-d3d12.cpp
+++ b/tools/gfx/render-d3d12.cpp
@@ -110,7 +110,7 @@ protected:
static const Int kMaxRTVCount = 8;
static const Int kMaxDescriptorSetCount = 16;
- struct AdapterInfo
+ struct DeviceInfo
{
void clear()
{
@@ -123,7 +123,7 @@ protected:
}
bool m_isWarp;
- ComPtr<IDXGIFactory4> m_dxgiFactory;
+ ComPtr<IDXGIFactory> m_dxgiFactory;
ComPtr<ID3D12Device> m_device;
ComPtr<IDXGIAdapter> m_adapter;
DXGI_ADAPTER_DESC m_desc;
@@ -500,7 +500,7 @@ protected:
// Result _calcBindParameters(BindParameters& params);
// RenderState* findRenderState(PipelineType pipelineType);
- Result _createAdaptor(DeviceCheckFlags deviceCheckFlags, D3D_FEATURE_LEVEL featureLevel, AdapterInfo& outAdapterInfo);
+ Result _createDevice(DeviceCheckFlags deviceCheckFlags, const UnownedStringSlice& nameMatch, D3D_FEATURE_LEVEL featureLevel, DeviceInfo& outDeviceInfo);
D3D12CircularResourceHeap m_circularResourceHeap;
@@ -542,7 +542,7 @@ protected:
ComPtr<ID3D12Debug> m_dxDebug;
- AdapterInfo m_adapterInfo;
+ DeviceInfo m_deviceInfo;
ID3D12Device* m_device = nullptr;
ComPtr<IDXGISwapChain3> m_swapChain;
@@ -587,10 +587,7 @@ protected:
int32_t m_targetUsageFlags = 0; ///< D3DUtil::UsageFlag combination for target
// Dll entry points
- typedef HRESULT(WINAPI *PFN_DXGI_CREATE_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void **ppFactory);
-
PFN_D3D12_GET_DEBUG_INTERFACE m_D3D12GetDebugInterface = nullptr;
- PFN_DXGI_CREATE_FACTORY_2 m_CreateDXGIFactory2 = nullptr;
PFN_D3D12_CREATE_DEVICE m_D3D12CreateDevice = nullptr;
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE m_D3D12SerializeRootSignature = nullptr;
@@ -1314,63 +1311,30 @@ Result D3D12Renderer::_bindRenderState(PipelineStateImpl* pipelineStateImpl, ID3
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-Result D3D12Renderer::_createAdaptor(DeviceCheckFlags deviceCheckFlags, D3D_FEATURE_LEVEL featureLevel, AdapterInfo& outAdapterInfo)
+Result D3D12Renderer::_createDevice(DeviceCheckFlags deviceCheckFlags, const UnownedStringSlice& nameMatch, D3D_FEATURE_LEVEL featureLevel, DeviceInfo& outDeviceInfo)
{
- outAdapterInfo.clear();
+ outDeviceInfo.clear();
- const UINT dxgiFactoryFlags = (deviceCheckFlags & DeviceCheckFlag::UseDebug) ? DXGI_CREATE_FACTORY_DEBUG : 0;
+ ComPtr<IDXGIFactory> dxgiFactory;
+ SLANG_RETURN_ON_FAIL(D3DUtil::createFactory(deviceCheckFlags, dxgiFactory));
- ComPtr<IDXGIFactory4> dxgiFactory;
+ List<ComPtr<IDXGIAdapter>> dxgiAdapters;
+ SLANG_RETURN_ON_FAIL(D3DUtil::findAdapters(deviceCheckFlags, nameMatch, dxgiFactory, dxgiAdapters));
- // Try and create DXGIFactory
- SLANG_RETURN_ON_FAIL(m_CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(dxgiFactory.writeRef())));
-
- // Search for an adapter that meets our requirements
- ComPtr<IDXGIAdapter> adapter;
ComPtr<ID3D12Device> device;
+ ComPtr<IDXGIAdapter> adapter;
- if ((deviceCheckFlags & DeviceCheckFlag::UseHardwareDevice) == 0)
- {
- // Look for software renderer (warp)
-
- SLANG_RETURN_ON_FAIL(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.writeRef())));
- SLANG_RETURN_ON_FAIL(m_D3D12CreateDevice(adapter, featureLevel, IID_PPV_ARGS(device.writeRef())));
-
- outAdapterInfo.m_isWarp = true;
- }
- else
+ for (int i = 0; i < int(dxgiAdapters.Count()); ++i)
{
- // Look for hardware
- UINT adapterCounter = 0;
- for (;;)
+ IDXGIAdapter* dxgiAdapter = dxgiAdapters[i];
+ if (SLANG_SUCCEEDED(m_D3D12CreateDevice(dxgiAdapter, featureLevel, IID_PPV_ARGS(device.writeRef()))))
{
- UINT adapterIndex = adapterCounter++;
-
- ComPtr<IDXGIAdapter1> candidateAdapter;
- if (dxgiFactory->EnumAdapters1(adapterIndex, candidateAdapter.writeRef()) == DXGI_ERROR_NOT_FOUND)
- break;
-
- DXGI_ADAPTER_DESC1 desc;
- candidateAdapter->GetDesc1(&desc);
-
- if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
- {
- // If it's software - then ignore it
- continue;
- }
-
- if (SUCCEEDED(m_D3D12CreateDevice(candidateAdapter, featureLevel, IID_PPV_ARGS(device.writeRef()))))
- {
- // We found one!
- adapter = candidateAdapter;
- break;
- }
+ adapter = dxgiAdapter;
+ break;
}
}
- // Didn't find an adapter
- if (!adapter)
+ if (!device)
{
return SLANG_FAIL;
}
@@ -1421,20 +1385,21 @@ Result D3D12Renderer::_createAdaptor(DeviceCheckFlags deviceCheckFlags, D3D_FEAT
// Get the descs
{
- adapter->GetDesc(&outAdapterInfo.m_desc);
+ adapter->GetDesc(&outDeviceInfo.m_desc);
// Look up GetDesc1 info
ComPtr<IDXGIAdapter1> adapter1;
if (SLANG_SUCCEEDED(adapter->QueryInterface(adapter1.writeRef())))
{
- adapter1->GetDesc1(&outAdapterInfo.m_desc1);
+ adapter1->GetDesc1(&outDeviceInfo.m_desc1);
}
}
// Save other info
- outAdapterInfo.m_device = device;
- outAdapterInfo.m_dxgiFactory = dxgiFactory;
- outAdapterInfo.m_adapter = adapter;
+ outDeviceInfo.m_device = device;
+ outDeviceInfo.m_dxgiFactory = dxgiFactory;
+ outDeviceInfo.m_adapter = adapter;
+ outDeviceInfo.m_isWarp = D3DUtil::isWarp(dxgiFactory, adapter);
return SLANG_OK;
}
@@ -1451,13 +1416,6 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
return SLANG_FAIL;
}
- HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
- if (!dxgiModule)
- {
- fprintf(stderr, "error: failed load 'dxgi.dll'\n");
- return SLANG_FAIL;
- }
-
// Get all the dll entry points
m_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)loadProc(d3dModule, "D3D12SerializeRootSignature");
if (!m_D3D12SerializeRootSignature)
@@ -1491,11 +1449,6 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
}
#endif
- m_CreateDXGIFactory2 = (PFN_DXGI_CREATE_FACTORY_2)loadProc(dxgiModule, "CreateDXGIFactory2");
- if (!m_CreateDXGIFactory2)
- {
- return SLANG_FAIL;
- }
m_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)loadProc(d3dModule, "D3D12CreateDevice");
if (!m_D3D12CreateDevice)
{
@@ -1518,20 +1471,20 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
const int numCombinations = combiner.getNumCombinations();
for (int i = 0; i < numCombinations; ++i)
{
- if (SLANG_SUCCEEDED(_createAdaptor(combiner.getCombination(i), featureLevel, m_adapterInfo)))
+ if (SLANG_SUCCEEDED(_createDevice(combiner.getCombination(i), desc.adapter.getUnownedSlice(), featureLevel, m_deviceInfo)))
{
break;
}
}
- if (!m_adapterInfo.m_adapter)
+ if (!m_deviceInfo.m_adapter)
{
// Couldn't find an adapter
return SLANG_FAIL;
}
// Set the device
- m_device = m_adapterInfo.m_device;
+ m_device = m_deviceInfo.m_device;
// Find what features are supported
{
@@ -1544,7 +1497,7 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
// TODO: Currently warp causes a crash when using half, so disable for now
if (SLANG_SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &featureShaderModel, sizeof(featureShaderModel))) &&
- m_adapterInfo.m_isWarp == false &&
+ m_deviceInfo.m_isWarp == false &&
featureShaderModel.HighestShaderModel >= 0x62)
{
// With sm_6_2 we have half
@@ -1615,7 +1568,7 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
// Swap chain needs the queue so that it can force a flush on it.
ComPtr<IDXGISwapChain> swapChain;
- SLANG_RETURN_ON_FAIL(m_adapterInfo.m_dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
if (!m_hasVsync)
@@ -1632,7 +1585,7 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
}
// This sample does not support fullscreen transitions.
- SLANG_RETURN_ON_FAIL(m_adapterInfo.m_dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
+ SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
diff --git a/tools/gfx/render-gl.cpp b/tools/gfx/render-gl.cpp
index a2d379778..a3703a75b 100644
--- a/tools/gfx/render-gl.cpp
+++ b/tools/gfx/render-gl.cpp
@@ -677,6 +677,19 @@ SlangResult GLRenderer::initialize(const Desc& desc, void* inWindowHandle)
wglMakeCurrent(m_hdc, m_glContext);
auto renderer = glGetString(GL_RENDERER);
+
+ if (renderer && desc.adapter.Length() > 0)
+ {
+ String lowerAdapter = desc.adapter.ToLower();
+ String lowerRenderer = String((const char*)renderer).ToLower();
+
+ // The adapter is not available
+ if (lowerRenderer.IndexOf(lowerAdapter) == UInt(-1))
+ {
+ return SLANG_E_NOT_AVAILABLE;
+ }
+ }
+
auto extensions = glGetString(GL_EXTENSIONS);
// Load each of our extension functions by name
diff --git a/tools/gfx/render-vk.cpp b/tools/gfx/render-vk.cpp
index defc08355..30eff04c9 100644
--- a/tools/gfx/render-vk.cpp
+++ b/tools/gfx/render-vk.cpp
@@ -948,8 +948,35 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
physicalDevices.SetSize(numPhysicalDevices);
SLANG_VK_RETURN_ON_FAIL(m_api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, physicalDevices.Buffer()));
- // TODO: allow override of selected device
- uint32_t selectedDeviceIndex = 0;
+ int32_t selectedDeviceIndex = 0;
+
+ if (desc.adapter.Length())
+ {
+ selectedDeviceIndex = -1;
+
+ String lowerAdapter = desc.adapter.ToLower();
+
+ for (int i = 0; i < int(physicalDevices.Count()); ++i)
+ {
+ auto physicalDevice = physicalDevices[i];
+
+ VkPhysicalDeviceProperties basicProps = {};
+ m_api.vkGetPhysicalDeviceProperties(physicalDevice, &basicProps);
+
+ String lowerName = String(basicProps.deviceName).ToLower();
+
+ if (lowerName.IndexOf(lowerAdapter) != UInt(-1))
+ {
+ selectedDeviceIndex = i;
+ break;
+ }
+ }
+ if (selectedDeviceIndex < 0)
+ {
+ // Device not found
+ return SLANG_FAIL;
+ }
+ }
SLANG_RETURN_ON_FAIL(m_api.initPhysicalDevice(physicalDevices[selectedDeviceIndex]));
@@ -2704,7 +2731,7 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
VkPipeline pipeline = VK_NULL_HANDLE;
SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline));
- RefPtr<PipelineStateImpl> pipelineStateImpl;
+ RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(m_api);
pipelineStateImpl->m_pipeline = pipeline;
pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
pipelineStateImpl->m_shaderProgram = programImpl;
diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp
index 38af85f79..e618c8f8c 100644
--- a/tools/gfx/render.cpp
+++ b/tools/gfx/render.cpp
@@ -389,4 +389,17 @@ ProjectionStyle RendererUtil::getProjectionStyle(RendererType type)
}
}
+/* static */UnownedStringSlice RendererUtil::toText(RendererType type)
+{
+ switch (type)
+ {
+ case RendererType::DirectX11: return UnownedStringSlice::fromLiteral("DirectX11");
+ case RendererType::DirectX12: return UnownedStringSlice::fromLiteral("DirectX11");
+ case RendererType::OpenGl: return UnownedStringSlice::fromLiteral("OpenGL");
+ case RendererType::Vulkan: return UnownedStringSlice::fromLiteral("Vulkan");
+ case RendererType::Unknown: return UnownedStringSlice::fromLiteral("Unknown");
+ default: return UnownedStringSlice::fromLiteral("?!?");
+ }
+}
+
} // renderer_test
diff --git a/tools/gfx/render.h b/tools/gfx/render.h
index 775e71613..eebeaa170 100644
--- a/tools/gfx/render.h
+++ b/tools/gfx/render.h
@@ -779,8 +779,9 @@ public:
struct Desc
{
- int width; ///< Width in pixels
- int height; ///< height in pixels
+ int width; ///< Width in pixels
+ int height; ///< height in pixels
+ Slang::String adapter; ///< Name to identify the adapter to use
};
virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) = 0;
@@ -978,6 +979,9 @@ struct RendererUtil
/// Get the binding style from the type
static BindingStyle getBindingStyle(RendererType type) { return s_rendererTypeToBindingStyle[int(type)]; }
+ /// Get as text
+ static Slang::UnownedStringSlice toText(RendererType type);
+
private:
static void compileTimeAsserts();
static const uint8_t s_formatSize[]; // Maps Format::XXX to a size in bytes;
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 1171a2a03..9d5ff35c8 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -151,6 +151,16 @@ SlangResult parseOptions(int argc, const char*const* argv, Slang::WriterHelper s
{
gOptions.useDXIL = true;
}
+ else if (strcmp(arg, "-adapter") == 0)
+ {
+ if (argCursor == argEnd)
+ {
+ stdError.print("expected argument for '%s' option\n", arg);
+ return SLANG_FAIL;
+ }
+
+ gOptions.adapter = *argCursor++;
+ }
else
{
// Lookup
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index 7b55b9ac0..104906f42 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -57,6 +57,8 @@ struct Options
bool useDXIL = false;
Slang::List<Slang::String> renderFeatures; /// Required render features for this test to run
+
+ Slang::String adapter; ///< The adapter to use either name or index
};
extern Options gOptions;
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index ee408f283..2bc6cd8f8 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -555,21 +555,30 @@ SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSe
return SLANG_FAIL;
}
+ StringBuilder rendererName;
+ rendererName << "[" << RendererUtil::toText(gOptions.rendererType) << "] ";
+ if (gOptions.adapter.Length())
+ {
+ rendererName << "'" << gOptions.adapter << "'";
+ }
+
+
if (!renderer)
{
- fprintf(stderr, "Unable to create renderer\n");
+ fprintf(stderr, "Unable to create renderer %s\n", rendererName.Buffer());
return SLANG_FAIL;
}
Renderer::Desc desc;
desc.width = gWindowWidth;
desc.height = gWindowHeight;
+ desc.adapter = gOptions.adapter;
{
SlangResult res = renderer->initialize(desc, (HWND)window->getHandle());
if (SLANG_FAILED(res))
{
- fprintf(stderr, "Unable to initialize renderer\n");
+ fprintf(stderr, "Unable to initialize renderer %s\n", rendererName.Buffer());
return res;
}
}
diff --git a/tools/slang-test/options.cpp b/tools/slang-test/options.cpp
index 70b7a4533..2b9ec6c06 100644
--- a/tools/slang-test/options.cpp
+++ b/tools/slang-test/options.cpp
@@ -170,6 +170,15 @@ static bool _isSubCommand(const char* arg)
argCursor++;
// Assumed to be handle by .bat file that called us
}
+ else if (strcmp(arg, "-adapter") == 0)
+ {
+ if (argCursor == argEnd)
+ {
+ stdError.print("error: expected operand for '%s'\n", arg);
+ return SLANG_FAIL;
+ }
+ optionsOut->adapter = *argCursor++;
+ }
else if (strcmp(arg, "-appveyor") == 0)
{
optionsOut->outputMode = TestOutputMode::AppVeyor;
diff --git a/tools/slang-test/options.h b/tools/slang-test/options.h
index 58b8e0fb2..72dc66035 100644
--- a/tools/slang-test/options.h
+++ b/tools/slang-test/options.h
@@ -86,6 +86,9 @@ struct Options
// OpenGL is disabled for now
Slang::RenderApiFlags synthesizedTestApis = Slang::RenderApiFlag::AllOf & ~(Slang::RenderApiFlag::Vulkan | Slang::RenderApiFlag::OpenGl);
+ // The adapter to use. If empty will match first found adapter.
+ Slang::String adapter;
+
/// Parse the args, report any errors into stdError, and write the results into optionsOut
static SlangResult parse(int argc, char** argv, TestCategorySet* categorySet, Slang::WriterHelper stdError, Options* optionsOut);
};
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp
index 0b4b83198..9119c3224 100644
--- a/tools/slang-test/slang-test-main.cpp
+++ b/tools/slang-test/slang-test-main.cpp
@@ -452,6 +452,8 @@ ToolReturnCode getReturnCode(OSProcessSpawner& spawner)
ToolReturnCode spawnAndWait(TestContext* context, const String& testPath, SpawnType spawnType, OSProcessSpawner& spawner)
{
+ const auto& options = context->options;
+
OSError spawnResult = kOSError_OperationFailed;
switch (spawnType)
{
@@ -1079,6 +1081,14 @@ TestResult runGLSLComparisonTest(TestContext* context, TestInput& input)
return TestResult::Pass;
}
+static void _addRenderTestOptions(const Options& options, OSProcessSpawner& spawner)
+{
+ if (options.adapter.Length())
+ {
+ spawner.pushArgument("-adapter");
+ spawner.pushArgument(options.adapter);
+ }
+}
TestResult runComputeComparisonImpl(TestContext* context, TestInput& input, const char *const* langOpts, size_t numLangOpts)
{
@@ -1097,6 +1107,8 @@ TestResult runComputeComparisonImpl(TestContext* context, TestInput& input, cons
spawner.pushExecutablePath(String(context->options.binDir) + "render-test" + osGetExecutableSuffix());
spawner.pushArgument(filePath999);
+ _addRenderTestOptions(context->options, spawner);
+
for (auto arg : input.testOptions->args)
{
spawner.pushArgument(arg);
@@ -1199,6 +1211,8 @@ TestResult doRenderComparisonTestRun(TestContext* context, TestInput& input, cha
spawner.pushExecutablePath(String(context->options.binDir) + "render-test" + osGetExecutableSuffix());
spawner.pushArgument(filePath);
+ _addRenderTestOptions(context->options, spawner);
+
for( auto arg : input.testOptions->args )
{
spawner.pushArgument(arg);
@@ -1405,7 +1419,15 @@ TestResult runHLSLRenderComparisonTestImpl(
String actualOutput;
TestResult hlslResult = doRenderComparisonTestRun(context, input, expectedArg, ".expected", &expectedOutput);
+ if (hlslResult != TestResult::Pass)
+ {
+ return hlslResult;
+ }
TestResult slangResult = doRenderComparisonTestRun(context, input, actualArg, ".actual", &actualOutput);
+ if (slangResult != TestResult::Pass)
+ {
+ return slangResult;
+ }
Slang::File::WriteAllText(outputStem + ".expected", expectedOutput);
Slang::File::WriteAllText(outputStem + ".actual", actualOutput);