Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 60 additions & 63 deletions layers/vulkansc/state_tracker/sc_pipeline_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,59 +29,7 @@

namespace vvl::sc {

PipelineCache::PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache,
const VkPipelineCacheCreateInfo* pCreateInfo)
: vvl::PipelineCache(pipeline_cache, pCreateInfo), pipelines_() {
vvl::sc::PipelineCacheData pipeline_cache_data(*pCreateInfo);

for (uint32_t pipeline_index = 0; pipeline_index < pipeline_cache_data.PipelineIndexCount(); ++pipeline_index) {
auto cache_entry = pipeline_cache_data.PipelineIndexEntry(pipeline_index);
if (cache_entry) {
pipelines_.emplace(cache_entry.PipelineID(), Entry(state_data, cache_entry));
}
}
}

PipelineCache::Entry::StageModules PipelineCache::Entry::InitShaderModules(const DeviceState& state_data,
const PipelineCacheData::Entry& cache_entry) {
Entry::StageModules stage_modules;
stage_modules.reserve(cache_entry.StageIndexCount());

for (uint32_t stage_index = 0; stage_index < cache_entry.StageIndexCount(); ++stage_index) {
auto code = cache_entry.StageSPIRV(stage_index);

if (code.size() > 0) {
spirv::StatelessData stateless_data{};
auto spirv_module = vvl::CreateSpirvModuleState(code.size() * sizeof(uint32_t), code.data(), state_data.global_settings, &stateless_data);

if (stateless_data.has_group_decoration) {
// Run optimizer to flatten group decorations
spv_target_env spirv_environment = PickSpirvEnv(state_data.api_version, true);
spvtools::Optimizer optimizer(spirv_environment);
optimizer.RegisterPass(spvtools::CreateFlattenDecorationPass());
std::vector<uint32_t> optimized_binary;
auto result = optimizer.Run(spirv_module->words_.data(), spirv_module->words_.size(), &optimized_binary,
spvtools::ValidatorOptions(), true);
if (result) {
spirv_module = std::make_shared<spirv::Module>(optimized_binary);
}
}

// We use the SPIR-V module pointer as the internal shader module handle
auto handle = (VkShaderModule)spirv_module.get();
auto module_state = std::make_shared<vvl::ShaderModule>(handle, spirv_module);

stage_modules.emplace_back(std::move(module_state));
} else {
stage_modules.emplace_back(nullptr);
}
}
return stage_modules;
}

PipelineCache::Entry::JsonData PipelineCache::Entry::ParseJsonData(const PipelineCacheData::Entry& cache_entry) {
PipelineCache::Entry::JsonData data{};

PipelineJsonData::PipelineJsonData(const PipelineCacheData::Entry& cache_entry) {
auto parse_entrypoint_name = [](const Json::Value& entrypoint_name) -> std::string {
if (entrypoint_name.isString()) {
auto result = entrypoint_name.asString();
Expand Down Expand Up @@ -145,31 +93,80 @@ PipelineCache::Entry::JsonData PipelineCache::Entry::ParseJsonData(const Pipelin
std::istringstream json_stream(json_string);
std::string json_errors{};
Json::CharReaderBuilder builder{};
bool parse_ok = Json::parseFromStream(builder, json_stream, &data.json, &json_errors);
bool parse_ok = Json::parseFromStream(builder, json_stream, &this->json, &json_errors);
if (parse_ok) {
auto graphics_pipe_state = data.json["GraphicsPipelineState"];
auto graphics_pipe_state = this->json["GraphicsPipelineState"];
if (graphics_pipe_state != Json::nullValue) {
auto stages = graphics_pipe_state["GraphicsPipeline"]["pStages"];
uint32_t stage_count = graphics_pipe_state["GraphicsPipeline"]["stageCount"].asUInt();
data.entrypoint_name.reserve(stage_count);
data.specialization_info.reserve(stage_count);
this->entrypoint_name.reserve(stage_count);
this->specialization_info.reserve(stage_count);
for (uint32_t stage_index = 0; stage_index < stage_count; ++stage_index) {
auto stage = stages[stage_index];
data.entrypoint_name.push_back(parse_entrypoint_name(stage["pName"]));
data.specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"]));
this->entrypoint_name.push_back(parse_entrypoint_name(stage["pName"]));
this->specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"]));
}
}

auto compute_pipe_state = data.json["ComputePipelineState"];
auto compute_pipe_state = this->json["ComputePipelineState"];
if (compute_pipe_state != Json::nullValue) {
auto stage = compute_pipe_state["ComputePipeline"]["stage"];
data.entrypoint_name.push_back(parse_entrypoint_name(stage["pName"]));
data.specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"]));
this->entrypoint_name.push_back(parse_entrypoint_name(stage["pName"]));
this->specialization_info.push_back(parse_spec_info(stage["pSpecializationInfo"]));
}
}
}
}

PipelineCache::PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache,
const VkPipelineCacheCreateInfo* pCreateInfo)
: vvl::PipelineCache(pipeline_cache, pCreateInfo), pipelines_() {
vvl::sc::PipelineCacheData pipeline_cache_data(*pCreateInfo);

return data;
for (uint32_t pipeline_index = 0; pipeline_index < pipeline_cache_data.PipelineIndexCount(); ++pipeline_index) {
auto cache_entry = pipeline_cache_data.PipelineIndexEntry(pipeline_index);
if (cache_entry) {
pipelines_.emplace(cache_entry.PipelineID(), Entry(state_data, cache_entry));
}
}
}

PipelineCache::Entry::StageModules PipelineCache::Entry::InitShaderModules(const DeviceState& state_data,
const PipelineCacheData::Entry& cache_entry) {
Entry::StageModules stage_modules;
stage_modules.reserve(cache_entry.StageIndexCount());

for (uint32_t stage_index = 0; stage_index < cache_entry.StageIndexCount(); ++stage_index) {
auto code = cache_entry.StageSPIRV(stage_index);

if (code.size() > 0) {
spirv::StatelessData stateless_data{};
auto spirv_module = vvl::CreateSpirvModuleState(code.size() * sizeof(uint32_t), code.data(), state_data.global_settings,
&stateless_data);

if (stateless_data.has_group_decoration) {
// Run optimizer to flatten group decorations
spv_target_env spirv_environment = PickSpirvEnv(state_data.api_version, true);
spvtools::Optimizer optimizer(spirv_environment);
optimizer.RegisterPass(spvtools::CreateFlattenDecorationPass());
std::vector<uint32_t> optimized_binary;
auto result = optimizer.Run(spirv_module->words_.data(), spirv_module->words_.size(), &optimized_binary,
spvtools::ValidatorOptions(), true);
if (result) {
spirv_module = std::make_shared<spirv::Module>(optimized_binary);
}
}

// We use the SPIR-V module pointer as the internal shader module handle
auto handle = (VkShaderModule)spirv_module.get();
auto module_state = std::make_shared<vvl::ShaderModule>(handle, spirv_module);

stage_modules.emplace_back(std::move(module_state));
} else {
stage_modules.emplace_back(nullptr);
}
}
return stage_modules;
}

} // namespace vvl::sc
21 changes: 10 additions & 11 deletions layers/vulkansc/state_tracker/sc_pipeline_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ class PipelineCacheData {
}
};

