Allow D3D9 context creation to bail if shader compilation fails (D3D9 runtime not installed).
Fixes an issue where after switching to D3D9 on a PC without the D3D9 runtime, it's impossible to start PPSSPP anymore.
This commit is contained in:
parent
a6cf2e6ca0
commit
017d3da067
16 changed files with 45 additions and 18 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "PPSSPP_UWPMain.h"
|
#include "PPSSPP_UWPMain.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
@ -323,6 +324,7 @@ void PPSSPP_UWPMain::LoadStorageFile(StorageFile ^file) {
|
||||||
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
|
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
|
||||||
draw_ = Draw::T3DCreateD3D11Context(
|
draw_ = Draw::T3DCreateD3D11Context(
|
||||||
resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetDeviceFeatureLevel(), 0);
|
resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetDeviceFeatureLevel(), 0);
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UWPGraphicsContext::Shutdown() {
|
void UWPGraphicsContext::Shutdown() {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Common/CommonWindows.h"
|
#include "Common/CommonWindows.h"
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "util/text/utf8.h"
|
#include "util/text/utf8.h"
|
||||||
|
@ -139,6 +140,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_);
|
draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_);
|
||||||
|
assert(draw_->CreatePresets()); // If we can run D3D11, there's a compiler installed. I think.
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
|
@ -165,6 +165,13 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
|
||||||
//deviceEx->SetMaximumFrameLatency(1);
|
//deviceEx->SetMaximumFrameLatency(1);
|
||||||
}
|
}
|
||||||
draw_ = Draw::T3DCreateDX9Context(d3d_, d3dEx_, adapterId_, device_, deviceEx_);
|
draw_ = Draw::T3DCreateDX9Context(d3d_, d3dEx_, adapterId_, device_, deviceEx_);
|
||||||
|
if (!draw_->CreatePresets()) {
|
||||||
|
// Shader compiler not installed? Return an error so we can fall back to GL.
|
||||||
|
device_->Release();
|
||||||
|
d3d_->Release();
|
||||||
|
*error_message = "DirectX9 runtime not correctly installed. Please install.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (draw_)
|
if (draw_)
|
||||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr);
|
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
// Official git repository and contact information can be found at
|
// Official git repository and contact information can be found at
|
||||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||||
|
|
||||||
// TODO: What a mess this is :(
|
#include <cassert>
|
||||||
|
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "Common/CommonWindows.h"
|
#include "Common/CommonWindows.h"
|
||||||
#include "gfx/gl_common.h"
|
#include "gfx/gl_common.h"
|
||||||
|
@ -358,6 +357,7 @@ bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_mes
|
||||||
|
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets()); // if we get this far, there will always be a GLSL compiler capable of compiling these.
|
||||||
CHECK_GL_ERROR_IF_DEBUG();
|
CHECK_GL_ERROR_IF_DEBUG();
|
||||||
return true; // Success
|
return true; // Success
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,7 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
||||||
|
assert(draw_->CreatePresets()); // Doesn't fail, we include the compiler.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,7 @@ bool AndroidEGLGraphicsContext::Init(ANativeWindow *wnd, int backbufferWidth, in
|
||||||
gl->MakeCurrent();
|
gl->MakeCurrent();
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets()); // There will always be a GLSL compiler capable of compiling these.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +158,7 @@ public:
|
||||||
AndroidJavaEGLGraphicsContext() {
|
AndroidJavaEGLGraphicsContext() {
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
~AndroidJavaEGLGraphicsContext() {
|
~AndroidJavaEGLGraphicsContext() {
|
||||||
delete draw_;
|
delete draw_;
|
||||||
|
@ -310,6 +312,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
|
||||||
}
|
}
|
||||||
g_Vulkan->InitObjects(true);
|
g_Vulkan->InitObjects(true);
|
||||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
||||||
|
assert(draw_->CreatePresets()); // Doesn't fail, we ship the compiler.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ SDLJoystick *joystick = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "base/display.h"
|
#include "base/display.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
@ -51,6 +52,7 @@ public:
|
||||||
GLDummyGraphicsContext() {
|
GLDummyGraphicsContext() {
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
~GLDummyGraphicsContext() { delete draw_; }
|
~GLDummyGraphicsContext() { delete draw_; }
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ QTM_USE_NAMESPACE
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "base/display.h"
|
#include "base/display.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/timeutil.h"
|
#include "base/timeutil.h"
|
||||||
|
@ -42,6 +44,7 @@ class QtDummyGraphicsContext : public DummyGraphicsContext {
|
||||||
public:
|
public:
|
||||||
QtDummyGraphicsContext() {
|
QtDummyGraphicsContext() {
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
~QtDummyGraphicsContext() {
|
~QtDummyGraphicsContext() {
|
||||||
delete draw_;
|
delete draw_;
|
||||||
|
|
|
@ -299,12 +299,14 @@ static ShaderModule *CreateShader(DrawContext *draw, ShaderStage stage, const st
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::CreatePresets() {
|
bool DrawContext::CreatePresets() {
|
||||||
vsPresets_[VS_TEXTURE_COLOR_2D] = CreateShader(this, ShaderStage::VERTEX, vsTexCol);
|
vsPresets_[VS_TEXTURE_COLOR_2D] = CreateShader(this, ShaderStage::VERTEX, vsTexCol);
|
||||||
vsPresets_[VS_COLOR_2D] = CreateShader(this, ShaderStage::VERTEX, vsCol);
|
vsPresets_[VS_COLOR_2D] = CreateShader(this, ShaderStage::VERTEX, vsCol);
|
||||||
|
|
||||||
fsPresets_[FS_TEXTURE_COLOR_2D] = CreateShader(this, ShaderStage::FRAGMENT, fsTexCol);
|
fsPresets_[FS_TEXTURE_COLOR_2D] = CreateShader(this, ShaderStage::FRAGMENT, fsTexCol);
|
||||||
fsPresets_[FS_COLOR_2D] = CreateShader(this, ShaderStage::FRAGMENT, fsCol);
|
fsPresets_[FS_COLOR_2D] = CreateShader(this, ShaderStage::FRAGMENT, fsCol);
|
||||||
|
|
||||||
|
return vsPresets_[VS_TEXTURE_COLOR_2D] && vsPresets_[VS_COLOR_2D] && fsPresets_[FS_TEXTURE_COLOR_2D] && fsPresets_[FS_COLOR_2D];
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawContext::~DrawContext() {
|
DrawContext::~DrawContext() {
|
||||||
|
|
|
@ -583,6 +583,7 @@ struct RenderPassInfo {
|
||||||
class DrawContext {
|
class DrawContext {
|
||||||
public:
|
public:
|
||||||
virtual ~DrawContext();
|
virtual ~DrawContext();
|
||||||
|
bool CreatePresets();
|
||||||
|
|
||||||
virtual const DeviceCaps &GetDeviceCaps() const = 0;
|
virtual const DeviceCaps &GetDeviceCaps() const = 0;
|
||||||
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
|
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
|
||||||
|
@ -691,8 +692,6 @@ public:
|
||||||
virtual void FlushState() {}
|
virtual void FlushState() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CreatePresets();
|
|
||||||
|
|
||||||
ShaderModule *vsPresets_[VS_MAX_PRESET];
|
ShaderModule *vsPresets_[VS_MAX_PRESET];
|
||||||
ShaderModule *fsPresets_[FS_MAX_PRESET];
|
ShaderModule *fsPresets_[FS_MAX_PRESET];
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,6 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
|
||||||
}
|
}
|
||||||
dxgiDevice->Release();
|
dxgiDevice->Release();
|
||||||
}
|
}
|
||||||
CreatePresets();
|
|
||||||
|
|
||||||
// Temp texture for read-back of small images. Custom textures are created on demand for larger ones.
|
// Temp texture for read-back of small images. Custom textures are created on demand for larger ones.
|
||||||
// TODO: Should really benchmark if this extra complexity has any benefit.
|
// TODO: Should really benchmark if this extra complexity has any benefit.
|
||||||
|
|
|
@ -585,7 +585,6 @@ private:
|
||||||
|
|
||||||
D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx)
|
D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx)
|
||||||
: d3d_(d3d), d3dEx_(d3dEx), adapterId_(adapterId), device_(device), deviceEx_(deviceEx), caps_{} {
|
: d3d_(d3d), d3dEx_(d3dEx), adapterId_(adapterId), device_(device), deviceEx_(deviceEx), caps_{} {
|
||||||
CreatePresets();
|
|
||||||
if (FAILED(d3d->GetAdapterIdentifier(adapterId, 0, &identifier_))) {
|
if (FAILED(d3d->GetAdapterIdentifier(adapterId, 0, &identifier_))) {
|
||||||
ELOG("Failed to get adapter identifier: %d", adapterId);
|
ELOG("Failed to get adapter identifier: %d", adapterId);
|
||||||
}
|
}
|
||||||
|
@ -633,6 +632,10 @@ Pipeline *D3D9Context::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||||
}
|
}
|
||||||
D3D9Pipeline *pipeline = new D3D9Pipeline(device_);
|
D3D9Pipeline *pipeline = new D3D9Pipeline(device_);
|
||||||
for (auto iter : desc.shaders) {
|
for (auto iter : desc.shaders) {
|
||||||
|
if (!iter) {
|
||||||
|
ELOG("NULL shader passed to CreateGraphicsPipeline");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (iter->GetStage() == ShaderStage::FRAGMENT) {
|
if (iter->GetStage() == ShaderStage::FRAGMENT) {
|
||||||
pipeline->pshader = static_cast<D3D9ShaderModule *>(iter);
|
pipeline->pshader = static_cast<D3D9ShaderModule *>(iter);
|
||||||
}
|
}
|
||||||
|
@ -947,20 +950,24 @@ void D3D9Context::SetBlendFactor(float color[4]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, size_t size) {
|
bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, size_t size) {
|
||||||
LPD3DXMACRO defines = NULL;
|
LPD3DXMACRO defines = nullptr;
|
||||||
LPD3DXINCLUDE includes = NULL;
|
LPD3DXINCLUDE includes = nullptr;
|
||||||
DWORD flags = 0;
|
DWORD flags = 0;
|
||||||
LPD3DXBUFFER codeBuffer;
|
LPD3DXBUFFER codeBuffer = nullptr;
|
||||||
LPD3DXBUFFER errorBuffer;
|
LPD3DXBUFFER errorBuffer = nullptr;
|
||||||
const char *source = (const char *)data;
|
const char *source = (const char *)data;
|
||||||
const char *profile = stage_ == ShaderStage::FRAGMENT ? "ps_2_0" : "vs_2_0";
|
const char *profile = stage_ == ShaderStage::FRAGMENT ? "ps_2_0" : "vs_2_0";
|
||||||
HRESULT hr = dyn_D3DXCompileShader(source, (UINT)strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, nullptr);
|
HRESULT hr = dyn_D3DXCompileShader(source, (UINT)strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
const char *error = (const char *)errorBuffer->GetBufferPointer();
|
const char *error = errorBuffer ? (const char *)errorBuffer->GetBufferPointer() : "(no errorbuffer returned)";
|
||||||
|
if (hr == ERROR_MOD_NOT_FOUND) {
|
||||||
|
// No D3D9-compatible shader compiler installed.
|
||||||
|
error = "D3D9 shader compiler not installed";
|
||||||
|
}
|
||||||
OutputDebugStringA(source);
|
OutputDebugStringA(source);
|
||||||
OutputDebugStringA(error);
|
OutputDebugStringA(error);
|
||||||
errorBuffer->Release();
|
if (errorBuffer)
|
||||||
|
errorBuffer->Release();
|
||||||
if (codeBuffer)
|
if (codeBuffer)
|
||||||
codeBuffer->Release();
|
codeBuffer->Release();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -591,8 +591,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenGLContext::OpenGLContext() {
|
OpenGLContext::OpenGLContext() {
|
||||||
CreatePresets();
|
|
||||||
|
|
||||||
// TODO: Detect more caps
|
// TODO: Detect more caps
|
||||||
if (gl_extensions.IsGLES) {
|
if (gl_extensions.IsGLES) {
|
||||||
if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) {
|
if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) {
|
||||||
|
|
|
@ -719,7 +719,6 @@ VKContext::VKContext(VulkanContext *vulkan)
|
||||||
viewport_.minDepth = 0.0f;
|
viewport_.minDepth = 0.0f;
|
||||||
viewport_.maxDepth = 0.0f;
|
viewport_.maxDepth = 0.0f;
|
||||||
memset(boundTextures_, 0, sizeof(boundTextures_));
|
memset(boundTextures_, 0, sizeof(boundTextures_));
|
||||||
CreatePresets();
|
|
||||||
|
|
||||||
VkDescriptorPoolSize dpTypes[2];
|
VkDescriptorPoolSize dpTypes[2];
|
||||||
dpTypes[0].descriptorCount = 200;
|
dpTypes[0].descriptorCount = 200;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <cassert>
|
||||||
#include "gfx/gl_lost_manager.h"
|
#include "gfx/gl_lost_manager.h"
|
||||||
|
|
||||||
#include "headless/SDLHeadlessHost.h"
|
#include "headless/SDLHeadlessHost.h"
|
||||||
|
@ -54,6 +55,7 @@ public:
|
||||||
GLDummyGraphicsContext() {
|
GLDummyGraphicsContext() {
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
~GLDummyGraphicsContext() { delete draw_; }
|
~GLDummyGraphicsContext() { delete draw_; }
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#import "ViewController.h"
|
#import "ViewController.h"
|
||||||
#import "AudioEngine.h"
|
#import "AudioEngine.h"
|
||||||
#import <GLKit/GLKit.h>
|
#import <GLKit/GLKit.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "base/display.h"
|
#include "base/display.h"
|
||||||
#include "base/timeutil.h"
|
#include "base/timeutil.h"
|
||||||
|
@ -38,6 +39,7 @@ public:
|
||||||
IOSDummyGraphicsContext() {
|
IOSDummyGraphicsContext() {
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
assert(draw_->CreatePresets());
|
||||||
}
|
}
|
||||||
~IOSDummyGraphicsContext() {
|
~IOSDummyGraphicsContext() {
|
||||||
delete draw_;
|
delete draw_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue