Files
face_sdk/vulkan/framework/resource_replay.cpp
T

206 lines
6.1 KiB
C++

/* Copyright (c) 2019-2025, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "resource_replay.h"
#include "common/vk_common.h"
#include "core/util/logging.hpp"
#include "rendering/pipeline_state.h"
#include "resource_cache.h"
namespace vkb
{
namespace
{
inline void read_subpass_info(std::istringstream &is, std::vector<SubpassInfo> &value)
{
std::size_t size;
read(is, size);
value.resize(size);
for (SubpassInfo &subpass : value)
{
read(is, subpass.input_attachments);
read(is, subpass.output_attachments);
}
}
} // namespace
ResourceReplay::ResourceReplay()
{
stream_resources[ResourceType::ShaderModule] = std::bind(&ResourceReplay::create_shader_module, this, std::placeholders::_1, std::placeholders::_2);
stream_resources[ResourceType::PipelineLayout] = std::bind(&ResourceReplay::create_pipeline_layout, this, std::placeholders::_1, std::placeholders::_2);
stream_resources[ResourceType::RenderPass] = std::bind(&ResourceReplay::create_render_pass, this, std::placeholders::_1, std::placeholders::_2);
stream_resources[ResourceType::GraphicsPipeline] = std::bind(&ResourceReplay::create_graphics_pipeline, this, std::placeholders::_1, std::placeholders::_2);
}
void ResourceReplay::play(ResourceCache &resource_cache, ResourceRecord &recorder)
{
std::istringstream stream{recorder.get_stream().str()};
while (true)
{
// Read command id
ResourceType resource_type;
read(stream, resource_type);
if (stream.eof())
{
break;
}
// Find command function for the given command id
auto cmd_it = stream_resources.find(resource_type);
// Check if command replayer supports the given command
if (cmd_it != stream_resources.end())
{
// Run command function
cmd_it->second(resource_cache, stream);
}
else
{
LOGE("Replay command not supported.");
}
}
}
void ResourceReplay::create_shader_module(ResourceCache &resource_cache, std::istringstream &stream)
{
VkShaderStageFlagBits stage{};
std::string glsl_source;
std::string entry_point;
read(stream,
stage,
glsl_source,
entry_point);
ShaderSource shader_source{};
shader_source.set_source(std::move(glsl_source));
ShaderVariant shader_variant;
auto &shader_module = resource_cache.request_shader_module(stage, shader_source, shader_variant);
shader_modules.push_back(&shader_module);
}
void ResourceReplay::create_pipeline_layout(ResourceCache &resource_cache, std::istringstream &stream)
{
std::vector<size_t> shader_indices;
read(stream,
shader_indices);
std::vector<ShaderModule *> shader_stages(shader_indices.size());
std::transform(shader_indices.begin(),
shader_indices.end(),
shader_stages.begin(),
[&](size_t shader_index) {
assert(shader_index < shader_modules.size());
return shader_modules[shader_index];
});
auto &pipeline_layout = resource_cache.request_pipeline_layout(shader_stages);
pipeline_layouts.push_back(&pipeline_layout);
}
void ResourceReplay::create_render_pass(ResourceCache &resource_cache, std::istringstream &stream)
{
std::vector<Attachment> attachments;
std::vector<LoadStoreInfo> load_store_infos;
std::vector<SubpassInfo> subpasses;
read(stream,
attachments,
load_store_infos);
read_subpass_info(stream, subpasses);
auto &render_pass = resource_cache.request_render_pass(attachments, load_store_infos, subpasses);
render_passes.push_back(&render_pass);
}
void ResourceReplay::create_graphics_pipeline(ResourceCache &resource_cache, std::istringstream &stream)
{
size_t pipeline_layout_index{};
size_t render_pass_index{};
uint32_t subpass_index{};
read(stream,
pipeline_layout_index,
render_pass_index,
subpass_index);
std::map<uint32_t, std::vector<uint8_t>> specialization_constant_state{};
read(stream,
specialization_constant_state);
VertexInputState vertex_input_state{};
read(stream,
vertex_input_state.attributes,
vertex_input_state.bindings);
InputAssemblyState input_assembly_state{};
RasterizationState rasterization_state{};
ViewportState viewport_state{};
MultisampleState multisample_state{};
DepthStencilState depth_stencil_state{};
read(stream,
input_assembly_state,
rasterization_state,
viewport_state,
multisample_state,
depth_stencil_state);
ColorBlendState color_blend_state{};
read(stream,
color_blend_state.logic_op,
color_blend_state.logic_op_enable,
color_blend_state.attachments);
PipelineState pipeline_state{};
assert(pipeline_layout_index < pipeline_layouts.size());
pipeline_state.set_pipeline_layout(*pipeline_layouts[pipeline_layout_index]);
assert(render_pass_index < render_passes.size());
pipeline_state.set_render_pass(*render_passes[render_pass_index]);
for (auto &item : specialization_constant_state)
{
pipeline_state.set_specialization_constant(item.first, item.second);
}
pipeline_state.set_subpass_index(subpass_index);
pipeline_state.set_vertex_input_state(vertex_input_state);
pipeline_state.set_input_assembly_state(input_assembly_state);
pipeline_state.set_rasterization_state(rasterization_state);
pipeline_state.set_viewport_state(viewport_state);
pipeline_state.set_multisample_state(multisample_state);
pipeline_state.set_depth_stencil_state(depth_stencil_state);
pipeline_state.set_color_blend_state(color_blend_state);
auto &graphics_pipeline = resource_cache.request_graphics_pipeline(pipeline_state);
graphics_pipelines.push_back(&graphics_pipeline);
}
} // namespace vkb