Update SPIRV caching to use SkWriter32/SkReader32 and allow inspection
Change-Id: I6656d971c05f0ed3515f095ffcd41ae73a5c483f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206687 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
c328be8947
commit
a5a010b8cd
@ -14,7 +14,9 @@
|
|||||||
#include "SkSLString.h"
|
#include "SkSLString.h"
|
||||||
#include "SkWriter32.h"
|
#include "SkWriter32.h"
|
||||||
|
|
||||||
// Pack/unpack functions, to be shared by backend and debugging utils?
|
// The GrPersistentCache stores opaque blobs, as far as clients are concerned. It's helpful to
|
||||||
|
// inspect certain kinds of cached data within our tools, so for those cases (GLSL, SPIR-V), we
|
||||||
|
// put the serialization logic here, to be shared by the backend code and the tool code.
|
||||||
namespace GrPersistentCacheUtils {
|
namespace GrPersistentCacheUtils {
|
||||||
|
|
||||||
static inline void PackCachedGLSL(SkWriter32& writer, const SkSL::Program::Inputs& inputs,
|
static inline void PackCachedGLSL(SkWriter32& writer, const SkSL::Program::Inputs& inputs,
|
||||||
@ -35,6 +37,24 @@ static inline void UnpackCachedGLSL(SkReader32& reader, SkSL::Program::Inputs* i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void PackCachedSPIRV(SkWriter32& writer, const SkSL::String shaders[],
|
||||||
|
const SkSL::Program::Inputs inputs[]) {
|
||||||
|
for (int i = 0; i < kGrShaderTypeCount; ++i) {
|
||||||
|
writer.writeString(shaders[i].c_str(), shaders[i].size());
|
||||||
|
writer.writePad(&inputs[i], sizeof(inputs[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void UnpackCachedSPIRV(SkReader32& reader, SkSL::String shaders[],
|
||||||
|
SkSL::Program::Inputs inputs[]) {
|
||||||
|
for (int i = 0; i < kGrShaderTypeCount; ++i) {
|
||||||
|
size_t stringLen = 0;
|
||||||
|
const char* string = reader.readString(&stringLen);
|
||||||
|
shaders[i] = SkSL::String(string, stringLen);
|
||||||
|
reader.read(&inputs[i], sizeof(inputs[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "vk/GrVkPipelineStateBuilder.h"
|
#include "vk/GrVkPipelineStateBuilder.h"
|
||||||
#include "GrContext.h"
|
#include "GrContext.h"
|
||||||
#include "GrContextPriv.h"
|
#include "GrContextPriv.h"
|
||||||
|
#include "GrPersistentCacheUtils.h"
|
||||||
#include "GrShaderCaps.h"
|
#include "GrShaderCaps.h"
|
||||||
#include "GrStencilSettings.h"
|
#include "GrStencilSettings.h"
|
||||||
#include "GrVkRenderTarget.h"
|
#include "GrVkRenderTarget.h"
|
||||||
@ -113,118 +114,47 @@ int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
|
|||||||
VkShaderModule* outFragShaderModule,
|
VkShaderModule* outFragShaderModule,
|
||||||
VkShaderModule* outGeomShaderModule,
|
VkShaderModule* outGeomShaderModule,
|
||||||
VkPipelineShaderStageCreateInfo* outStageInfo) {
|
VkPipelineShaderStageCreateInfo* outStageInfo) {
|
||||||
// format for shader cache entries is:
|
SkSL::String shaders[kGrShaderTypeCount];
|
||||||
// shader_size vertSize;
|
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
|
||||||
// char[vertSize] vert;
|
|
||||||
// SkSL::Program::Inputs vertInputs;
|
|
||||||
// shader_size fragSize;
|
|
||||||
// char[fragSize] frag;
|
|
||||||
// SkSL::Program::Inputs fragInputs;
|
|
||||||
// shader_size geomSize;
|
|
||||||
// char[geomSize] geom;
|
|
||||||
// SkSL::Program::Inputs geomInputs;
|
|
||||||
size_t offset = 0;
|
|
||||||
|
|
||||||
// vertex shader
|
SkReader32 reader(cached.data(), cached.size());
|
||||||
shader_size vertSize = *((shader_size*) ((char*) cached.data() + offset));
|
GrPersistentCacheUtils::UnpackCachedSPIRV(reader, shaders, inputs);
|
||||||
offset += sizeof(shader_size);
|
|
||||||
SkSL::String vert((char*) cached.data() + offset, vertSize);
|
|
||||||
offset += vertSize;
|
|
||||||
SkSL::Program::Inputs vertInputs;
|
|
||||||
memcpy(&vertInputs, (char*) cached.data() + offset, sizeof(vertInputs));
|
|
||||||
offset += sizeof(vertInputs);
|
|
||||||
|
|
||||||
// fragment shader
|
|
||||||
shader_size fragSize = *((shader_size*) ((char*) cached.data() + offset));
|
|
||||||
offset += sizeof(shader_size);
|
|
||||||
SkSL::String frag((char*) cached.data() + offset, fragSize);
|
|
||||||
offset += fragSize;
|
|
||||||
SkSL::Program::Inputs fragInputs;
|
|
||||||
memcpy(&fragInputs, (char*) cached.data() + offset, sizeof(fragInputs));
|
|
||||||
offset += sizeof(fragInputs);
|
|
||||||
|
|
||||||
// geometry shader
|
|
||||||
shader_size geomSize = *((shader_size*) ((char*) cached.data() + offset));
|
|
||||||
offset += sizeof(shader_size);
|
|
||||||
SkSL::String geom((char*) cached.data() + offset, geomSize);
|
|
||||||
offset += geomSize;
|
|
||||||
SkSL::Program::Inputs geomInputs;
|
|
||||||
memcpy(&geomInputs, (char*) cached.data() + offset, sizeof(geomInputs));
|
|
||||||
offset += sizeof(geomInputs);
|
|
||||||
|
|
||||||
SkASSERT(offset == cached.size());
|
|
||||||
|
|
||||||
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
|
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
fVS,
|
fVS,
|
||||||
outVertShaderModule,
|
outVertShaderModule,
|
||||||
&outStageInfo[0],
|
&outStageInfo[0],
|
||||||
vert,
|
shaders[kVertex_GrShaderType],
|
||||||
vertInputs));
|
inputs[kVertex_GrShaderType]));
|
||||||
|
|
||||||
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
|
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
fFS,
|
fFS,
|
||||||
outFragShaderModule,
|
outFragShaderModule,
|
||||||
&outStageInfo[1],
|
&outStageInfo[1],
|
||||||
frag,
|
shaders[kFragment_GrShaderType],
|
||||||
fragInputs));
|
inputs[kFragment_GrShaderType]));
|
||||||
|
|
||||||
if (geomSize) {
|
if (!shaders[kGeometry_GrShaderType].empty()) {
|
||||||
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
|
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
fGS,
|
fGS,
|
||||||
outGeomShaderModule,
|
outGeomShaderModule,
|
||||||
&outStageInfo[2],
|
&outStageInfo[2],
|
||||||
geom,
|
shaders[kGeometry_GrShaderType],
|
||||||
geomInputs));
|
inputs[kGeometry_GrShaderType]));
|
||||||
return 3;
|
return 3;
|
||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String& vert,
|
void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
|
||||||
const SkSL::Program::Inputs& vertInputs,
|
const SkSL::Program::Inputs inputs[]) {
|
||||||
const SkSL::String& frag,
|
|
||||||
const SkSL::Program::Inputs& fragInputs,
|
|
||||||
const SkSL::String& geom,
|
|
||||||
const SkSL::Program::Inputs& geomInputs) {
|
|
||||||
Desc* desc = static_cast<Desc*>(this->desc());
|
Desc* desc = static_cast<Desc*>(this->desc());
|
||||||
|
|
||||||
// see loadShadersFromCache for the layout of cache entries
|
|
||||||
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
|
sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
|
||||||
size_t dataLength = (sizeof(shader_size) + sizeof(SkSL::Program::Inputs)) * 3 + vert.length() +
|
SkWriter32 writer;
|
||||||
frag.length() + geom.length();
|
GrPersistentCacheUtils::PackCachedSPIRV(writer, shaders, inputs);
|
||||||
std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
|
auto data = writer.snapshotAsData();
|
||||||
size_t offset = 0;
|
this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
|
||||||
|
|
||||||
// vertex shader
|
|
||||||
*((shader_size*) (data.get() + offset)) = (shader_size) vert.length();
|
|
||||||
offset += sizeof(shader_size);
|
|
||||||
memcpy(data.get() + offset, vert.data(), vert.length());
|
|
||||||
offset += vert.length();
|
|
||||||
memcpy(data.get() + offset, &vertInputs, sizeof(vertInputs));
|
|
||||||
offset += sizeof(vertInputs);
|
|
||||||
|
|
||||||
// fragment shader
|
|
||||||
*((shader_size*) (data.get() + offset)) = (shader_size) frag.length();
|
|
||||||
offset += sizeof(shader_size);
|
|
||||||
memcpy(data.get() + offset, frag.data(), frag.length());
|
|
||||||
offset += frag.length();
|
|
||||||
memcpy(data.get() + offset, &fragInputs, sizeof(fragInputs));
|
|
||||||
offset += sizeof(fragInputs);
|
|
||||||
|
|
||||||
// geometry shader
|
|
||||||
*((shader_size*) (data.get() + offset)) = (shader_size) geom.length();
|
|
||||||
offset += sizeof(shader_size);
|
|
||||||
memcpy(data.get() + offset, geom.data(), geom.length());
|
|
||||||
offset += geom.length();
|
|
||||||
memcpy(data.get() + offset, &geomInputs, sizeof(geomInputs));
|
|
||||||
offset += sizeof(geomInputs);
|
|
||||||
|
|
||||||
SkASSERT(offset == dataLength);
|
|
||||||
|
|
||||||
this->gpu()->getContext()->priv().getPersistentCache()->store(
|
|
||||||
*key,
|
|
||||||
*SkData::MakeWithoutCopy(data.get(), dataLength));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
|
GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
|
||||||
@ -292,20 +222,16 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
|||||||
&geomShaderModule, shaderStageInfo);
|
&geomShaderModule, shaderStageInfo);
|
||||||
} else {
|
} else {
|
||||||
numShaderStages = 2; // We always have at least vertex and fragment stages.
|
numShaderStages = 2; // We always have at least vertex and fragment stages.
|
||||||
SkSL::String vert;
|
SkSL::String shaders[kGrShaderTypeCount];
|
||||||
SkSL::Program::Inputs vertInputs;
|
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
|
||||||
SkSL::String frag;
|
|
||||||
SkSL::Program::Inputs fragInputs;
|
|
||||||
SkSL::String geom;
|
|
||||||
SkSL::Program::Inputs geomInputs;
|
|
||||||
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
|
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
fVS,
|
fVS,
|
||||||
&vertShaderModule,
|
&vertShaderModule,
|
||||||
&shaderStageInfo[0],
|
&shaderStageInfo[0],
|
||||||
settings,
|
settings,
|
||||||
desc,
|
desc,
|
||||||
&vert,
|
&shaders[kVertex_GrShaderType],
|
||||||
&vertInputs));
|
&inputs[kVertex_GrShaderType]));
|
||||||
|
|
||||||
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
|
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
fFS,
|
fFS,
|
||||||
@ -313,8 +239,8 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
|||||||
&shaderStageInfo[1],
|
&shaderStageInfo[1],
|
||||||
settings,
|
settings,
|
||||||
desc,
|
desc,
|
||||||
&frag,
|
&shaders[kFragment_GrShaderType],
|
||||||
&fragInputs));
|
&inputs[kFragment_GrShaderType]));
|
||||||
|
|
||||||
if (this->primitiveProcessor().willUseGeoShader()) {
|
if (this->primitiveProcessor().willUseGeoShader()) {
|
||||||
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
|
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
@ -323,12 +249,12 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
|
|||||||
&shaderStageInfo[2],
|
&shaderStageInfo[2],
|
||||||
settings,
|
settings,
|
||||||
desc,
|
desc,
|
||||||
&geom,
|
&shaders[kGeometry_GrShaderType],
|
||||||
&geomInputs));
|
&inputs[kGeometry_GrShaderType]));
|
||||||
++numShaderStages;
|
++numShaderStages;
|
||||||
}
|
}
|
||||||
if (persistentCache) {
|
if (persistentCache) {
|
||||||
this->storeShadersInCache(vert, vertInputs, frag, fragInputs, geom, geomInputs);
|
this->storeShadersInCache(shaders, inputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GrVkPipeline* pipeline = resourceProvider.createPipeline(
|
GrVkPipeline* pipeline = resourceProvider.createPipeline(
|
||||||
|
@ -97,12 +97,7 @@ private:
|
|||||||
VkShaderModule* outGeomShaderModule,
|
VkShaderModule* outGeomShaderModule,
|
||||||
VkPipelineShaderStageCreateInfo* outStageInfo);
|
VkPipelineShaderStageCreateInfo* outStageInfo);
|
||||||
|
|
||||||
void storeShadersInCache(const SkSL::String& vert,
|
void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[]);
|
||||||
const SkSL::Program::Inputs& vertInputs,
|
|
||||||
const SkSL::String& frag,
|
|
||||||
const SkSL::Program::Inputs& fragInputs,
|
|
||||||
const SkSL::String& geom,
|
|
||||||
const SkSL::Program::Inputs& geomInputs);
|
|
||||||
|
|
||||||
bool createVkShaderModule(VkShaderStageFlagBits stage,
|
bool createVkShaderModule(VkShaderStageFlagBits stage,
|
||||||
const GrGLSLShaderBuilder& builder,
|
const GrGLSLShaderBuilder& builder,
|
||||||
|
Loading…
Reference in New Issue
Block a user