diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-03-25 11:48:10 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-03-25 11:48:10 -0400 |
| commit | 2f4029a753f72833c30c4e6bad28c06b20540384 (patch) | |
| tree | ca771b5e00c6126351079b2df920d014e4ed6a1e | |
| parent | 5bdc3ef07373be62363deb64dedd4163589430b6 (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.cpp | 147 | ||||
| -rw-r--r-- | tools/gfx/d3d-util.h | 18 | ||||
| -rw-r--r-- | tools/gfx/render-d3d11.cpp | 25 | ||||
| -rw-r--r-- | tools/gfx/render-d3d12.cpp | 105 | ||||
| -rw-r--r-- | tools/gfx/render-gl.cpp | 13 | ||||
| -rw-r--r-- | tools/gfx/render-vk.cpp | 33 | ||||
| -rw-r--r-- | tools/gfx/render.cpp | 13 | ||||
| -rw-r--r-- | tools/gfx/render.h | 8 | ||||
| -rw-r--r-- | tools/render-test/options.cpp | 10 | ||||
| -rw-r--r-- | tools/render-test/options.h | 2 | ||||
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 13 | ||||
| -rw-r--r-- | tools/slang-test/options.cpp | 9 | ||||
| -rw-r--r-- | tools/slang-test/options.h | 3 | ||||
| -rw-r--r-- | tools/slang-test/slang-test-main.cpp | 22 |
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); |
