Skip to content

Commit

Permalink
AbstractPipeline: Support returning "cache data"
Browse files Browse the repository at this point in the history
"Cache data" can be used to assist a driver with creating pipelines by
using previously-compiled shader ISA.
  • Loading branch information
stenzek committed Apr 15, 2019
1 parent 2863183 commit 61a6565
Show file tree
Hide file tree
Showing 29 changed files with 68 additions and 51 deletions.
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/D3D/Render.cpp
Expand Up @@ -127,7 +127,9 @@ std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage sta
return DXShader::CreateFromBytecode(stage, DXShader::CreateByteCode(data, length));
}

std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return DXPipeline::Create(config);
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/D3D/Render.h
Expand Up @@ -34,7 +34,9 @@ class Renderer : public ::Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/D3D/main.cpp
Expand Up @@ -82,6 +82,8 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true;
g_Config.backend_info.bSupportsGSInstancing = true;
g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsShaderBinaries = true;
g_Config.backend_info.bSupportsPipelineCacheData = false;

g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/D3D12/Renderer.cpp
Expand Up @@ -99,7 +99,9 @@ Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
return std::make_unique<DXVertexFormat>(vtx_decl);
}

std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return DXPipeline::Create(config);
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/D3D12/Renderer.h
Expand Up @@ -41,7 +41,9 @@ class Renderer final : public ::Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;

u16 BBoxRead(int index) override;
void BBoxWrite(int index, u16 value) override;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/D3D12/VideoBackend.cpp
Expand Up @@ -80,6 +80,8 @@ void VideoBackend::FillBackendInfo()
g_Config.backend_info.bSupportsPartialDepthCopies = false;
g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
g_Config.backend_info.AAModes = DXContext::GetAAModes(g_Config.iAdapter);
g_Config.backend_info.bSupportsShaderBinaries = true;
g_Config.backend_info.bSupportsPipelineCacheData = true;

// We can only check texture support once we have a device.
if (g_dx_context)
Expand Down
5 changes: 0 additions & 5 deletions Source/Core/VideoBackends/D3DCommon/Shader.cpp
Expand Up @@ -23,11 +23,6 @@ Shader::Shader(ShaderStage stage, BinaryData bytecode)

Shader::~Shader() = default;

bool Shader::HasBinary() const
{
return true;
}

AbstractShader::BinaryData Shader::GetBinary() const
{
return m_bytecode;
Expand Down
1 change: 0 additions & 1 deletion Source/Core/VideoBackends/D3DCommon/Shader.h
Expand Up @@ -16,7 +16,6 @@ class Shader : public AbstractShader

const BinaryData& GetByteCode() const { return m_bytecode; }

bool HasBinary() const override;
BinaryData GetBinary() const override;

static bool CompileShader(D3D_FEATURE_LEVEL feature_level, BinaryData* out_bytecode,
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/Null/NullBackend.cpp
Expand Up @@ -52,6 +52,8 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsLogicOp = false;
g_Config.backend_info.bSupportsLargePoints = false;
g_Config.backend_info.bSupportsPartialDepthCopies = false;
g_Config.backend_info.bSupportsShaderBinaries = false;
g_Config.backend_info.bSupportsPipelineCacheData = false;

// aamodes: We only support 1 sample, so no MSAA
g_Config.backend_info.Adapters.clear();
Expand Down
7 changes: 3 additions & 4 deletions Source/Core/VideoBackends/Null/Render.cpp
Expand Up @@ -46,9 +46,6 @@ class NullShader final : public AbstractShader
public:
explicit NullShader(ShaderStage stage) : AbstractShader(stage) {}
~NullShader() = default;

bool HasBinary() const override { return false; }
BinaryData GetBinary() const override { return {}; }
};

std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
Expand All @@ -70,7 +67,9 @@ class NullPipeline final : public AbstractPipeline
~NullPipeline() override = default;
};

std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return std::make_unique<NullPipeline>();
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/Null/Render.h
Expand Up @@ -28,7 +28,9 @@ class Renderer : public ::Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;

u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; }
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
Expand Down
11 changes: 0 additions & 11 deletions Source/Core/VideoBackends/OGL/OGLShader.cpp
Expand Up @@ -44,17 +44,6 @@ OGLShader::~OGLShader()
glDeleteProgram(m_gl_compute_program_id);
}

bool OGLShader::HasBinary() const
{
// NOTE: GL shaders do not have binaries, programs do.
return false;
}

AbstractShader::BinaryData OGLShader::GetBinary() const
{
return {};
}

