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:
Brian Osman 2019-04-08 15:01:32 -04:00 committed by Skia Commit-Bot
parent c328be8947
commit a5a010b8cd
3 changed files with 49 additions and 108 deletions

View File

@ -14,7 +14,9 @@
#include "SkSLString.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 {
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

View File

@ -8,6 +8,7 @@
#include "vk/GrVkPipelineStateBuilder.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrPersistentCacheUtils.h"
#include "GrShaderCaps.h"
#include "GrStencilSettings.h"
#include "GrVkRenderTarget.h"
@ -113,118 +114,47 @@ int GrVkPipelineStateBuilder::loadShadersFromCache(const SkData& cached,
VkShaderModule* outFragShaderModule,
VkShaderModule* outGeomShaderModule,
VkPipelineShaderStageCreateInfo* outStageInfo) {
// format for shader cache entries is:
// shader_size vertSize;
// 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;
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
// vertex shader
shader_size vertSize = *((shader_size*) ((char*) cached.data() + offset));
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());
SkReader32 reader(cached.data(), cached.size());
GrPersistentCacheUtils::UnpackCachedSPIRV(reader, shaders, inputs);
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
fVS,
outVertShaderModule,
&outStageInfo[0],
vert,
vertInputs));
shaders[kVertex_GrShaderType],
inputs[kVertex_GrShaderType]));
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
fFS,
outFragShaderModule,
&outStageInfo[1],
frag,
fragInputs));
shaders[kFragment_GrShaderType],
inputs[kFragment_GrShaderType]));
if (geomSize) {
if (!shaders[kGeometry_GrShaderType].empty()) {
SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
fGS,
outGeomShaderModule,
&outStageInfo[2],
geom,
geomInputs));
shaders[kGeometry_GrShaderType],
inputs[kGeometry_GrShaderType]));
return 3;
} else {
return 2;
}
}
void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String& vert,
const SkSL::Program::Inputs& vertInputs,
const SkSL::String& frag,
const SkSL::Program::Inputs& fragInputs,
const SkSL::String& geom,
const SkSL::Program::Inputs& geomInputs) {
void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
const SkSL::Program::Inputs inputs[]) {
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());
size_t dataLength = (sizeof(shader_size) + sizeof(SkSL::Program::Inputs)) * 3 + vert.length() +
frag.length() + geom.length();
std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
size_t offset = 0;
// 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));
SkWriter32 writer;
GrPersistentCacheUtils::PackCachedSPIRV(writer, shaders, inputs);
auto data = writer.snapshotAsData();
this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
}
GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
@ -292,20 +222,16 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
&geomShaderModule, shaderStageInfo);
} else {
numShaderStages = 2; // We always have at least vertex and fragment stages.
SkSL::String vert;
SkSL::Program::Inputs vertInputs;
SkSL::String frag;
SkSL::Program::Inputs fragInputs;
SkSL::String geom;
SkSL::Program::Inputs geomInputs;
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
fVS,
&vertShaderModule,
&shaderStageInfo[0],
settings,
desc,
&vert,
&vertInputs));
&shaders[kVertex_GrShaderType],
&inputs[kVertex_GrShaderType]));
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
fFS,
@ -313,8 +239,8 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
&shaderStageInfo[1],
settings,
desc,
&frag,
&fragInputs));
&shaders[kFragment_GrShaderType],
&inputs[kFragment_GrShaderType]));
if (this->primitiveProcessor().willUseGeoShader()) {
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
@ -323,12 +249,12 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
&shaderStageInfo[2],
settings,
desc,
&geom,
&geomInputs));
&shaders[kGeometry_GrShaderType],
&inputs[kGeometry_GrShaderType]));
++numShaderStages;
}
if (persistentCache) {
this->storeShadersInCache(vert, vertInputs, frag, fragInputs, geom, geomInputs);
this->storeShadersInCache(shaders, inputs);
}
}
GrVkPipeline* pipeline = resourceProvider.createPipeline(

View File

@ -97,12 +97,7 @@ private:
VkShaderModule* outGeomShaderModule,
VkPipelineShaderStageCreateInfo* outStageInfo);
void storeShadersInCache(const SkSL::String& vert,
const SkSL::Program::Inputs& vertInputs,
const SkSL::String& frag,
const SkSL::Program::Inputs& fragInputs,
const SkSL::String& geom,
const SkSL::Program::Inputs& geomInputs);
void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[]);
bool createVkShaderModule(VkShaderStageFlagBits stage,
const GrGLSLShaderBuilder& builder,