libretro: dx11 crash in single-threaded. Use compiler and feature level

libretro: Null first frame erroneously set as valid causing a crash with dx11 (single-threaded rendering)
libretro: pass dx11 compiler pointer to shaders
dx11: use feature level to check if per-pixel is supported
This commit is contained in:
flyinghead 2021-12-14 10:41:04 +01:00
parent 6a3a8d5578
commit 4d60150345
11 changed files with 32 additions and 20 deletions

View File

@ -487,7 +487,7 @@ ComPtr<ID3DBlob> DX11Shaders::compileShader(const char* source, const char* func
if (!lookupShader(hash, shaderBlob))
{
ComPtr<ID3DBlob> errorBlob;
if (FAILED(D3DCompile(source, strlen(source), nullptr, pDefines, nullptr, function, profile, 0, 0, &shaderBlob.get(), &errorBlob.get())))
if (FAILED(this->D3DCompile(source, strlen(source), nullptr, pDefines, nullptr, function, profile, 0, 0, &shaderBlob.get(), &errorBlob.get())))
ERROR_LOG(RENDERER, "Shader compilation failed: %s", errorBlob->GetBufferPointer());
else
cacheShader(hash, shaderBlob);
@ -538,9 +538,10 @@ ComPtr<ID3DBlob> DX11Shaders::getQuadVertexShaderBlob()
return compileShader(QuadVertexShader, "main", "vs_4_0", nullptr);
}
void DX11Shaders::init(const ComPtr<ID3D11Device>& device)
void DX11Shaders::init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCompile)
{
this->device = device;
this->D3DCompile = D3DCompile;
enableCache(!theDX11Context.hasShaderCache());
loadCache(CacheFile);
}

View File

@ -47,7 +47,7 @@ private:
class DX11Shaders : CachedDX11Shaders
{
public:
void init(const ComPtr<ID3D11Device>& device);
void init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCompile);
void term();
const ComPtr<ID3D11PixelShader>& getShader(bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr,
@ -77,6 +77,7 @@ private:
ComPtr<ID3D11PixelShader> quadPixelShader;
ComPtr<ID3D11VertexShader> quadVertexShader;
ComPtr<ID3D11VertexShader> quadRotateVertexShader;
pD3DCompile D3DCompile = nullptr;
constexpr static const char *CacheFile = "dx11_shader_cache.bin";
};

View File

@ -89,7 +89,7 @@ bool DX11Context::init(bool keepCurrentWindow)
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&pDevice.get(),
nullptr,
&featureLevel,
&pDeviceContext.get());
ComPtr<IDXGIDevice2> dxgiDevice;
@ -168,7 +168,7 @@ bool DX11Context::init(bool keepCurrentWindow)
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX11Driver());
resize();
gui_init();
shaders.init(pDevice);
shaders.init(pDevice, &D3DCompile);
overlay.init(pDevice, pDeviceContext, &shaders, &samplers);
return ImGui_ImplDX11_Init(pDevice, pDeviceContext);
}

View File

@ -40,6 +40,8 @@ public:
const ComPtr<ID3D11Device>& getDevice() const { return pDevice; }
const ComPtr<ID3D11DeviceContext>& getDeviceContext() const { return pDeviceContext; }
ComPtr<ID3D11RenderTargetView>& getRenderTarget() { return renderTargetView; }
const pD3DCompile getCompiler() const { return D3DCompile; }
void resize() override;
void setOverlay(bool overlayOnly) { this->overlayOnly = overlayOnly; }
std::string getDriverName() override {
@ -49,7 +51,7 @@ public:
return adapterVersion;
}
bool hasPerPixel() override {
return true;
return featureLevel >= D3D_FEATURE_LEVEL_11_0;
}
bool isIntel() const {
return vendorId == VENDOR_INTEL;
@ -86,6 +88,7 @@ private:
bool _hasShaderCache = false;
DX11Shaders shaders;
Samplers samplers;
D3D_FEATURE_LEVEL featureLevel{};
static constexpr UINT VENDOR_INTEL = 0x8086;
};

View File

@ -22,11 +22,13 @@
DX11Context theDX11Context;
bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext)
bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel)
{
NOTICE_LOG(RENDERER, "DX11 Context initializing");
pDevice.reset(device);
pDeviceContext.reset(deviceContext);
this->D3DCompile = D3DCompile;
this->featureLevel = featureLevel;
GraphicsContext::instance = this;
ComPtr<IDXGIDevice2> dxgiDevice;
@ -46,7 +48,7 @@ bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext)
NOTICE_LOG(RENDERER, "No system-provided shader cache");
}
shaders.init(pDevice);
shaders.init(pDevice, D3DCompile);
// overlay.init(pDevice, pDeviceContext, &shaders, &samplers);
return true;
}

View File

