mirror of https://github.com/AxioDL/boo.git
Runtime shader cache fixes
This commit is contained in:
parent
03f155fcf5
commit
a547eb9dbb
|
@ -7,6 +7,9 @@
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
template <class T>
|
template <class T>
|
||||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||||
|
template <class T>
|
||||||
|
static inline ComPtr<T>* ReferenceComPtr(ComPtr<T>& ptr)
|
||||||
|
{ return reinterpret_cast<ComPtr<T>*>(ptr.GetAddressOf()); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -28,8 +28,8 @@ public:
|
||||||
public:
|
public:
|
||||||
bool bindingNeedsVertexFormat() const {return false;}
|
bool bindingNeedsVertexFormat() const {return false;}
|
||||||
virtual IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
virtual IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
ComPtr<ID3DBlob>& vertBlobOut, ComPtr<ID3DBlob>& fragBlobOut,
|
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
|
||||||
ComPtr<ID3DBlob>& pipelineBlob, IVertexFormat* vtxFmt,
|
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)=0;
|
bool depthTest, bool depthWrite, bool backfaceCulling)=0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -280,7 +280,7 @@ class GraphicsDataToken
|
||||||
friend class D3D12DataFactory;
|
friend class D3D12DataFactory;
|
||||||
friend class D3D11DataFactory;
|
friend class D3D11DataFactory;
|
||||||
friend class MetalDataFactoryImpl;
|
friend class MetalDataFactoryImpl;
|
||||||
friend class VulkanDataFactory;
|
friend class VulkanDataFactoryImpl;
|
||||||
IGraphicsDataFactory* m_factory = nullptr;
|
IGraphicsDataFactory* m_factory = nullptr;
|
||||||
IGraphicsData* m_data = nullptr;
|
IGraphicsData* m_data = nullptr;
|
||||||
GraphicsDataToken(IGraphicsDataFactory* factory, IGraphicsData* data)
|
GraphicsDataToken(IGraphicsDataFactory* factory, IGraphicsData* data)
|
||||||
|
@ -327,7 +327,7 @@ class GraphicsBufferPoolToken
|
||||||
friend class D3D12DataFactory;
|
friend class D3D12DataFactory;
|
||||||
friend class D3D11DataFactory;
|
friend class D3D11DataFactory;
|
||||||
friend class MetalDataFactoryImpl;
|
friend class MetalDataFactoryImpl;
|
||||||
friend class VulkanDataFactory;
|
friend class VulkanDataFactoryImpl;
|
||||||
IGraphicsDataFactory* m_factory = nullptr;
|
IGraphicsDataFactory* m_factory = nullptr;
|
||||||
IGraphicsBufferPool* m_pool = nullptr;
|
IGraphicsBufferPool* m_pool = nullptr;
|
||||||
GraphicsBufferPoolToken(IGraphicsDataFactory* factory, IGraphicsBufferPool* pool)
|
GraphicsBufferPoolToken(IGraphicsDataFactory* factory, IGraphicsBufferPool* pool)
|
||||||
|
|
|
@ -103,31 +103,10 @@ extern VulkanContext g_VulkanContext;
|
||||||
|
|
||||||
class VulkanDataFactory : public IGraphicsDataFactory
|
class VulkanDataFactory : public IGraphicsDataFactory
|
||||||
{
|
{
|
||||||
friend struct VulkanCommandQueue;
|
|
||||||
IGraphicsContext* m_parent;
|
|
||||||
VulkanContext* m_ctx;
|
|
||||||
uint32_t m_drawSamples;
|
|
||||||
static ThreadLocalPtr<struct VulkanData> m_deferredData;
|
|
||||||
std::unordered_set<struct VulkanData*> m_committedData;
|
|
||||||
std::unordered_set<struct VulkanPool*> m_committedPools;
|
|
||||||
std::mutex m_committedMutex;
|
|
||||||
std::vector<int> m_texUnis;
|
|
||||||
void destroyData(IGraphicsData*);
|
|
||||||
void destroyPool(IGraphicsBufferPool*);
|
|
||||||
void destroyAllData();
|
|
||||||
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool *pool, BufferUse use,
|
|
||||||
size_t stride, size_t count);
|
|
||||||
void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf);
|
|
||||||
public:
|
public:
|
||||||
VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples);
|
|
||||||
~VulkanDataFactory() {destroyAllData();}
|
|
||||||
|
|
||||||
Platform platform() const {return Platform::Vulkan;}
|
|
||||||
const SystemChar* platformName() const {return _S("Vulkan");}
|
|
||||||
|
|
||||||
class Context : public IGraphicsDataFactory::Context
|
class Context : public IGraphicsDataFactory::Context
|
||||||
{
|
{
|
||||||
friend class VulkanDataFactory;
|
friend class VulkanDataFactoryImpl;
|
||||||
VulkanDataFactory& m_parent;
|
VulkanDataFactory& m_parent;
|
||||||
Context(VulkanDataFactory& parent) : m_parent(parent) {}
|
Context(VulkanDataFactory& parent) : m_parent(parent) {}
|
||||||
public:
|
public:
|
||||||
|
@ -150,8 +129,8 @@ public:
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
|
||||||
std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt,
|
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling);
|
bool depthTest, bool depthWrite, bool backfaceCulling);
|
||||||
|
|
||||||
|
@ -159,10 +138,7 @@ public:
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> vertBlob;
|
return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr,
|
||||||
std::vector<unsigned int> fragBlob;
|
|
||||||
std::vector<unsigned char> pipelineBlob;
|
|
||||||
return newShaderPipeline(vertSource, fragSource, vertBlob, fragBlob, pipelineBlob,
|
|
||||||
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,9 +151,6 @@ public:
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, ITexture** texs,
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
|
||||||
GraphicsBufferPoolToken newBufferPool();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,15 +55,15 @@ class IShareableShader
|
||||||
{
|
{
|
||||||
std::atomic_int m_refCount = {0};
|
std::atomic_int m_refCount = {0};
|
||||||
FactoryImpl& m_factory;
|
FactoryImpl& m_factory;
|
||||||
uint64_t m_key;
|
uint64_t m_srckey, m_binKey;
|
||||||
public:
|
public:
|
||||||
IShareableShader(FactoryImpl& factory, uint64_t key)
|
IShareableShader(FactoryImpl& factory, uint64_t srcKey, uint64_t binKey)
|
||||||
: m_factory(factory), m_key(key) {}
|
: m_factory(factory), m_srckey(srcKey), m_binKey(binKey) {}
|
||||||
void increment() { m_refCount++; }
|
void increment() { m_refCount++; }
|
||||||
void decrement()
|
void decrement()
|
||||||
{
|
{
|
||||||
if (m_refCount.fetch_sub(1) == 1)
|
if (m_refCount.fetch_sub(1) == 1)
|
||||||
m_factory._unregisterShareableShader(m_key);
|
m_factory._unregisterShareableShader(m_srckey, m_binKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Token
|
class Token
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
@ -21,6 +22,19 @@ extern pD3DCompile D3DCompilePROC;
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
static logvisor::Module Log("boo::D3D11");
|
static logvisor::Module Log("boo::D3D11");
|
||||||
|
class D3D11DataFactory;
|
||||||
|
|
||||||
|
struct D3D11ShareableShader : IShareableShader<D3D11DataFactory, D3D11ShareableShader>
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11DeviceChild> m_shader;
|
||||||
|
ComPtr<ID3DBlob> m_vtxBlob;
|
||||||
|
D3D11ShareableShader(D3D11DataFactory& fac, uint64_t srcKey, uint64_t binKey,
|
||||||
|
ComPtr<ID3D11DeviceChild>&& s, ComPtr<ID3DBlob>&& vb)
|
||||||
|
: IShareableShader(fac, srcKey, binKey), m_shader(std::move(s)), m_vtxBlob(std::move(vb)) {}
|
||||||
|
D3D11ShareableShader(D3D11DataFactory& fac, uint64_t srcKey, uint64_t binKey,
|
||||||
|
ComPtr<ID3D11DeviceChild>&& s)
|
||||||
|
: IShareableShader(fac, srcKey, binKey), m_shader(std::move(s)) {}
|
||||||
|
};
|
||||||
|
|
||||||
static inline void ThrowIfFailed(HRESULT hr)
|
static inline void ThrowIfFailed(HRESULT hr)
|
||||||
{
|
{
|
||||||
|
@ -479,15 +493,20 @@ class D3D11ShaderPipeline : public IShaderPipeline
|
||||||
friend class D3D11DataFactory;
|
friend class D3D11DataFactory;
|
||||||
friend struct D3D11ShaderDataBinding;
|
friend struct D3D11ShaderDataBinding;
|
||||||
const D3D11VertexFormat* m_vtxFmt;
|
const D3D11VertexFormat* m_vtxFmt;
|
||||||
|
D3D11ShareableShader::Token m_vert;
|
||||||
|
D3D11ShareableShader::Token m_pixel;
|
||||||
|
|
||||||
D3D11ShaderPipeline(D3D11Context* ctx, ID3DBlob* vert, ID3DBlob* pixel,
|
D3D11ShaderPipeline(D3D11Context* ctx,
|
||||||
|
D3D11ShareableShader::Token&& vert,
|
||||||
|
D3D11ShareableShader::Token&& pixel,
|
||||||
const D3D11VertexFormat* vtxFmt,
|
const D3D11VertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_vtxFmt(vtxFmt), m_topology(PRIMITIVE_TABLE[int(prim)])
|
: m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
|
||||||
|
m_topology(PRIMITIVE_TABLE[int(prim)])
|
||||||
{
|
{
|
||||||
ThrowIfFailed(ctx->m_dev->CreateVertexShader(vert->GetBufferPointer(), vert->GetBufferSize(), nullptr, &m_vShader));
|
m_vert.get().m_shader.As<ID3D11VertexShader>(&m_vShader);
|
||||||
ThrowIfFailed(ctx->m_dev->CreatePixelShader(pixel->GetBufferPointer(), pixel->GetBufferSize(), nullptr, &m_pShader));
|
m_pixel.get().m_shader.As<ID3D11PixelShader>(&m_pShader);
|
||||||
|
|
||||||
CD3D11_RASTERIZER_DESC rasDesc(D3D11_FILL_SOLID, backfaceCulling ? D3D11_CULL_BACK : D3D11_CULL_NONE, true,
|
CD3D11_RASTERIZER_DESC rasDesc(D3D11_FILL_SOLID, backfaceCulling ? D3D11_CULL_BACK : D3D11_CULL_NONE, true,
|
||||||
D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||||
|
@ -506,8 +525,9 @@ class D3D11ShaderPipeline : public IShaderPipeline
|
||||||
blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)];
|
blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)];
|
||||||
ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState));
|
ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState));
|
||||||
|
|
||||||
|
const auto& vertBuf = m_vert.get().m_vtxBlob;
|
||||||
ThrowIfFailed(ctx->m_dev->CreateInputLayout(vtxFmt->m_elements.get(), vtxFmt->m_elementCount,
|
ThrowIfFailed(ctx->m_dev->CreateInputLayout(vtxFmt->m_elements.get(), vtxFmt->m_elementCount,
|
||||||
vert->GetBufferPointer(), vert->GetBufferSize(), &m_inLayout));
|
vertBuf->GetBufferPointer(), vertBuf->GetBufferSize(), &m_inLayout));
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
ComPtr<ID3D11VertexShader> m_vShader;
|
ComPtr<ID3D11VertexShader> m_vShader;
|
||||||
|
@ -1125,6 +1145,8 @@ class D3D11DataFactory : public ID3DDataFactory
|
||||||
std::unordered_set<D3D11Data*> m_committedData;
|
std::unordered_set<D3D11Data*> m_committedData;
|
||||||
std::unordered_set<D3D11Pool*> m_committedPools;
|
std::unordered_set<D3D11Pool*> m_committedPools;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
|
std::unordered_map<uint64_t, std::unique_ptr<D3D11ShareableShader>> m_sharedShaders;
|
||||||
|
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||||
uint32_t m_sampleCount;
|
uint32_t m_sampleCount;
|
||||||
|
|
||||||
void destroyData(IGraphicsData* d)
|
void destroyData(IGraphicsData* d)
|
||||||
|
@ -1258,37 +1280,149 @@ public:
|
||||||
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint64_t CompileVert(ComPtr<ID3DBlob>& vertBlobOut, const char* vertSource, uint64_t srcKey,
|
||||||
|
D3D11DataFactory& factory)
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> errBlob;
|
||||||
|
if (FAILED(D3DCompilePROC(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main",
|
||||||
|
"vs_5_0", BOO_D3DCOMPILE_FLAG, 0, &vertBlobOut, &errBlob)))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "error compiling vert shader: %s", errBlob->GetBufferPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, vertBlobOut->GetBufferPointer(), vertBlobOut->GetBufferSize());
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t CompileFrag(ComPtr<ID3DBlob>& fragBlobOut, const char* fragSource, uint64_t srcKey,
|
||||||
|
D3D11DataFactory& factory)
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> errBlob;
|
||||||
|
if (FAILED(D3DCompilePROC(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main",
|
||||||
|
"ps_5_0", BOO_D3DCOMPILE_FLAG, 0, &fragBlobOut, &errBlob)))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "error compiling pixel shader: %s", errBlob->GetBufferPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, fragBlobOut->GetBufferPointer(), fragBlobOut->GetBufferSize());
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline
|
IShaderPipeline* newShaderPipeline
|
||||||
(const char* vertSource, const char* fragSource,
|
(const char* vertSource, const char* fragSource,
|
||||||
ComPtr<ID3DBlob>& vertBlobOut, ComPtr<ID3DBlob>& fragBlobOut,
|
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
|
||||||
ComPtr<ID3DBlob>& pipelineBlob, IVertexFormat* vtxFmt,
|
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
ComPtr<ID3DBlob> errBlob;
|
XXH64_state_t hashState;
|
||||||
|
uint64_t srcHashes[2] = {};
|
||||||
if (!vertBlobOut)
|
uint64_t binHashes[2] = {};
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (vertSource)
|
||||||
{
|
{
|
||||||
if (FAILED(D3DCompilePROC(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main",
|
XXH64_update(&hashState, vertSource, strlen(vertSource));
|
||||||
"vs_5_0", BOO_D3DCOMPILE_FLAG, 0, &vertBlobOut, &errBlob)))
|
srcHashes[0] = XXH64_digest(&hashState);
|
||||||
{
|
auto binSearch = m_parent.m_sourceToBinary.find(srcHashes[0]);
|
||||||
Log.report(logvisor::Fatal, "error compiling vert shader: %s", errBlob->GetBufferPointer());
|
if (binSearch != m_parent.m_sourceToBinary.cend())
|
||||||
return nullptr;
|
binHashes[0] = binSearch->second;
|
||||||
}
|
}
|
||||||
|
else if (vertBlobOut && *vertBlobOut)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, (*vertBlobOut)->GetBufferPointer(), (*vertBlobOut)->GetBufferSize());
|
||||||
|
binHashes[0] = XXH64_digest(&hashState);
|
||||||
|
}
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (fragSource)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, fragSource, strlen(fragSource));
|
||||||
|
srcHashes[1] = XXH64_digest(&hashState);
|
||||||
|
auto binSearch = m_parent.m_sourceToBinary.find(srcHashes[1]);
|
||||||
|
if (binSearch != m_parent.m_sourceToBinary.cend())
|
||||||
|
binHashes[1] = binSearch->second;
|
||||||
|
}
|
||||||
|
else if (fragBlobOut && *fragBlobOut)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, (*fragBlobOut)->GetBufferPointer(), (*fragBlobOut)->GetBufferSize());
|
||||||
|
binHashes[1] = XXH64_digest(&hashState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fragBlobOut)
|
if (vertBlobOut && !*vertBlobOut)
|
||||||
|
binHashes[0] = CompileVert(*vertBlobOut, vertSource, srcHashes[0], m_parent);
|
||||||
|
|
||||||
|
if (fragBlobOut && !*fragBlobOut)
|
||||||
|
binHashes[1] = CompileFrag(*fragBlobOut, fragSource, srcHashes[1], m_parent);
|
||||||
|
|
||||||
|
|
||||||
|
struct D3D11Context* ctx = m_parent.m_ctx;
|
||||||
|
D3D11ShareableShader::Token vertShader;
|
||||||
|
D3D11ShareableShader::Token fragShader;
|
||||||
|
auto vertFind = binHashes[0] ? m_parent.m_sharedShaders.find(binHashes[0]) :
|
||||||
|
m_parent.m_sharedShaders.end();
|
||||||
|
if (vertFind != m_parent.m_sharedShaders.end())
|
||||||
{
|
{
|
||||||
if (FAILED(D3DCompilePROC(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main",
|
vertShader = vertFind->second->lock();
|
||||||
"ps_5_0", BOO_D3DCOMPILE_FLAG, 0, &fragBlobOut, &errBlob)))
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> vertBlob;
|
||||||
|
if (vertBlobOut)
|
||||||
|
vertBlob = *vertBlobOut;
|
||||||
|
else
|
||||||
|
binHashes[0] = CompileVert(vertBlob, vertSource, srcHashes[0], m_parent);
|
||||||
|
|
||||||
|
ComPtr<ID3D11VertexShader> vShader;
|
||||||
|
ThrowIfFailed(ctx->m_dev->CreateVertexShader(vertBlob->GetBufferPointer(),
|
||||||
|
vertBlob->GetBufferSize(), nullptr, &vShader));
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
m_parent.m_sharedShaders.emplace(std::make_pair(binHashes[0],
|
||||||
|
std::make_unique<D3D11ShareableShader>(m_parent, srcHashes[0], binHashes[0],
|
||||||
|
std::move(vShader), std::move(vertBlob)))).first;
|
||||||
|
vertShader = it->second->lock();
|
||||||
|
}
|
||||||
|
auto fragFind = binHashes[1] ? m_parent.m_sharedShaders.find(binHashes[1]) :
|
||||||
|
m_parent.m_sharedShaders.end();
|
||||||
|
if (fragFind != m_parent.m_sharedShaders.end())
|
||||||
|
{
|
||||||
|
fragShader = fragFind->second->lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> fragBlob;
|
||||||
|
ComPtr<ID3DBlob>* useFragBlob;
|
||||||
|
if (fragBlobOut)
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Fatal, "error compiling pixel shader: %s", errBlob->GetBufferPointer());
|
useFragBlob = fragBlobOut;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useFragBlob = &fragBlob;
|
||||||
|
binHashes[1] = CompileFrag(fragBlob, fragSource, srcHashes[1], m_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<ID3D11PixelShader> pShader;
|
||||||
|
ThrowIfFailed(ctx->m_dev->CreatePixelShader((*useFragBlob)->GetBufferPointer(),
|
||||||
|
(*useFragBlob)->GetBufferSize(), nullptr, &pShader));
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
m_parent.m_sharedShaders.emplace(std::make_pair(binHashes[1],
|
||||||
|
std::make_unique<D3D11ShareableShader>(m_parent, srcHashes[1], binHashes[1],
|
||||||
|
std::move(pShader)))).first;
|
||||||
|
fragShader = it->second->lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11Data* d = static_cast<D3D11Data*>(m_deferredData);
|
D3D11Data* d = static_cast<D3D11Data*>(m_deferredData);
|
||||||
D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(m_parent.m_ctx, vertBlobOut.Get(), fragBlobOut.Get(),
|
D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(ctx,
|
||||||
|
std::move(vertShader), std::move(fragShader),
|
||||||
static_cast<const D3D11VertexFormat*>(vtxFmt),
|
static_cast<const D3D11VertexFormat*>(vtxFmt),
|
||||||
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
||||||
d->m_SPs.emplace_back(retval);
|
d->m_SPs.emplace_back(retval);
|
||||||
|
@ -1342,6 +1476,13 @@ public:
|
||||||
m_committedPools.insert(retval);
|
m_committedPools.insert(retval);
|
||||||
return GraphicsBufferPoolToken(this, retval);
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey)
|
||||||
|
{
|
||||||
|
if (srcKey)
|
||||||
|
m_sourceToBinary.erase(srcKey);
|
||||||
|
m_sharedShaders.erase(binKey);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local D3D11Data* D3D11DataFactory::m_deferredData;
|
thread_local D3D11Data* D3D11DataFactory::m_deferredData;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
#define MAX_UNIFORM_COUNT 8
|
#define MAX_UNIFORM_COUNT 8
|
||||||
#define MAX_TEXTURE_COUNT 8
|
#define MAX_TEXTURE_COUNT 8
|
||||||
|
@ -23,6 +24,14 @@ extern pD3DCompile D3DCompilePROC;
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
static logvisor::Module Log("boo::D3D12");
|
static logvisor::Module Log("boo::D3D12");
|
||||||
|
class D3D12DataFactory;
|
||||||
|
|
||||||
|
struct D3D12ShareableShader : IShareableShader<D3D12DataFactory, D3D12ShareableShader>
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> m_shader;
|
||||||
|
D3D12ShareableShader(D3D12DataFactory& fac, uint64_t srcKey, uint64_t binKey, ComPtr<ID3DBlob>&& s)
|
||||||
|
: IShareableShader(fac, srcKey, binKey), m_shader(std::move(s)) {}
|
||||||
|
};
|
||||||
|
|
||||||
static inline void ThrowIfFailed(HRESULT hr)
|
static inline void ThrowIfFailed(HRESULT hr)
|
||||||
{
|
{
|
||||||
|
@ -638,17 +647,23 @@ class D3D12ShaderPipeline : public IShaderPipeline
|
||||||
friend class D3D12DataFactory;
|
friend class D3D12DataFactory;
|
||||||
friend struct D3D12ShaderDataBinding;
|
friend struct D3D12ShaderDataBinding;
|
||||||
const D3D12VertexFormat* m_vtxFmt;
|
const D3D12VertexFormat* m_vtxFmt;
|
||||||
|
D3D12ShareableShader::Token m_vert;
|
||||||
|
D3D12ShareableShader::Token m_pixel;
|
||||||
|
|
||||||
D3D12ShaderPipeline(D3D12Context* ctx, ID3DBlob* vert, ID3DBlob* pixel, ID3DBlob* pipeline,
|
D3D12ShaderPipeline(D3D12Context* ctx, D3D12ShareableShader::Token&& vert,
|
||||||
|
D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline,
|
||||||
const D3D12VertexFormat* vtxFmt,
|
const D3D12VertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_vtxFmt(vtxFmt), m_topology(PRIMITIVE_TABLE[int(prim)])
|
: m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
|
||||||
|
m_topology(PRIMITIVE_TABLE[int(prim)])
|
||||||
{
|
{
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};
|
||||||
desc.pRootSignature = ctx->m_rs.Get();
|
desc.pRootSignature = ctx->m_rs.Get();
|
||||||
desc.VS = {vert->GetBufferPointer(), vert->GetBufferSize()};
|
const auto& vBlob = m_vert.get().m_shader;
|
||||||
desc.PS = {pixel->GetBufferPointer(), pixel->GetBufferSize()};
|
const auto& pBlob = m_pixel.get().m_shader;
|
||||||
|
desc.VS = {vBlob->GetBufferPointer(), vBlob->GetBufferSize()};
|
||||||
|
desc.PS = {pBlob->GetBufferPointer(), pBlob->GetBufferSize()};
|
||||||
desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
|
desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
|
||||||
if (dstFac != BlendFactor::Zero)
|
if (dstFac != BlendFactor::Zero)
|
||||||
{
|
{
|
||||||
|
@ -1532,6 +1547,8 @@ class D3D12DataFactory : public ID3DDataFactory
|
||||||
std::unordered_set<D3D12Data*> m_committedData;
|
std::unordered_set<D3D12Data*> m_committedData;
|
||||||
std::unordered_set<D3D12Pool*> m_committedPools;
|
std::unordered_set<D3D12Pool*> m_committedPools;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
|
std::unordered_map<uint64_t, std::unique_ptr<D3D12ShareableShader>> m_sharedShaders;
|
||||||
|
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||||
uint32_t m_sampleCount;
|
uint32_t m_sampleCount;
|
||||||
|
|
||||||
void destroyData(IGraphicsData* d)
|
void destroyData(IGraphicsData* d)
|
||||||
|
@ -1693,43 +1710,138 @@ public:
|
||||||
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint64_t CompileVert(ComPtr<ID3DBlob>& vertBlobOut, const char* vertSource, uint64_t srcKey,
|
||||||
|
D3D12DataFactory& factory)
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> errBlob;
|
||||||
|
if (FAILED(D3DCompilePROC(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main",
|
||||||
|
"vs_5_0", BOO_D3DCOMPILE_FLAG, 0, &vertBlobOut, &errBlob)))
|
||||||
|
{
|
||||||
|
printf("%s\n", vertSource);
|
||||||
|
Log.report(logvisor::Fatal, "error compiling vert shader: %s", errBlob->GetBufferPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, vertBlobOut->GetBufferPointer(), vertBlobOut->GetBufferSize());
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t CompileFrag(ComPtr<ID3DBlob>& fragBlobOut, const char* fragSource, uint64_t srcKey,
|
||||||
|
D3D12DataFactory& factory)
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> errBlob;
|
||||||
|
if (FAILED(D3DCompilePROC(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main",
|
||||||
|
"ps_5_0", BOO_D3DCOMPILE_FLAG, 0, &fragBlobOut, &errBlob)))
|
||||||
|
{
|
||||||
|
printf("%s\n", fragSource);
|
||||||
|
Log.report(logvisor::Fatal, "error compiling pixel shader: %s", errBlob->GetBufferPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, fragBlobOut->GetBufferPointer(), fragBlobOut->GetBufferSize());
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline
|
IShaderPipeline* newShaderPipeline
|
||||||
(const char* vertSource, const char* fragSource,
|
(const char* vertSource, const char* fragSource,
|
||||||
ComPtr<ID3DBlob>& vertBlobOut, ComPtr<ID3DBlob>& fragBlobOut,
|
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
|
||||||
ComPtr<ID3DBlob>& pipelineBlob, IVertexFormat* vtxFmt,
|
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
ComPtr<ID3DBlob> errBlob;
|
XXH64_state_t hashState;
|
||||||
|
uint64_t srcHashes[2] = {};
|
||||||
//printf("%s\n", vertSource);
|
uint64_t binHashes[2] = {};
|
||||||
//printf("%s\n", fragSource);
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (vertSource)
|
||||||
if (!vertBlobOut)
|
|
||||||
{
|
{
|
||||||
if (FAILED(D3DCompilePROC(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main",
|
XXH64_update(&hashState, vertSource, strlen(vertSource));
|
||||||
"vs_5_0", BOO_D3DCOMPILE_FLAG, 0, &vertBlobOut, &errBlob)))
|
srcHashes[0] = XXH64_digest(&hashState);
|
||||||
{
|
auto binSearch = m_parent.m_sourceToBinary.find(srcHashes[0]);
|
||||||
Log.report(logvisor::Fatal, "error compiling vert shader: %s", errBlob->GetBufferPointer());
|
if (binSearch != m_parent.m_sourceToBinary.cend())
|
||||||
return nullptr;
|
binHashes[0] = binSearch->second;
|
||||||
}
|
}
|
||||||
|
else if (vertBlobOut && *vertBlobOut)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, (*vertBlobOut)->GetBufferPointer(), (*vertBlobOut)->GetBufferSize());
|
||||||
|
binHashes[0] = XXH64_digest(&hashState);
|
||||||
|
}
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (fragSource)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, fragSource, strlen(fragSource));
|
||||||
|
srcHashes[1] = XXH64_digest(&hashState);
|
||||||
|
auto binSearch = m_parent.m_sourceToBinary.find(srcHashes[1]);
|
||||||
|
if (binSearch != m_parent.m_sourceToBinary.cend())
|
||||||
|
binHashes[1] = binSearch->second;
|
||||||
|
}
|
||||||
|
else if (fragBlobOut && *fragBlobOut)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, (*fragBlobOut)->GetBufferPointer(), (*fragBlobOut)->GetBufferSize());
|
||||||
|
binHashes[1] = XXH64_digest(&hashState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fragBlobOut)
|
if (vertBlobOut && !*vertBlobOut)
|
||||||
|
binHashes[0] = CompileVert(*vertBlobOut, vertSource, srcHashes[0], m_parent);
|
||||||
|
|
||||||
|
if (fragBlobOut && !*fragBlobOut)
|
||||||
|
binHashes[1] = CompileFrag(*fragBlobOut, fragSource, srcHashes[1], m_parent);
|
||||||
|
|
||||||
|
D3D12ShareableShader::Token vertShader;
|
||||||
|
D3D12ShareableShader::Token fragShader;
|
||||||
|
auto vertFind = binHashes[0] ? m_parent.m_sharedShaders.find(binHashes[0]) :
|
||||||
|
m_parent.m_sharedShaders.end();
|
||||||
|
if (vertFind != m_parent.m_sharedShaders.end())
|
||||||
{
|
{
|
||||||
if (FAILED(D3DCompilePROC(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main",
|
vertShader = vertFind->second->lock();
|
||||||
"ps_5_0", BOO_D3DCOMPILE_FLAG, 0, &fragBlobOut, &errBlob)))
|
}
|
||||||
{
|
else
|
||||||
Log.report(logvisor::Fatal, "error compiling pixel shader: %s", errBlob->GetBufferPointer());
|
{
|
||||||
return nullptr;
|
ComPtr<ID3DBlob> vertBlob;
|
||||||
}
|
if (vertBlobOut)
|
||||||
|
vertBlob = *vertBlobOut;
|
||||||
|
else
|
||||||
|
binHashes[0] = CompileVert(vertBlob, vertSource, srcHashes[0], m_parent);
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
m_parent.m_sharedShaders.emplace(std::make_pair(binHashes[0],
|
||||||
|
std::make_unique<D3D12ShareableShader>(m_parent, srcHashes[0], binHashes[0],
|
||||||
|
std::move(vertBlob)))).first;
|
||||||
|
vertShader = it->second->lock();
|
||||||
|
}
|
||||||
|
auto fragFind = binHashes[1] ? m_parent.m_sharedShaders.find(binHashes[1]) :
|
||||||
|
m_parent.m_sharedShaders.end();
|
||||||
|
if (fragFind != m_parent.m_sharedShaders.end())
|
||||||
|
{
|
||||||
|
fragShader = fragFind->second->lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> fragBlob;
|
||||||
|
if (fragBlobOut)
|
||||||
|
fragBlob = *fragBlobOut;
|
||||||
|
else
|
||||||
|
binHashes[1] = CompileFrag(fragBlob, fragSource, srcHashes[1], m_parent);
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
m_parent.m_sharedShaders.emplace(std::make_pair(binHashes[1],
|
||||||
|
std::make_unique<D3D12ShareableShader>(m_parent, srcHashes[0], binHashes[1],
|
||||||
|
std::move(fragBlob)))).first;
|
||||||
|
fragShader = it->second->lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, vertBlobOut.Get(), fragBlobOut.Get(), pipelineBlob.Get(),
|
ID3DBlob* pipeline = pipelineBlob ? pipelineBlob->Get() : nullptr;
|
||||||
static_cast<const D3D12VertexFormat*>(vtxFmt),
|
D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, std::move(vertShader), std::move(fragShader),
|
||||||
|
pipeline, static_cast<const D3D12VertexFormat*>(vtxFmt),
|
||||||
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
||||||
if (!pipelineBlob)
|
if (pipelineBlob && !*pipelineBlob)
|
||||||
retval->m_state->GetCachedBlob(&pipelineBlob);
|
retval->m_state->GetCachedBlob(&*pipelineBlob);
|
||||||
static_cast<D3D12Data*>(m_deferredData)->m_SPs.emplace_back(retval);
|
static_cast<D3D12Data*>(m_deferredData)->m_SPs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1877,6 +1989,13 @@ public:
|
||||||
m_committedPools.insert(retval);
|
m_committedPools.insert(retval);
|
||||||
return GraphicsBufferPoolToken(this, retval);
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey)
|
||||||
|
{
|
||||||
|
if (srcKey)
|
||||||
|
m_sourceToBinary.erase(srcKey);
|
||||||
|
m_sharedShaders.erase(binKey);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
thread_local D3D12Data* D3D12DataFactory::m_deferredData;
|
thread_local D3D12Data* D3D12DataFactory::m_deferredData;
|
||||||
|
|
|
@ -26,8 +26,8 @@ class GLDataFactoryImpl;
|
||||||
struct GLShareableShader : IShareableShader<GLDataFactoryImpl, GLShareableShader>
|
struct GLShareableShader : IShareableShader<GLDataFactoryImpl, GLShareableShader>
|
||||||
{
|
{
|
||||||
GLuint m_shader = 0;
|
GLuint m_shader = 0;
|
||||||
GLShareableShader(GLDataFactoryImpl& fac, uint64_t key, GLuint s)
|
GLShareableShader(GLDataFactoryImpl& fac, uint64_t srcKey, GLuint s)
|
||||||
: IShareableShader(fac, key), m_shader(s) {}
|
: IShareableShader(fac, srcKey, 0), m_shader(s) {}
|
||||||
~GLShareableShader() { glDeleteShader(m_shader); }
|
~GLShareableShader() { glDeleteShader(m_shader); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +58,10 @@ public:
|
||||||
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
||||||
GraphicsBufferPoolToken newBufferPool();
|
GraphicsBufferPoolToken newBufferPool();
|
||||||
|
|
||||||
void _unregisterShareableShader(uint64_t key) { m_sharedShaders.erase(key); }
|
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey)
|
||||||
|
{
|
||||||
|
m_sharedShaders.erase(srcKey);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData;
|
ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData;
|
||||||
|
@ -421,21 +424,8 @@ public:
|
||||||
~GLShaderPipeline() { glDeleteProgram(m_prog); }
|
~GLShaderPipeline() { glDeleteProgram(m_prog); }
|
||||||
GLShaderPipeline& operator=(const GLShaderPipeline&) = delete;
|
GLShaderPipeline& operator=(const GLShaderPipeline&) = delete;
|
||||||
GLShaderPipeline(const GLShaderPipeline&) = delete;
|
GLShaderPipeline(const GLShaderPipeline&) = delete;
|
||||||
GLShaderPipeline& operator=(GLShaderPipeline&& other)
|
GLShaderPipeline& operator=(GLShaderPipeline&& other) = default;
|
||||||
{
|
GLShaderPipeline(GLShaderPipeline&& other) = default;
|
||||||
m_vert = std::move(other.m_vert);
|
|
||||||
m_frag = std::move(other.m_frag);
|
|
||||||
m_prog = std::move(other.m_prog);
|
|
||||||
m_sfactor = other.m_sfactor;
|
|
||||||
m_dfactor = other.m_dfactor;
|
|
||||||
m_depthTest = other.m_depthTest;
|
|
||||||
m_depthWrite = other.m_depthWrite;
|
|
||||||
m_backfaceCulling = other.m_backfaceCulling;
|
|
||||||
m_uniLocs = std::move(other.m_uniLocs);
|
|
||||||
m_drawPrim = other.m_drawPrim;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
GLShaderPipeline(GLShaderPipeline&& other) {*this = std::move(other);}
|
|
||||||
|
|
||||||
GLuint bind() const
|
GLuint bind() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <SPIRV/disassemble.h>
|
#include <SPIRV/disassemble.h>
|
||||||
#include "boo/graphicsdev/GLSLMacros.hpp"
|
#include "boo/graphicsdev/GLSLMacros.hpp"
|
||||||
#include "Common.hpp"
|
#include "Common.hpp"
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
#include "logvisor/logvisor.hpp"
|
#include "logvisor/logvisor.hpp"
|
||||||
|
|
||||||
|
@ -20,6 +21,55 @@ namespace boo
|
||||||
{
|
{
|
||||||
static logvisor::Module Log("boo::Vulkan");
|
static logvisor::Module Log("boo::Vulkan");
|
||||||
VulkanContext g_VulkanContext;
|
VulkanContext g_VulkanContext;
|
||||||
|
class VulkanDataFactoryImpl;
|
||||||
|
|
||||||
|
struct VulkanShareableShader : IShareableShader<VulkanDataFactoryImpl, VulkanShareableShader>
|
||||||
|
{
|
||||||
|
VkDevice m_dev;
|
||||||
|
VkShaderModule m_shader;
|
||||||
|
VulkanShareableShader(VulkanDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey,
|
||||||
|
VkDevice dev, VkShaderModule s)
|
||||||
|
: IShareableShader(fac, srcKey, binKey), m_dev(dev), m_shader(s) {}
|
||||||
|
~VulkanShareableShader() { vk::DestroyShaderModule(m_dev, m_shader, nullptr); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class VulkanDataFactoryImpl : public VulkanDataFactory
|
||||||
|
{
|
||||||
|
friend struct VulkanCommandQueue;
|
||||||
|
friend class VulkanDataFactory::Context;
|
||||||
|
IGraphicsContext* m_parent;
|
||||||
|
VulkanContext* m_ctx;
|
||||||
|
uint32_t m_drawSamples;
|
||||||
|
static ThreadLocalPtr<struct VulkanData> m_deferredData;
|
||||||
|
std::unordered_set<struct VulkanData*> m_committedData;
|
||||||
|
std::unordered_set<struct VulkanPool*> m_committedPools;
|
||||||
|
std::mutex m_committedMutex;
|
||||||
|
std::unordered_map<uint64_t, std::unique_ptr<VulkanShareableShader>> m_sharedShaders;
|
||||||
|
std::vector<int> m_texUnis;
|
||||||
|
void destroyData(IGraphicsData*);
|
||||||
|
void destroyPool(IGraphicsBufferPool*);
|
||||||
|
void destroyAllData();
|
||||||
|
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool *pool, BufferUse use,
|
||||||
|
size_t stride, size_t count);
|
||||||
|
void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf);
|
||||||
|
public:
|
||||||
|
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||||
|
VulkanDataFactoryImpl(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples);
|
||||||
|
~VulkanDataFactoryImpl() {destroyAllData();}
|
||||||
|
|
||||||
|
Platform platform() const {return Platform::Vulkan;}
|
||||||
|
const SystemChar* platformName() const {return _S("Vulkan");}
|
||||||
|
|
||||||
|
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
|
||||||
|
GraphicsBufferPoolToken newBufferPool();
|
||||||
|
|
||||||
|
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey)
|
||||||
|
{
|
||||||
|
if (srcKey)
|
||||||
|
m_sourceToBinary.erase(srcKey);
|
||||||
|
m_sharedShaders.erase(binKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static inline void ThrowIfFailed(VkResult res)
|
static inline void ThrowIfFailed(VkResult res)
|
||||||
{
|
{
|
||||||
|
@ -809,6 +859,7 @@ public:
|
||||||
class VulkanGraphicsBufferD : public IGraphicsBufferD
|
class VulkanGraphicsBufferD : public IGraphicsBufferD
|
||||||
{
|
{
|
||||||
friend class VulkanDataFactory;
|
friend class VulkanDataFactory;
|
||||||
|
friend class VulkanDataFactoryImpl;
|
||||||
friend struct VulkanCommandQueue;
|
friend struct VulkanCommandQueue;
|
||||||
struct VulkanCommandQueue* m_q;
|
struct VulkanCommandQueue* m_q;
|
||||||
size_t m_cpuSz;
|
size_t m_cpuSz;
|
||||||
|
@ -1782,14 +1833,17 @@ class VulkanShaderPipeline : public IShaderPipeline
|
||||||
VulkanContext* m_ctx;
|
VulkanContext* m_ctx;
|
||||||
VkPipelineCache m_pipelineCache;
|
VkPipelineCache m_pipelineCache;
|
||||||
const VulkanVertexFormat* m_vtxFmt;
|
const VulkanVertexFormat* m_vtxFmt;
|
||||||
|
VulkanShareableShader::Token m_vert;
|
||||||
|
VulkanShareableShader::Token m_frag;
|
||||||
VulkanShaderPipeline(VulkanContext* ctx,
|
VulkanShaderPipeline(VulkanContext* ctx,
|
||||||
VkShaderModule vert,
|
VulkanShareableShader::Token&& vert,
|
||||||
VkShaderModule frag,
|
VulkanShareableShader::Token&& frag,
|
||||||
VkPipelineCache pipelineCache,
|
VkPipelineCache pipelineCache,
|
||||||
const VulkanVertexFormat* vtxFmt,
|
const VulkanVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
: m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt)
|
: m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt),
|
||||||
|
m_vert(std::move(vert)), m_frag(std::move(frag))
|
||||||
{
|
{
|
||||||
VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
|
||||||
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
VkPipelineDynamicStateCreateInfo dynamicState = {};
|
||||||
|
@ -1804,7 +1858,7 @@ class VulkanShaderPipeline : public IShaderPipeline
|
||||||
stages[0].pNext = nullptr;
|
stages[0].pNext = nullptr;
|
||||||
stages[0].flags = 0;
|
stages[0].flags = 0;
|
||||||
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
stages[0].module = vert;
|
stages[0].module = m_vert.get().m_shader;
|
||||||
stages[0].pName = "main";
|
stages[0].pName = "main";
|
||||||
stages[0].pSpecializationInfo = nullptr;
|
stages[0].pSpecializationInfo = nullptr;
|
||||||
|
|
||||||
|
@ -1812,7 +1866,7 @@ class VulkanShaderPipeline : public IShaderPipeline
|
||||||
stages[1].pNext = nullptr;
|
stages[1].pNext = nullptr;
|
||||||
stages[1].flags = 0;
|
stages[1].flags = 0;
|
||||||
stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
stages[1].module = frag;
|
stages[1].module = m_frag.get().m_shader;
|
||||||
stages[1].pName = "main";
|
stages[1].pName = "main";
|
||||||
stages[1].pSpecializationInfo = nullptr;
|
stages[1].pSpecializationInfo = nullptr;
|
||||||
|
|
||||||
|
@ -1905,7 +1959,8 @@ public:
|
||||||
~VulkanShaderPipeline()
|
~VulkanShaderPipeline()
|
||||||
{
|
{
|
||||||
vk::DestroyPipeline(m_ctx->m_dev, m_pipeline, nullptr);
|
vk::DestroyPipeline(m_ctx->m_dev, m_pipeline, nullptr);
|
||||||
vk::DestroyPipelineCache(m_ctx->m_dev, m_pipelineCache, nullptr);
|
if (m_pipelineCache)
|
||||||
|
vk::DestroyPipelineCache(m_ctx->m_dev, m_pipelineCache, nullptr);
|
||||||
}
|
}
|
||||||
VulkanShaderPipeline& operator=(const VulkanShaderPipeline&) = delete;
|
VulkanShaderPipeline& operator=(const VulkanShaderPipeline&) = delete;
|
||||||
VulkanShaderPipeline(const VulkanShaderPipeline&) = delete;
|
VulkanShaderPipeline(const VulkanShaderPipeline&) = delete;
|
||||||
|
@ -2847,19 +2902,19 @@ void VulkanTextureD::unmap()
|
||||||
m_validSlots = 0;
|
m_validSlots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDataFactory::destroyData(IGraphicsData* d)
|
void VulkanDataFactoryImpl::destroyData(IGraphicsData* d)
|
||||||
{
|
{
|
||||||
VulkanData* data = static_cast<VulkanData*>(d);
|
VulkanData* data = static_cast<VulkanData*>(d);
|
||||||
data->m_dead = true;
|
data->m_dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDataFactory::destroyPool(IGraphicsBufferPool* p)
|
void VulkanDataFactoryImpl::destroyPool(IGraphicsBufferPool* p)
|
||||||
{
|
{
|
||||||
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
||||||
pool->m_dead = true;
|
pool->m_dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDataFactory::destroyAllData()
|
void VulkanDataFactoryImpl::destroyAllData()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
for (VulkanData* data : m_committedData)
|
for (VulkanData* data : m_committedData)
|
||||||
|
@ -2870,7 +2925,8 @@ void VulkanDataFactory::destroyAllData()
|
||||||
m_committedPools.clear();
|
m_committedPools.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples)
|
VulkanDataFactoryImpl::VulkanDataFactoryImpl(IGraphicsContext* parent,
|
||||||
|
VulkanContext* ctx, uint32_t drawSamples)
|
||||||
: m_parent(parent), m_ctx(ctx), m_drawSamples(drawSamples)
|
: m_parent(parent), m_ctx(ctx), m_drawSamples(drawSamples)
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayoutBinding layoutBindings[BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT];
|
VkDescriptorSetLayoutBinding layoutBindings[BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT];
|
||||||
|
@ -2947,152 +3003,268 @@ VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ct
|
||||||
ThrowIfFailed(vk::CreateRenderPass(ctx->m_dev, &renderPass, nullptr, &ctx->m_pass));
|
ThrowIfFailed(vk::CreateRenderPass(ctx->m_dev, &renderPass, nullptr, &ctx->m_pass));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t CompileVert(std::vector<unsigned int>& out, const char* vertSource, uint64_t srcKey,
|
||||||
|
VulkanDataFactoryImpl& factory)
|
||||||
|
{
|
||||||
|
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
|
glslang::TShader vs(EShLangVertex);
|
||||||
|
vs.setStrings(&vertSource, 1);
|
||||||
|
if (!vs.parse(&glslang::DefaultTBuiltInResource, 110, false, messages))
|
||||||
|
{
|
||||||
|
printf("%s\n", vertSource);
|
||||||
|
Log.report(logvisor::Fatal, "unable to compile vertex shader\n%s", vs.getInfoLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
glslang::TProgram prog;
|
||||||
|
prog.addShader(&vs);
|
||||||
|
if (!prog.link(messages))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "unable to link shader program\n%s", prog.getInfoLog());
|
||||||
|
}
|
||||||
|
glslang::GlslangToSpv(*prog.getIntermediate(EShLangVertex), out);
|
||||||
|
//spv::Disassemble(std::cerr, out);
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, out.data(), out.size() * sizeof(unsigned int));
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t CompileFrag(std::vector<unsigned int>& out, const char* fragSource, uint64_t srcKey,
|
||||||
|
VulkanDataFactoryImpl& factory)
|
||||||
|
{
|
||||||
|
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
|
glslang::TShader fs(EShLangFragment);
|
||||||
|
fs.setStrings(&fragSource, 1);
|
||||||
|
if (!fs.parse(&glslang::DefaultTBuiltInResource, 110, false, messages))
|
||||||
|
{
|
||||||
|
printf("%s\n", fragSource);
|
||||||
|
Log.report(logvisor::Fatal, "unable to compile fragment shader\n%s", fs.getInfoLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
glslang::TProgram prog;
|
||||||
|
prog.addShader(&fs);
|
||||||
|
if (!prog.link(messages))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "unable to link shader program\n%s", prog.getInfoLog());
|
||||||
|
}
|
||||||
|
glslang::GlslangToSpv(*prog.getIntermediate(EShLangFragment), out);
|
||||||
|
//spv::Disassemble(std::cerr, out);
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
XXH64_update(&hashState, out.data(), out.size() * sizeof(unsigned int));
|
||||||
|
uint64_t binKey = XXH64_digest(&hashState);
|
||||||
|
factory.m_sourceToBinary[srcKey] = binKey;
|
||||||
|
return binKey;
|
||||||
|
}
|
||||||
|
|
||||||
IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
|
IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
|
||||||
(const char* vertSource, const char* fragSource,
|
(const char* vertSource, const char* fragSource,
|
||||||
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
|
||||||
std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt,
|
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
if (vertBlobOut.empty() || fragBlobOut.empty())
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
|
|
||||||
|
XXH64_state_t hashState;
|
||||||
|
uint64_t srcHashes[2] = {};
|
||||||
|
uint64_t binHashes[2] = {};
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (vertSource)
|
||||||
{
|
{
|
||||||
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
|
XXH64_update(&hashState, vertSource, strlen(vertSource));
|
||||||
|
srcHashes[0] = XXH64_digest(&hashState);
|
||||||
//printf("%s\n", vertSource);
|
auto binSearch = factory.m_sourceToBinary.find(srcHashes[0]);
|
||||||
//printf("%s\n", fragSource);
|
if (binSearch != factory.m_sourceToBinary.cend())
|
||||||
|
binHashes[0] = binSearch->second;
|
||||||
glslang::TShader vs(EShLangVertex);
|
|
||||||
vs.setStrings(&vertSource, 1);
|
|
||||||
if (!vs.parse(&glslang::DefaultTBuiltInResource, 110, false, messages))
|
|
||||||
{
|
|
||||||
printf("%s\n", vertSource);
|
|
||||||
Log.report(logvisor::Fatal, "unable to compile vertex shader\n%s", vs.getInfoLog());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang::TShader fs(EShLangFragment);
|
|
||||||
fs.setStrings(&fragSource, 1);
|
|
||||||
if (!fs.parse(&glslang::DefaultTBuiltInResource, 110, false, messages))
|
|
||||||
{
|
|
||||||
printf("%s\n", fragSource);
|
|
||||||
Log.report(logvisor::Fatal, "unable to compile fragment shader\n%s", fs.getInfoLog());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang::TProgram prog;
|
|
||||||
prog.addShader(&vs);
|
|
||||||
prog.addShader(&fs);
|
|
||||||
if (!prog.link(messages))
|
|
||||||
{
|
|
||||||
Log.report(logvisor::Fatal, "unable to link shader program\n%s", prog.getInfoLog());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (vertBlobOut.empty())
|
|
||||||
{
|
|
||||||
glslang::GlslangToSpv(*prog.getIntermediate(EShLangVertex), vertBlobOut);
|
|
||||||
//spv::Disassemble(std::cerr, vertBlobOut);
|
|
||||||
}
|
|
||||||
if (fragBlobOut.empty())
|
|
||||||
{
|
|
||||||
glslang::GlslangToSpv(*prog.getIntermediate(EShLangFragment), fragBlobOut);
|
|
||||||
//spv::Disassemble(std::cerr, fragBlobOut);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (vertBlobOut && vertBlobOut->size())
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, vertBlobOut->data(), vertBlobOut->size() * sizeof(unsigned int));
|
||||||
|
binHashes[0] = XXH64_digest(&hashState);
|
||||||
|
}
|
||||||
|
XXH64_reset(&hashState, 0);
|
||||||
|
if (fragSource)
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, fragSource, strlen(fragSource));
|
||||||
|
srcHashes[1] = XXH64_digest(&hashState);
|
||||||
|
auto binSearch = factory.m_sourceToBinary.find(srcHashes[1]);
|
||||||
|
if (binSearch != factory.m_sourceToBinary.cend())
|
||||||
|
binHashes[1] = binSearch->second;
|
||||||
|
}
|
||||||
|
else if (fragBlobOut && fragBlobOut->size())
|
||||||
|
{
|
||||||
|
XXH64_update(&hashState, fragBlobOut->data(), fragBlobOut->size() * sizeof(unsigned int));
|
||||||
|
binHashes[1] = XXH64_digest(&hashState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertBlobOut && vertBlobOut->empty())
|
||||||
|
binHashes[0] = CompileVert(*vertBlobOut, vertSource, srcHashes[0], factory);
|
||||||
|
|
||||||
|
if (fragBlobOut && fragBlobOut->empty())
|
||||||
|
binHashes[1] = CompileFrag(*fragBlobOut, fragSource, srcHashes[1], factory);
|
||||||
|
|
||||||
VkShaderModuleCreateInfo smCreateInfo = {};
|
VkShaderModuleCreateInfo smCreateInfo = {};
|
||||||
smCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
smCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
smCreateInfo.pNext = nullptr;
|
smCreateInfo.pNext = nullptr;
|
||||||
smCreateInfo.flags = 0;
|
smCreateInfo.flags = 0;
|
||||||
|
|
||||||
smCreateInfo.codeSize = vertBlobOut.size() * sizeof(unsigned int);
|
VulkanShareableShader::Token vertShader;
|
||||||
smCreateInfo.pCode = vertBlobOut.data();
|
VulkanShareableShader::Token fragShader;
|
||||||
VkShaderModule vertModule;
|
auto vertFind = binHashes[0] ? factory.m_sharedShaders.find(binHashes[0]) :
|
||||||
ThrowIfFailed(vk::CreateShaderModule(m_parent.m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule));
|
factory.m_sharedShaders.end();
|
||||||
|
if (vertFind != factory.m_sharedShaders.end())
|
||||||
|
{
|
||||||
|
vertShader = vertFind->second->lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<unsigned int> vertBlob;
|
||||||
|
const std::vector<unsigned int>* useVertBlob;
|
||||||
|
if (vertBlobOut)
|
||||||
|
{
|
||||||
|
useVertBlob = vertBlobOut;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useVertBlob = &vertBlob;
|
||||||
|
binHashes[0] = CompileVert(vertBlob, vertSource, srcHashes[0], factory);
|
||||||
|
}
|
||||||
|
|
||||||
smCreateInfo.codeSize = fragBlobOut.size() * sizeof(unsigned int);
|
smCreateInfo.codeSize = useVertBlob->size() * sizeof(unsigned int);
|
||||||
smCreateInfo.pCode = fragBlobOut.data();
|
smCreateInfo.pCode = useVertBlob->data();
|
||||||
VkShaderModule fragModule;
|
VkShaderModule vertModule;
|
||||||
ThrowIfFailed(vk::CreateShaderModule(m_parent.m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule));
|
ThrowIfFailed(vk::CreateShaderModule(factory.m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule));
|
||||||
|
|
||||||
VkPipelineCacheCreateInfo cacheDataInfo = {};
|
auto it =
|
||||||
cacheDataInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
factory.m_sharedShaders.emplace(std::make_pair(binHashes[0],
|
||||||
cacheDataInfo.pNext = nullptr;
|
std::make_unique<VulkanShareableShader>(factory, srcHashes[0], binHashes[0],
|
||||||
cacheDataInfo.initialDataSize = pipelineBlob.size();
|
factory.m_ctx->m_dev, vertModule))).first;
|
||||||
if (cacheDataInfo.initialDataSize)
|
vertShader = it->second->lock();
|
||||||
cacheDataInfo.pInitialData = pipelineBlob.data();
|
}
|
||||||
|
auto fragFind = binHashes[1] ? factory.m_sharedShaders.find(binHashes[1]) :
|
||||||
|
factory.m_sharedShaders.end();
|
||||||
|
if (fragFind != factory.m_sharedShaders.end())
|
||||||
|
{
|
||||||
|
fragShader = fragFind->second->lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<unsigned int> fragBlob;
|
||||||
|
const std::vector<unsigned int>* useFragBlob;
|
||||||
|
if (fragBlobOut)
|
||||||
|
{
|
||||||
|
useFragBlob = fragBlobOut;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useFragBlob = &fragBlob;
|
||||||
|
binHashes[1] = CompileFrag(fragBlob, fragSource, srcHashes[1], factory);
|
||||||
|
}
|
||||||
|
|
||||||
VkPipelineCache pipelineCache;
|
smCreateInfo.codeSize = useFragBlob->size() * sizeof(unsigned int);
|
||||||
ThrowIfFailed(vk::CreatePipelineCache(m_parent.m_ctx->m_dev, &cacheDataInfo, nullptr, &pipelineCache));
|
smCreateInfo.pCode = useFragBlob->data();
|
||||||
|
VkShaderModule fragModule;
|
||||||
|
ThrowIfFailed(vk::CreateShaderModule(factory.m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule));
|
||||||
|
|
||||||
VulkanShaderPipeline* retval = new VulkanShaderPipeline(m_parent.m_ctx, vertModule, fragModule, pipelineCache,
|
auto it =
|
||||||
static_cast<const VulkanVertexFormat*>(vtxFmt),
|
factory.m_sharedShaders.emplace(std::make_pair(binHashes[1],
|
||||||
|
std::make_unique<VulkanShareableShader>(factory, srcHashes[1], binHashes[1],
|
||||||
|
factory.m_ctx->m_dev, fragModule))).first;
|
||||||
|
fragShader = it->second->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkPipelineCache pipelineCache = VK_NULL_HANDLE;
|
||||||
|
if (pipelineBlob)
|
||||||
|
{
|
||||||
|
VkPipelineCacheCreateInfo cacheDataInfo = {};
|
||||||
|
cacheDataInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
||||||
|
cacheDataInfo.pNext = nullptr;
|
||||||
|
|
||||||
|
cacheDataInfo.initialDataSize = pipelineBlob->size();
|
||||||
|
if (cacheDataInfo.initialDataSize)
|
||||||
|
cacheDataInfo.pInitialData = pipelineBlob->data();
|
||||||
|
|
||||||
|
ThrowIfFailed(vk::CreatePipelineCache(factory.m_ctx->m_dev, &cacheDataInfo, nullptr, &pipelineCache));
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanShaderPipeline* retval = new VulkanShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader),
|
||||||
|
pipelineCache, static_cast<const VulkanVertexFormat*>(vtxFmt),
|
||||||
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
|
||||||
|
|
||||||
if (pipelineBlob.empty())
|
if (pipelineBlob && pipelineBlob->empty())
|
||||||
{
|
{
|
||||||
size_t cacheSz = 0;
|
size_t cacheSz = 0;
|
||||||
ThrowIfFailed(vk::GetPipelineCacheData(m_parent.m_ctx->m_dev, pipelineCache, &cacheSz, nullptr));
|
ThrowIfFailed(vk::GetPipelineCacheData(factory.m_ctx->m_dev, pipelineCache, &cacheSz, nullptr));
|
||||||
if (cacheSz)
|
if (cacheSz)
|
||||||
{
|
{
|
||||||
pipelineBlob.resize(cacheSz);
|
pipelineBlob->resize(cacheSz);
|
||||||
ThrowIfFailed(vk::GetPipelineCacheData(m_parent.m_ctx->m_dev, pipelineCache, &cacheSz, pipelineBlob.data()));
|
ThrowIfFailed(vk::GetPipelineCacheData(factory.m_ctx->m_dev, pipelineCache, &cacheSz, pipelineBlob->data()));
|
||||||
pipelineBlob.resize(cacheSz);
|
pipelineBlob->resize(cacheSz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DestroyShaderModule(m_parent.m_ctx->m_dev, fragModule, nullptr);
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_SPs.emplace_back(retval);
|
||||||
vk::DestroyShaderModule(m_parent.m_ctx->m_dev, vertModule, nullptr);
|
|
||||||
|
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_SPs.emplace_back(retval);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsBufferS* VulkanDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
|
IGraphicsBufferS* VulkanDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(use, m_parent.m_ctx, data, stride, count);
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_SBufs.emplace_back(retval);
|
VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(use, factory.m_ctx, data, stride, count);
|
||||||
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_SBufs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsBufferD* VulkanDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
|
IGraphicsBufferD* VulkanDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, m_parent.m_ctx, stride, count);
|
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(factory.m_parent->getCommandQueue());
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_DBufs.emplace_back(retval);
|
VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, factory.m_ctx, stride, count);
|
||||||
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_DBufs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITextureS* VulkanDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips,
|
ITextureS* VulkanDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips,
|
||||||
TextureFormat fmt, const void* data, size_t sz)
|
TextureFormat fmt, const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
VulkanTextureS* retval = new VulkanTextureS(m_parent.m_ctx, width, height, mips, fmt, data, sz);
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_STexs.emplace_back(retval);
|
VulkanTextureS* retval = new VulkanTextureS(factory.m_ctx, width, height, mips, fmt, data, sz);
|
||||||
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_STexs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
||||||
TextureFormat fmt, const void* data, size_t sz)
|
TextureFormat fmt, const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
VulkanTextureSA* retval = new VulkanTextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz);
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_SATexs.emplace_back(retval);
|
VulkanTextureSA* retval = new VulkanTextureSA(factory.m_ctx, width, height, layers, mips, fmt, data, sz);
|
||||||
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_SATexs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITextureD* VulkanDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
|
ITextureD* VulkanDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
|
||||||
{
|
{
|
||||||
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
VulkanTextureD* retval = new VulkanTextureD(q, m_parent.m_ctx, width, height, fmt);
|
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(factory.m_parent->getCommandQueue());
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_DTexs.emplace_back(retval);
|
VulkanTextureD* retval = new VulkanTextureD(q, factory.m_ctx, width, height, fmt);
|
||||||
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_DTexs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t height,
|
ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t height,
|
||||||
bool enableShaderColorBinding, bool enableShaderDepthBinding)
|
bool enableShaderColorBinding, bool enableShaderDepthBinding)
|
||||||
{
|
{
|
||||||
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
VulkanTextureR* retval = new VulkanTextureR(m_parent.m_ctx, q, width, height, m_parent.m_drawSamples,
|
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(factory.m_parent->getCommandQueue());
|
||||||
|
VulkanTextureR* retval = new VulkanTextureR(factory.m_ctx, q, width, height, factory.m_drawSamples,
|
||||||
enableShaderColorBinding, enableShaderDepthBinding);
|
enableShaderColorBinding, enableShaderDepthBinding);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_RTexs.emplace_back(retval);
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_RTexs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3101,7 +3273,7 @@ IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount,
|
||||||
size_t baseVert, size_t baseInst)
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements);
|
VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements);
|
||||||
static_cast<VulkanData*>(m_deferredData.get())->m_VFmts.emplace_back(retval);
|
static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get())->m_VFmts.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3113,16 +3285,17 @@ IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipe
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, ITexture** texs,
|
||||||
size_t baseVert, size_t baseInst)
|
size_t baseVert, size_t baseInst)
|
||||||
{
|
{
|
||||||
VulkanData* d = static_cast<VulkanData*>(m_deferredData.get());
|
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);
|
||||||
|
VulkanData* d = static_cast<VulkanData*>(VulkanDataFactoryImpl::m_deferredData.get());
|
||||||
VulkanShaderDataBinding* retval =
|
VulkanShaderDataBinding* retval =
|
||||||
new VulkanShaderDataBinding(d, m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
new VulkanShaderDataBinding(d, factory.m_ctx, pipeline, vbuf, instVbuf, ibuf,
|
||||||
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs,
|
ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs,
|
||||||
baseVert, baseInst);
|
baseVert, baseInst);
|
||||||
d->m_SBinds.emplace_back(retval);
|
d->m_SBinds.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsDataToken VulkanDataFactory::commitTransaction
|
GraphicsDataToken VulkanDataFactoryImpl::commitTransaction
|
||||||
(const std::function<bool(IGraphicsDataFactory::Context&)>& trans)
|
(const std::function<bool(IGraphicsDataFactory::Context&)>& trans)
|
||||||
{
|
{
|
||||||
if (m_deferredData.get())
|
if (m_deferredData.get())
|
||||||
|
@ -3245,8 +3418,8 @@ GraphicsDataToken VulkanDataFactory::commitTransaction
|
||||||
return GraphicsDataToken(this, retval);
|
return GraphicsDataToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsBufferD* VulkanDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
IGraphicsBufferD* VulkanDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
||||||
size_t stride, size_t count)
|
size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
||||||
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue());
|
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue());
|
||||||
|
@ -3277,7 +3450,7 @@ IGraphicsBufferD* VulkanDataFactory::newPoolBuffer(IGraphicsBufferPool* p, Buffe
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDataFactory::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)
|
void VulkanDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)
|
||||||
{
|
{
|
||||||
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
VulkanPool* pool = static_cast<VulkanPool*>(p);
|
||||||
auto search = pool->m_DBufs.find(static_cast<VulkanGraphicsBufferD*>(buf));
|
auto search = pool->m_DBufs.find(static_cast<VulkanGraphicsBufferD*>(buf));
|
||||||
|
@ -3285,7 +3458,7 @@ void VulkanDataFactory::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBuffer
|
||||||
search->second.m_dead = true;
|
search->second.m_dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsBufferPoolToken VulkanDataFactory::newBufferPool()
|
GraphicsBufferPoolToken VulkanDataFactoryImpl::newBufferPool()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
VulkanPool* retval = new VulkanPool(m_ctx);
|
VulkanPool* retval = new VulkanPool(m_ctx);
|
||||||
|
@ -3293,7 +3466,7 @@ GraphicsBufferPoolToken VulkanDataFactory::newBufferPool()
|
||||||
return GraphicsBufferPoolToken(this, retval);
|
return GraphicsBufferPoolToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadLocalPtr<struct VulkanData> VulkanDataFactory::m_deferredData;
|
ThreadLocalPtr<struct VulkanData> VulkanDataFactoryImpl::m_deferredData;
|
||||||
|
|
||||||
void VulkanCommandQueue::execute()
|
void VulkanCommandQueue::execute()
|
||||||
{
|
{
|
||||||
|
@ -3301,7 +3474,7 @@ void VulkanCommandQueue::execute()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Stage dynamic uploads */
|
/* Stage dynamic uploads */
|
||||||
VulkanDataFactory* gfxF = static_cast<VulkanDataFactory*>(m_parent->getDataFactory());
|
VulkanDataFactoryImpl* gfxF = static_cast<VulkanDataFactoryImpl*>(m_parent->getDataFactory());
|
||||||
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
||||||
for (VulkanData* d : gfxF->m_committedData)
|
for (VulkanData* d : gfxF->m_committedData)
|
||||||
{
|
{
|
||||||
|
@ -3452,5 +3625,10 @@ IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx, VulkanContext:
|
||||||
return new struct VulkanCommandQueue(ctx, windowCtx, parent);
|
return new struct VulkanCommandQueue(ctx, windowCtx, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IGraphicsDataFactory* _NewVulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx,
|
||||||
|
uint32_t drawSamples)
|
||||||
|
{
|
||||||
|
return new class VulkanDataFactoryImpl(parent, ctx, drawSamples);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,8 @@ IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawS
|
||||||
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
|
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
|
||||||
VulkanContext::Window* windowCtx,
|
VulkanContext::Window* windowCtx,
|
||||||
IGraphicsContext* parent);
|
IGraphicsContext* parent);
|
||||||
|
IGraphicsDataFactory* _NewVulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx,
|
||||||
|
uint32_t drawSamples);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct GraphicsContextWin32 : IGraphicsContext
|
struct GraphicsContextWin32 : IGraphicsContext
|
||||||
|
@ -597,7 +599,7 @@ public:
|
||||||
|
|
||||||
m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
||||||
|
|
||||||
m_dataFactory = new class VulkanDataFactory(this, m_ctx, m_sampleCount);
|
m_dataFactory = _NewVulkanDataFactory(this, m_ctx, m_sampleCount);
|
||||||
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,8 @@ IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawS
|
||||||
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
|
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
|
||||||
VulkanContext::Window* windowCtx,
|
VulkanContext::Window* windowCtx,
|
||||||
IGraphicsContext* parent);
|
IGraphicsContext* parent);
|
||||||
|
IGraphicsDataFactory* _NewVulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx,
|
||||||
|
uint32_t drawSamples);
|
||||||
#endif
|
#endif
|
||||||
void _XlibUpdateLastGlxCtx(GLXContext lastGlxCtx);
|
void _XlibUpdateLastGlxCtx(GLXContext lastGlxCtx);
|
||||||
void GLXExtensionCheck();
|
void GLXExtensionCheck();
|
||||||
|
@ -828,7 +830,7 @@ public:
|
||||||
});
|
});
|
||||||
initcv.wait(outerLk);
|
initcv.wait(outerLk);
|
||||||
|
|
||||||
m_dataFactory = new class VulkanDataFactory(this, m_ctx, m_drawSamples);
|
m_dataFactory = _NewVulkanDataFactory(Sthis, m_ctx, m_drawSamples);
|
||||||
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -369,10 +369,7 @@ struct TestApplicationCallback : IApplicationCallback
|
||||||
" return tex.Sample(samp, d.out_uv);\n"
|
" return tex.Sample(samp, d.out_uv);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
ComPtr<ID3DBlob> vsCompile;
|
pipeline = d3dF.newShaderPipeline(VS, PS, nullptr, nullptr, nullptr, vfmt,
|
||||||
ComPtr<ID3DBlob> psCompile;
|
|
||||||
ComPtr<ID3DBlob> cachedPipeline;
|
|
||||||
pipeline = d3dF.newShaderPipeline(VS, PS, vsCompile, psCompile, cachedPipeline, vfmt,
|
|
||||||
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
|
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
|
||||||
true, true, false);
|
true, true, false);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue