mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-27 18:30:56 +00:00
Merge pull request #10922 from hrydgard/gpu-device-choice
GPU device choice for D3D11 and Vulkan
This commit is contained in:
commit
07e178a2da
@ -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_);
|
||||
|
@ -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{};
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user