struct PipelineJsonData {
Json::Value json{};
std::vector<std::string> entrypoint_name{};
std::vector<std::unique_ptr<vku::safe_VkSpecializationInfo>> specialization_info{};

PipelineJsonData(const PipelineCacheData::Entry& cache_entry);
};

class PipelineCache : public vvl::PipelineCache {
public:
class Entry {
Expand All @@ -169,9 +177,7 @@ class PipelineCache : public vvl::PipelineCache {
using StageModules = std::vector<std::shared_ptr<vvl::ShaderModule>>;

Entry(const DeviceState& state_data, const PipelineCacheData::Entry& cache_entry)
: id_(cache_entry.PipelineID()),
shader_modules_(InitShaderModules(state_data, cache_entry)),
json_data_(ParseJsonData(cache_entry)) {}
: id_(cache_entry.PipelineID()), shader_modules_(InitShaderModules(state_data, cache_entry)), json_data_(cache_entry) {}

ID PipelineID() const { return id_; }

Expand Down Expand Up @@ -200,18 +206,11 @@ class PipelineCache : public vvl::PipelineCache {
}

private:
struct JsonData {
Json::Value json{};
std::vector<std::string> entrypoint_name{};
std::vector<std::unique_ptr<vku::safe_VkSpecializationInfo>> specialization_info{};
};

StageModules InitShaderModules(const DeviceState& state_data, const PipelineCacheData::Entry& cache_entry);
JsonData ParseJsonData(const PipelineCacheData::Entry& cache_entry);

ID id_;
const StageModules shader_modules_;
JsonData json_data_;
PipelineJsonData json_data_;
};

PipelineCache(const DeviceState& state_data, VkPipelineCache pipeline_cache, const VkPipelineCacheCreateInfo* pCreateInfo);
Expand Down
10 changes: 9 additions & 1 deletion scripts/vksc_convert_tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,15 @@
]
},
{
"reason": "TODO: These tests fail due to some SPIR-V Tools bugs and do not happen to show up upstream as they do spec constant folding and other optimizations on SPIR-V before validation, unlike our device-create-time SPIR-V validation",
"reason": "TODO: These tests fail due to a combination of glslang and SPIR-V Tools bugs",
"details": [
"The two bugs that cause this are as follows:",
" - glslang incorrectly generates the InputAttachmentArrayDynamicIndexing cap into the SPIR-V",
" - spirv-val claims that InputAttachmentArrayDynamicIndexing is not supported in Vulkan 1.2 (which it is)",
"This does not happen upstream because the shader is built with the Vulkan 1.0 SPIR-V environment not, Vulkan 1.2, therefore:",
" - glslang does not generate the InputAttachmentArrayDynamicIndexing into the SPIR-V because it does not exist in that version",
" - hence spirv-val does not complain"
],
"cases": [
"NegativeSubpass.InputAttachmentMissingSpecConstant",
"PositiveSubpass.InputAttachmentMissingSpecConstant"
Expand Down