Merge pull request #10922 from hrydgard/gpu-device-choice

GPU device choice for D3D11 and Vulkan
This commit is contained in:
Unknown W. Brackets 2018-06-06 08:50:32 -04:00 committed by GitHub
commit 07e178a2da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 188 additions and 60 deletions

View File

@ -213,6 +213,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
assert(gpu_count > 0);
physical_devices_.resize(gpu_count);
physicalDeviceProperties_.resize(gpu_count);
res = vkEnumeratePhysicalDevices(instance_, &gpu_count, physical_devices_.data());
if (res != VK_SUCCESS) {
init_error_ = "Failed to enumerate physical devices";
@ -221,6 +222,9 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
return res;
}
for (uint32_t i = 0; i < gpu_count; i++) {
vkGetPhysicalDeviceProperties(physical_devices_[i], &physicalDeviceProperties_[i]);
}
return VK_SUCCESS;
}
@ -417,6 +421,14 @@ bool VulkanContext::CheckLayers(const std::vector<LayerProperties> &layer_props,
return true;
}
int VulkanContext::GetPhysicalDeviceByName(std::string name) {
for (size_t i = 0; i < physical_devices_.size(); i++) {
if (physicalDeviceProperties_[i].deviceName == name)
return (int)i;
}
return -1;
}
int VulkanContext::GetBestPhysicalDevice() {
// Rules: Prefer discrete over embedded.
// Prefer nVidia over Intel.
@ -490,7 +502,6 @@ void VulkanContext::ChooseDevice(int physical_device) {
// This is as good a place as any to do this
vkGetPhysicalDeviceMemoryProperties(physical_devices_[physical_device_], &memory_properties);
vkGetPhysicalDeviceProperties(physical_devices_[physical_device_], &gpu_props);
// Optional features
vkGetPhysicalDeviceFeatures(physical_devices_[physical_device_], &featuresAvailable_);

View File

@ -128,6 +128,7 @@ public:
void DestroyInstance();
int GetBestPhysicalDevice();
int GetPhysicalDeviceByName(std::string name);
void ChooseDevice(int physical_device);
bool EnableDeviceExtension(const char *extension);
VkResult CreateDevice();
@ -173,6 +174,12 @@ public:
VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
return physical_devices_[n];
}
int GetCurrentPhysicalDevice() const {
return physical_device_;
}
int GetNumPhysicalDevices() const {
return (int)physical_devices_.size();
}
VkQueue GetGraphicsQueue() const {
return gfx_queue_;
@ -182,8 +189,8 @@ public:
return graphics_queue_family_index_;
}
const VkPhysicalDeviceProperties &GetPhysicalDeviceProperties() {
return gpu_props;
const VkPhysicalDeviceProperties &GetPhysicalDeviceProperties(int i) const {
return physicalDeviceProperties_[i];
}
VkResult GetInstanceLayerExtensionList(const char *layerName, std::vector<VkExtensionProperties> &extensions);
@ -281,7 +288,7 @@ private:
int physical_device_ = -1;
uint32_t graphics_queue_family_index_ = -1;
VkPhysicalDeviceProperties gpu_props{};
std::vector<VkPhysicalDeviceProperties> physicalDeviceProperties_{};
std::vector<VkQueueFamilyProperties> queue_props;
VkPhysicalDeviceMemoryProperties memory_properties{};

View File

@ -507,6 +507,10 @@ static ConfigSetting graphicsSettings[] = {
ConfigSetting("CardboardYShift", &g_Config.iCardboardXShift, 0, true, true),
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend),
ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false),
#ifdef _WIN32
ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false),
#endif
ReportedConfigSetting("RenderingMode", &g_Config.iRenderingMode, &DefaultRenderingMode, true, true),
ConfigSetting("SoftwareRenderer", &g_Config.bSoftwareRendering, false, true, true),
ReportedConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, true, true),

View File

@ -153,6 +153,12 @@ public:
// GFX
int iGPUBackend;
// We have separate device parameters for each backend so it doesn't get erased if you switch backends.
// If not set, will use the "best" device.
std::string sVulkanDevice;
#ifdef _WIN32
std::string sD3D11Device;
#endif
bool bSoftwareRendering;
bool bHardwareTransform; // only used in the GLES backend
bool bSoftwareSkinning; // may speed up some games

View File

@ -1007,7 +1007,7 @@ void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&po
float color[4];
};
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minStorageBufferOffsetAlignment;
uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), &offset_, &buf_, ssboAlignment);
range_ = size * sizeof(TessData);