std::unique_ptr<OGLShader> OGLShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
{
Expand Down
2 changes: 0 additions & 2 deletions Source/Core/VideoBackends/OGL/OGLShader.h
Expand Up @@ -24,8 +24,6 @@ class OGLShader final : public AbstractShader
GLenum GetGLShaderType() const { return m_type; }
GLuint GetGLShaderID() const { return m_gl_id; }
GLuint GetGLComputeProgramID() const { return m_gl_compute_program_id; }
bool HasBinary() const override;
BinaryData GetBinary() const override;

static std::unique_ptr<OGLShader> CreateFromSource(ShaderStage stage, const char* source,
size_t length);
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/OGL/Render.cpp
Expand Up @@ -828,7 +828,9 @@ std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage sta
return nullptr;
}

std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return OGLPipeline::Create(config);
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/OGL/Render.h
Expand Up @@ -102,7 +102,9 @@ class Renderer : public ::Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;
std::unique_ptr<AbstractFramebuffer>
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/OGL/main.cpp
Expand Up @@ -90,6 +90,8 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsCopyToVram = true;
g_Config.backend_info.bSupportsLargePoints = true;
g_Config.backend_info.bSupportsPartialDepthCopies = true;
g_Config.backend_info.bSupportsShaderBinaries = false;
g_Config.backend_info.bSupportsPipelineCacheData = false;

// TODO: There is a bug here, if texel buffers or SSBOs/atomics are not supported the graphics
// options will show the option when it is not supported. The only way around this would be
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/VideoBackends/Software/SWRenderer.cpp
Expand Up @@ -64,7 +64,6 @@ class SWShader final : public AbstractShader
explicit SWShader(ShaderStage stage) : AbstractShader(stage) {}
~SWShader() = default;

bool HasBinary() const override { return false; }
BinaryData GetBinary() const override { return {}; }
};

Expand All @@ -87,7 +86,9 @@ class SWPipeline final : public AbstractPipeline
~SWPipeline() override = default;
};

std::unique_ptr<AbstractPipeline> SWRenderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> SWRenderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return std::make_unique<SWPipeline>();
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/Software/SWRenderer.h
Expand Up @@ -33,7 +33,9 @@ class SWRenderer final : public Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;

u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/Software/SWmain.cpp
Expand Up @@ -74,6 +74,8 @@ void VideoSoftware::InitBackendInfo()
g_Config.backend_info.bSupportsFramebufferFetch = false;
g_Config.backend_info.bSupportsBackgroundCompiling = false;
g_Config.backend_info.bSupportsLogicOp = true;
g_Config.backend_info.bSupportsShaderBinaries = false;
g_Config.backend_info.bSupportsPipelineCacheData = false;

// aamodes
g_Config.backend_info.AAModes = {1};
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/Vulkan/Renderer.cpp
Expand Up @@ -112,7 +112,9 @@ Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
return std::make_unique<VertexFormat>(vtx_decl);
}

std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data,
size_t cache_data_length)
{
return VKPipeline::Create(config);
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/VideoBackends/Vulkan/Renderer.h
Expand Up @@ -48,7 +48,9 @@ class Renderer : public ::Renderer
size_t length) override;
std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) override;

SwapChain* GetSwapChain() const { return m_swap_chain.get(); }
BoundingBox* GetBoundingBox() const { return m_bounding_box.get(); }
Expand Down
6 changes: 0 additions & 6 deletions Source/Core/VideoBackends/Vulkan/VKShader.cpp
Expand Up @@ -32,12 +32,6 @@ VKShader::~VKShader()
vkDestroyPipeline(g_vulkan_context->GetDevice(), m_compute_pipeline, nullptr);
}

bool VKShader::HasBinary() const
{
ASSERT(!m_spv.empty());
return true;
}