@ -31,14 +31,18 @@
class DX11Context : public GraphicsContext
{
public:
bool init(ID3D11Device *device, ID3D11DeviceContext *deviceContext);
bool init(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel);
void term() override;
const ComPtr<ID3D11Device>& getDevice() const { return pDevice; }
const ComPtr<ID3D11DeviceContext>& getDeviceContext() const { return pDeviceContext; }
const pD3DCompile getCompiler() const { return this->D3DCompile; }
std::string getDriverName() override { return ""; }
std::string getDriverVersion() override { return ""; }
bool hasPerPixel() override {
return featureLevel >= D3D_FEATURE_LEVEL_11_0;
}
bool isIntel() const {
return vendorId == VENDOR_INTEL;
@ -57,10 +61,12 @@ public:
private:
ComPtr<ID3D11Device> pDevice;
ComPtr<ID3D11DeviceContext> pDeviceContext;
pD3DCompile D3DCompile = nullptr;
UINT vendorId = 0;
bool _hasShaderCache = false;
DX11Shaders shaders;
Samplers samplers;
D3D_FEATURE_LEVEL featureLevel{};
static constexpr UINT VENDOR_INTEL = 0x8086;
};

View File

@ -77,7 +77,7 @@ struct DX11OITRenderer : public DX11Renderer
desc.ByteWidth = (((desc.ByteWidth - 1) >> 4) + 1) << 4;
bool success = SUCCEEDED(device->CreateBuffer(&desc, nullptr, &pxlPolyConstants.get()));
shaders.init(device);
shaders.init(device, theDX11Context.getCompiler());
buffers.init(device, deviceContext);
ComPtr<ID3DBlob> blob = shaders.getVertexShaderBlob();
mainInputLayout.reset();

View File

@ -972,7 +972,7 @@ ComPtr<ID3DBlob> DX11OITShaders::compileShader(const char* source, const char* f
ComPtr<ID3DBlob> errorBlob;
IncludeManager includeManager;
if (FAILED(D3DCompile(source, strlen(source), nullptr, pDefines, &includeManager, function, profile, 0, 0, &shaderBlob.get(), &errorBlob.get())))
if (FAILED(this->D3DCompile(source, strlen(source), nullptr, pDefines, &includeManager, function, profile, 0, 0, &shaderBlob.get(), &errorBlob.get())))
ERROR_LOG(RENDERER, "Shader compilation failed: %s", errorBlob->GetBufferPointer());
else
cacheShader(hash, shaderBlob);
@ -1018,9 +1018,10 @@ ComPtr<ID3DBlob> DX11OITShaders::getMVVertexShaderBlob()
return compileShader(ModVolVertexShader, "main", "vs_5_0", nullptr);
}
void DX11OITShaders::init(const ComPtr<ID3D11Device>& device)
void DX11OITShaders::init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCompile)
{
this->device = device;
this->D3DCompile = D3DCompile;
enableCache(!theDX11Context.hasShaderCache());
loadCache(CacheFile);
}

View File

@ -30,7 +30,7 @@ class DX11OITShaders : CachedDX11Shaders
public:
enum Pass { Depth, Color, OIT };
void init(const ComPtr<ID3D11Device>& device);
void init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCompile);
const ComPtr<ID3D11PixelShader>& getShader(bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr,
bool pp_Offset, u32 pp_FogCtrl, bool pp_BumpMap, bool fog_clamping,
@ -76,6 +76,7 @@ private:
ComPtr<ID3D11PixelShader> finalShader;
ComPtr<ID3D11PixelShader> clearShader;
ComPtr<ID3D11VertexShader> finalVertexShader;
pD3DCompile D3DCompile = nullptr;
constexpr static const char *CacheFile = "dx11oit_shader_cache.bin";
};

View File

@ -863,11 +863,11 @@ void retro_run()
if (environ_cb(RETRO_ENVIRONMENT_GET_FASTFORWARDING, &fastforward))
settings.input.fastForwardMode = fastforward;
is_dupe = true;
try {
if (config::ThreadedRendering)
{
// Render
is_dupe = true;
for (int i = 0; i < 5 && is_dupe; i++)
is_dupe = !emu.render();
}
@ -886,9 +886,6 @@ void retro_run()
glsm_ctl(GLSM_CTL_STATE_UNBIND, nullptr);
video_cb(is_dupe ? 0 : RETRO_HW_FRAME_BUFFER_VALID, framebufferWidth, framebufferHeight, 0);
if (!config::ThreadedRendering)
is_dupe = true;
}
static bool loadGame()
@ -1511,7 +1508,7 @@ static void dx11_context_reset()
rend_term_renderer();
theDX11Context.term();
theDX11Context.init(hw_render->device, hw_render->context);
theDX11Context.init(hw_render->device, hw_render->context, hw_render->D3DCompile, hw_render->featureLevel);
if (config::RendererType == RenderType::OpenGL_OIT || config::RendererType == RenderType::Vulkan_OIT)
config::RendererType = RenderType::DirectX11_OIT;
else if (config::RendererType != RenderType::DirectX11_OIT)

View File

@ -23,12 +23,12 @@ BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "Flycast Team"
VALUE "FileDescription", "Flycast is a multiplatform Sega Dreamcast, Naomi and Atomiswave emulator"
VALUE "FileDescription", "Flycast"
VALUE "FileVersion", GIT_VERSION
VALUE "InternalName", "flycast"
VALUE "LegalCopyright", "Copyright various authors. Released under the GNU General Public License."
VALUE "OriginalFilename", "flycast.exe"
VALUE "ProductName", "Flycast"
VALUE "ProductName", "Flycast is a multiplatform Sega Dreamcast, Naomi and Atomiswave emulator"
VALUE "ProductVersion", GIT_VERSION
END
END