View File

@ -175,7 +175,7 @@ GPU_Vulkan::~GPU_Vulkan() {
void GPU_Vulkan::CheckGPUFeatures() {
uint32_t features = 0;
switch (vulkan_->GetPhysicalDeviceProperties().vendorID) {
switch (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
case VULKAN_VENDOR_AMD:
// Accurate depth is required on AMD (due to reverse-Z driver bug) so we ignore the compat flag to disable it on those. See #9545
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
@ -183,7 +183,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
case VULKAN_VENDOR_ARM:
// Also required on older ARM Mali drivers, like the one on many Galaxy S7.
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth ||
vulkan_->GetPhysicalDeviceProperties().driverVersion <= VK_MAKE_VERSION(428, 811, 2674)) {
vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion <= VK_MAKE_VERSION(428, 811, 2674)) {
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
}
break;
@ -212,7 +212,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_DEPTH_CLAMP;
}
if (vulkan_->GetFeaturesEnabled().dualSrcBlend) {
switch (vulkan_->GetPhysicalDeviceProperties().vendorID) {
switch (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
// We thought we had a bug here on nVidia but turns out we accidentally #ifdef-ed out crucial
// code on Android.
case VULKAN_VENDOR_INTEL:
@ -220,7 +220,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
break;
case VULKAN_VENDOR_AMD:
// See issue #10074, and also #10065 (AMD) and #10109 for the choice of the driver version to check for
if (vulkan_->GetPhysicalDeviceProperties().driverVersion >= 0x00407000)
if (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion >= 0x00407000)
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
break;
default:
@ -310,7 +310,7 @@ void GPU_Vulkan::EndHostFrame() {
// Needs to be called on GPU thread, not reporting thread.
void GPU_Vulkan::BuildReportingInfo() {
const auto &props = vulkan_->GetPhysicalDeviceProperties();
const auto &props = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice());
const auto &features = vulkan_->GetFeaturesAvailable();
#define CHECK_BOOL_FEATURE(n) do { if (features.n) { featureNames += ", " #n; } } while (false)

View File

@ -676,7 +676,7 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha
WARN_LOG(G3D, "Bad Vulkan pipeline cache header - ignoring");
return false;
}
if (0 != memcmp(header->uuid, vulkan_->GetPhysicalDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE)) {
if (0 != memcmp(header->uuid, vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).pipelineCacheUUID, VK_UUID_SIZE)) {
// Wrong hardware/driver/etc.
WARN_LOG(G3D, "Bad Vulkan pipeline cache UUID - ignoring");
return false;

View File

@ -159,7 +159,7 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons
ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan)
: vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) {
codeBuffer_ = new char[16384];
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment;
memset(&ub_base, 0, sizeof(ub_base));
memset(&ub_lights, 0, sizeof(ub_lights));
memset(&ub_bones, 0, sizeof(ub_bones));
@ -176,7 +176,7 @@ ShaderManagerVulkan::~ShaderManagerVulkan() {
void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment;
}
void ShaderManagerVulkan::Clear() {

View File

@ -683,7 +683,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
uint32_t bufferOffset;
VkBuffer texBuf;
// nvidia returns 1 but that can't be healthy... let's align by 16 as a minimum.
int pushAlignment = std::max(16, (int)vulkan_->GetPhysicalDeviceProperties().limits.optimalBufferCopyOffsetAlignment);
int pushAlignment = std::max(16, (int)vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.optimalBufferCopyOffsetAlignment);
void *data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
if (replaced.Valid()) {
replaced.Load(i, data, stride);

View File

@ -202,6 +202,24 @@ void GameSettingsScreen::CreateViews() {
renderingBackendChoice->HideChoice(3);
}
#endif
Draw::DrawContext *draw = screenManager()->getDrawContext();
// Backends that don't allow a device choice will only expose one device.
if (draw->GetDeviceList().size() > 1) {
std::string *deviceNameSetting = nullptr;
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
deviceNameSetting = &g_Config.sVulkanDevice;
}
#ifdef _WIN32
if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D11) {
deviceNameSetting = &g_Config.sD3D11Device;
}
#endif
if (deviceNameSetting) {
PopupMultiChoiceDynamic *deviceChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(deviceNameSetting, gr->T("Device"), draw->GetDeviceList(), nullptr, screenManager()));
deviceChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend);
}
}
static const char *renderingMode[] = { "Non-Buffered Rendering", "Buffered Rendering"};
PopupMultiChoice *renderingModeChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iRenderingMode, gr->T("Mode"), renderingMode, 0, ARRAY_SIZE(renderingMode), gr->GetName(), screenManager()));

View File

@ -2,6 +2,7 @@
#include "Common/CommonWindows.h"
#include <d3d11.h>
#include <WinError.h>
#include <cassert>
#include "base/logging.h"
@ -22,6 +23,12 @@
#define __uuidof(type) IID_##type
#endif
#ifndef DXGI_ERROR_NOT_FOUND
#define _FACDXGI 0x87a
#define MAKE_DXGI_HRESULT(code) MAKE_HRESULT(1, _FACDXGI, code)
#define DXGI_ERROR_NOT_FOUND MAKE_DXGI_HRESULT(2)
#endif
#if PPSSPP_PLATFORM(UWP)
#error This file should not be compiled for UWP.
#endif
@ -41,7 +48,7 @@ void D3D11Context::SwapInterval(int interval) {
// Dummy
}
HRESULT D3D11Context::CreateTheDevice() {
HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) {
bool windowed = true;
#ifdef _DEBUG
UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
@ -70,19 +77,13 @@ HRESULT D3D11Context::CreateTheDevice() {
const UINT numFeatureLevels = ARRAYSIZE(featureLevels);
HRESULT hr = S_OK;
// Temporarily commenting out until we can dynamically load D3D11CreateDevice.
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {
driverType_ = driverTypes[driverTypeIndex];
hr = ptr_D3D11CreateDevice(nullptr, driverType_, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)featureLevels, numFeatureLevels,
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_UNKNOWN;
hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &device_, &featureLevel_, &context_);
if (hr == E_INVALIDARG) {
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
hr = ptr_D3D11CreateDevice(adapter, driverType, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)&featureLevels[3], numFeatureLevels - 3,
D3D11_SDK_VERSION, &device_, &featureLevel_, &context_);
if (hr == E_INVALIDARG) {
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
hr = ptr_D3D11CreateDevice(nullptr, driverType_, nullptr, createDeviceFlags, (D3D_FEATURE_LEVEL *)&featureLevels[3], numFeatureLevels - 3,
D3D11_SDK_VERSION, &device_, &featureLevel_, &context_);
}
if (SUCCEEDED(hr))
break;
}
return hr;
}
@ -99,8 +100,30 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
LoadD3D11Error result = LoadD3D11();
HRESULT hr = E_FAIL;
std::vector<std::string> adapterNames;
if (result == LoadD3D11Error::SUCCESS) {
hr = CreateTheDevice();
std::vector<IDXGIAdapter *> adapters;
int chosenAdapter = 0;
IDXGIFactory * pFactory = nullptr;
ptr_CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);
IDXGIAdapter *pAdapter;
for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) {
adapters.push_back(pAdapter);
DXGI_ADAPTER_DESC desc;
pAdapter->GetDesc(&desc);
std::string str = ConvertWStringToUTF8(desc.Description);
adapterNames.push_back(str);
if (str == g_Config.sD3D11Device) {
chosenAdapter = i;
}
}
hr = CreateTheDevice(adapters[chosenAdapter]);
for (int i = 0; i < (int)adapters.size(); i++) {
adapters[i]->Release();
}
}
if (FAILED(hr)) {
@ -146,7 +169,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
}
#endif
draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_);
draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames);
SetGPUBackend(GPUBackend::DIRECT3D11);
bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think.
assert(success);