AbstractShader::BinaryData VKShader::GetBinary() const
{
BinaryData ret(sizeof(u32) * m_spv.size());
Expand Down
1 change: 0 additions & 1 deletion Source/Core/VideoBackends/Vulkan/VKShader.h
Expand Up @@ -23,7 +23,6 @@ class VKShader final : public AbstractShader

VkShaderModule GetShaderModule() const { return m_module; }
VkPipeline GetComputePipeline() const { return m_compute_pipeline; }
bool HasBinary() const override;
BinaryData GetBinary() const override;

static std::unique_ptr<VKShader> CreateFromSource(ShaderStage stage, const char* source,
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoBackends/Vulkan/VulkanContext.cpp
Expand Up @@ -266,6 +266,8 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
config->backend_info.bSupportsGPUTextureDecoding = true; // Assumed support.
config->backend_info.bSupportsBitfield = true; // Assumed support.
config->backend_info.bSupportsPartialDepthCopies = true; // Assumed support.
config->backend_info.bSupportsShaderBinaries = true; // Assumed support.
config->backend_info.bSupportsPipelineCacheData = false; // Handled via pipeline caches.
config->backend_info.bSupportsDynamicSamplerIndexing = true; // Assumed support.
config->backend_info.bSupportsPostProcessing = true; // Assumed support.
config->backend_info.bSupportsBackgroundCompiling = true; // Assumed support.
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/VideoCommon/AbstractPipeline.h
Expand Up @@ -75,4 +75,10 @@ class AbstractPipeline
public:
AbstractPipeline() = default;
virtual ~AbstractPipeline() = default;

// "Cache data" can be used to assist a driver with creating pipelines by using previously
// compiled shader ISA. The abstract shaders and creation struct are still required to create
// pipeline objects, the cache is optionally used by the driver to speed up compilation.
using CacheData = std::vector<u8>;
virtual CacheData GetCacheData() const { return {}; }
};
6 changes: 4 additions & 2 deletions Source/Core/VideoCommon/AbstractShader.h
Expand Up @@ -25,9 +25,11 @@ class AbstractShader
virtual ~AbstractShader() = default;

ShaderStage GetStage() const { return m_stage; }

// Shader binaries represent the input source code in a lower-level form. e.g. SPIR-V or DXBC.
// The shader source code is not required to create a shader object from the binary.
using BinaryData = std::vector<u8>;
virtual bool HasBinary() const = 0;
virtual BinaryData GetBinary() const = 0;
virtual BinaryData GetBinary() const { return {}; }

protected:
ShaderStage m_stage;
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/VideoCommon/RenderBase.h
Expand Up @@ -130,8 +130,9 @@ class Renderer
CreateShaderFromBinary(ShaderStage stage, const void* data, size_t length) = 0;
virtual std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) = 0;
virtual std::unique_ptr<AbstractPipeline>
CreatePipeline(const AbstractPipelineConfig& config) = 0;
virtual std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config,
const void* cache_data = nullptr,
size_t cache_data_length = 0) = 0;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage,
const std::string& source);

Expand Down
10 changes: 5 additions & 5 deletions Source/Core/VideoCommon/ShaderCache.cpp
Expand Up @@ -334,7 +334,7 @@ const AbstractShader* ShaderCache::InsertVertexShader(const VertexShaderUid& uid

if (shader && !entry.shader)
{
if (g_ActiveConfig.bShaderCache && shader->HasBinary())
if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
{
auto binary = shader->GetBinary();
if (!binary.empty())
Expand All @@ -356,7 +356,7 @@ const AbstractShader* ShaderCache::InsertVertexUberShader(const UberShader::Vert

if (shader && !entry.shader)
{
if (g_ActiveConfig.bShaderCache && shader->HasBinary())
if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
{
auto binary = shader->GetBinary();
if (!binary.empty())
Expand All @@ -378,7 +378,7 @@ const AbstractShader* ShaderCache::InsertPixelShader(const PixelShaderUid& uid,

if (shader && !entry.shader)
{
if (g_ActiveConfig.bShaderCache && shader->HasBinary())
if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
{
auto binary = shader->GetBinary();
if (!binary.empty())
Expand All @@ -400,7 +400,7 @@ const AbstractShader* ShaderCache::InsertPixelUberShader(const UberShader::Pixel

if (shader && !entry.shader)
{
if (g_ActiveConfig.bShaderCache && shader->HasBinary())
if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
{
auto binary = shader->GetBinary();
if (!binary.empty())
Expand All @@ -425,7 +425,7 @@ const AbstractShader* ShaderCache::CreateGeometryShader(const GeometryShaderUid&

if (shader && !entry.shader)
{
if (g_ActiveConfig.bShaderCache && shader->HasBinary())
if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
{
auto binary = shader->GetBinary();
if (!binary.empty())
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoCommon/VideoConfig.h
Expand Up @@ -219,6 +219,8 @@ struct VideoConfig final
bool bSupportsBackgroundCompiling;
bool bSupportsLargePoints;
bool bSupportsPartialDepthCopies;
bool bSupportsShaderBinaries;
bool bSupportsPipelineCacheData;
} backend_info;

// Utility
Expand Down

0 comments on commit 61a6565

Please sign in to comment.