View File

@ -40,7 +40,7 @@ public:
Draw::DrawContext *GetDrawContext() override { return draw_; }
private:
HRESULT CreateTheDevice();
HRESULT CreateTheDevice(IDXGIAdapter *adapter);
void LostBackbuffer();
void GotBackbuffer();
@ -60,7 +60,6 @@ private:
ID3D11InfoQueue *d3dInfoQueue_ = nullptr;
#endif
D3D_DRIVER_TYPE driverType_;
D3D_FEATURE_LEVEL featureLevel_ = D3D_FEATURE_LEVEL_11_0;
int adapterId;
HDC hDC; // Private GDI Device Context

View File

@ -109,7 +109,12 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
g_Vulkan = nullptr;
return false;
}
g_Vulkan->ChooseDevice(g_Vulkan->GetBestPhysicalDevice());
int deviceNum = g_Vulkan->GetPhysicalDeviceByName(g_Config.sVulkanDevice);
if (deviceNum < 0) {
deviceNum = g_Vulkan->GetBestPhysicalDevice();
g_Config.sVulkanDevice = g_Vulkan->GetPhysicalDeviceProperties(deviceNum).deviceName;
}
g_Vulkan->ChooseDevice(deviceNum);
if (g_Vulkan->EnableDeviceExtension(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME)) {
supportsDedicatedAlloc_ = true;
}

View File

@ -850,7 +850,7 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
// See pull request #10723.
bool maliBugWorkaround = step.render.numDraws == 0 &&
step.render.color == VKRRenderPassAction::CLEAR &&
vulkan_->GetPhysicalDeviceProperties().driverVersion == 0xaa9c4b29;
vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion == 0xaa9c4b29;
if (maliBugWorkaround) {
TransitionImageLayout2(cmd, step.render.framebuffer->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
fb->color.layout, VK_IMAGE_LAYOUT_GENERAL,

View File

@ -136,7 +136,7 @@ VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan
queueRunner_.CreateDeviceObjects();
// Temporary AMD hack for issue #10097
if (vulkan_->GetPhysicalDeviceProperties().vendorID == VULKAN_VENDOR_AMD) {
if (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID == VULKAN_VENDOR_AMD) {
useThread_ = false;
}
}

View File

@ -491,6 +491,7 @@ struct DeviceCaps {
bool framebufferBlitSupported;
bool framebufferDepthCopySupported;
bool framebufferDepthBlitSupported;
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};
struct TextureDesc {
@ -532,6 +533,7 @@ public:
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
virtual std::vector<std::string> GetFeatureList() const { return std::vector<std::string>(); }
virtual std::vector<std::string> GetExtensionList() const { return std::vector<std::string>(); }
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
virtual uint32_t GetSupportedShaderLanguages() const = 0;

View File

@ -1,5 +1,7 @@
#pragma once
#include <string>
#include <vector>
#include "thin3d/thin3d.h"
// Separated this stuff into its own file so we don't get Windows.h included if all we want is the thin3d declarations.
@ -30,9 +32,9 @@ DrawContext *T3DCreateGLContext();
#ifdef _WIN32
DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx);
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> adapterNames);
#endif
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split);
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool splitSubmit);
} // namespace Draw

View File

@ -38,12 +38,15 @@ class D3D11RasterState;
class D3D11DrawContext : public DrawContext {
public:
D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> deviceList);
~D3D11DrawContext();
const DeviceCaps &GetDeviceCaps() const override {
return caps_;
}
std::vector<std::string> GetDeviceList() const override {
return deviceList_;
}
uint32_t GetSupportedShaderLanguages() const override {
return (uint32_t)ShaderLanguage::HLSL_D3D11 | (uint32_t)ShaderLanguage::HLSL_D3D11_BYTECODE;
}
@ -210,15 +213,17 @@ private:
// System info
D3D_FEATURE_LEVEL featureLevel_;
std::string adapterDesc_;
std::vector<std::string> deviceList_;
};
D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd)
D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> deviceList)
: device_(device),
context_(deviceContext1),
device1_(device1),
context1_(deviceContext1),
featureLevel_(featureLevel),
hWnd_(hWnd) {
hWnd_(hWnd),
deviceList_(deviceList) {
// Seems like a fair approximation...
caps_.dualSourceBlend = featureLevel_ >= D3D_FEATURE_LEVEL_10_0;
@ -229,7 +234,6 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
caps_.framebufferDepthBlitSupported = false;
caps_.framebufferDepthCopySupported = true;
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
if (SUCCEEDED(result)) {
@ -239,8 +243,6 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
// caps_.logicOpSupported = true;
}
}
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
IDXGIFactory1* dxgiFactory = nullptr;
IDXGIDevice* dxgiDevice = nullptr;
IDXGIAdapter* adapter = nullptr;
HRESULT hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
@ -1552,8 +1554,8 @@ void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h
}
}
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd) {
return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd);
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> adapterNames) {
return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd, adapterNames);
}
} // namespace Draw

View File

@ -261,7 +261,7 @@ public:
// Returns the binding offset, and the VkBuffer to bind.
size_t PushUBO(VulkanPushBuffer *buf, VulkanContext *vulkan, VkBuffer *vkbuf) {
return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment, vkbuf);
return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment, vkbuf);
}
int GetUniformLoc(const char *name);
@ -350,6 +350,13 @@ public:
const DeviceCaps &GetDeviceCaps() const override {
return caps_;
}
std::vector<std::string> GetDeviceList() const override {
std::vector<std::string> list;
for (int i = 0; i < vulkan_->GetNumPhysicalDevices(); i++) {
list.push_back(vulkan_->GetPhysicalDeviceProperties(i).deviceName);
}
return list;
}
uint32_t GetSupportedShaderLanguages() const override {
return (uint32_t)ShaderLanguage::GLSL_VULKAN | (uint32_t)ShaderLanguage::SPIRV_VULKAN;
}
@ -446,13 +453,13 @@ public:
// TODO: Make these actually query the right information
switch (info) {
case APINAME: return "Vulkan";
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties().deviceName;
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties().vendorID);
case DRIVER: return FormatDriverVersion(vulkan_->GetPhysicalDeviceProperties());
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).deviceName;
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID);
case DRIVER: return FormatDriverVersion(vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()));
case SHADELANGVERSION: return "N/A";;
case APIVERSION:
{
uint32_t ver = vulkan_->GetPhysicalDeviceProperties().apiVersion;
uint32_t ver = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).apiVersion;
return StringFromFormat("%d.%d.%d", ver >> 22, (ver >> 12) & 0x3ff, ver & 0xfff);
}
default: return "?";
@ -746,7 +753,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case.
caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan.
switch (vulkan->GetPhysicalDeviceProperties().vendorID) {
switch (vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;

View File

@ -444,6 +444,8 @@ void PopupMultiChoice::Update() {
}
void PopupMultiChoice::UpdateText() {
if (!choices_)
return;
I18NCategory *category = GetI18NCategory(category_);
// Clamp the value to be safe.
if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) {
@ -466,6 +468,7 @@ void PopupMultiChoice::ChoiceCallback(int num) {
if (restoreFocus_) {
SetFocusedView(this);
}
PostChoiceCallback(num);
}
}

View File

@ -237,11 +237,13 @@ private:
class PopupMultiChoice : public UI::Choice {
public:
PopupMultiChoice(int *value, const std::string &text, const char **choices, int minVal, int numChoices,
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = 0)
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr)
: UI::Choice(text, "", false, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices),
category_(category), screenManager_(screenManager) {
if (*value >= numChoices+minVal) *value = numChoices+minVal-1;
if (*value < minVal) *value = minVal;
if (*value >= numChoices + minVal)
*value = numChoices + minVal - 1;
if (*value < minVal)
*value = minVal;
OnClick.Handle(this, &PopupMultiChoice::HandleClick);
UpdateText();
}
@ -255,16 +257,19 @@ public:
UI::Event OnChoice;
private:
void UpdateText();
UI::EventReturn HandleClick(UI::EventParams &e);
void ChoiceCallback(int num);
protected:
int *value_;
const char **choices_;
int minVal_;
int numChoices_;
void UpdateText();
private:
UI::EventReturn HandleClick(UI::EventParams &e);
void ChoiceCallback(int num);
virtual void PostChoiceCallback(int num) {}
const char *category_;
ScreenManager *screenManager_;
std::string valueText_;
@ -272,6 +277,40 @@ private:
std::set<int> hidden_;
};
// Allows passing in a dynamic vector of strings. Saves the string.
class PopupMultiChoiceDynamic : public PopupMultiChoice {
public:
PopupMultiChoiceDynamic(std::string *value, const std::string &text, std::vector<std::string> choices,
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr)
: UI::PopupMultiChoice(&valueInt_, text, nullptr, 0, (int)choices.size(), category, screenManager, layoutParams),
valueStr_(value) {
choices_ = new const char *[numChoices_];
valueInt_ = 0;
for (int i = 0; i < numChoices_; i++) {
choices_[i] = new char[choices[i].size() + 1];
memcpy((char *)choices_[i], choices[i].c_str(), choices[i].size() + 1);
if (*value == choices_[i])
valueInt_ = i;
}
value_ = &valueInt_;
UpdateText();
}
~PopupMultiChoiceDynamic() {
for (int i = 0; i < numChoices_; i++) {
delete[] choices_[i];
}
delete[] choices_;
}
protected:
void PostChoiceCallback(int num) {
*valueStr_ = choices_[num];
}
private:
int valueInt_;
std::string *valueStr_;
};
class PopupSliderChoice : public Choice {
public: