Vulkan: Use an enumeration to index pipeline layouts

This commit is contained in:
Stenzek 2016-11-13 15:24:55 +10:00
parent cd3481fbc7
commit 4bc0e14995
10 changed files with 96 additions and 112 deletions

View File

@ -42,6 +42,29 @@ enum DESCRIPTOR_SET_BIND_POINT
NUM_DESCRIPTOR_SET_BIND_POINTS
};
// We use four pipeline layouts:
// - Standard
// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS)
// - 8 combined image samplers (accessible from PS)
// - BBox Enabled
// - Same as standard, plus a single SSBO accessible from PS
// - Push Constant
// - Same as standard, plus 128 bytes of push constants, accessible from all stages.
// - Texture Decoding
// - Same as push constant, plus a single texel buffer accessible from PS.
//
// All four pipeline layout share the first two descriptor sets (uniform buffers, PS samplers).
// The third descriptor set (see bind points above) is used for storage or texel buffers.
//
enum PIPELINE_LAYOUT
{
PIPELINE_LAYOUT_STANDARD,
PIPELINE_LAYOUT_BBOX,
PIPELINE_LAYOUT_PUSH_CONSTANT,
PIPELINE_LAYOUT_TEXTURE_CONVERSION,
NUM_PIPELINE_LAYOUTS
};
// Uniform buffer bindings within the first descriptor set
enum UNIFORM_BUFFER_DESCRIPTOR_SET_BINDING
{

View File

@ -442,8 +442,8 @@ void FramebufferManager::ReinterpretPixelData(int convtype)
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(), m_efb_load_render_pass,
g_object_cache->GetScreenQuadVertexShader(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_efb_load_render_pass, g_object_cache->GetScreenQuadVertexShader(),
g_object_cache->GetScreenQuadGeometryShader(), pixel_shader);
RasterizationState rs_state = Util::GetNoCullRasterizationState();
@ -511,8 +511,8 @@ Texture2D* FramebufferManager::ResolveEFBDepthTexture(const VkRect2D& region)
// Draw using resolve shader to write the minimum depth of all samples to the resolve texture.
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(), m_depth_resolve_render_pass,
g_object_cache->GetScreenQuadVertexShader(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_depth_resolve_render_pass, g_object_cache->GetScreenQuadVertexShader(),
g_object_cache->GetScreenQuadGeometryShader(), m_ps_depth_resolve);
draw.BeginRenderPass(m_depth_resolve_framebuffer, region);
draw.SetPSSampler(0, m_efb_depth_texture->GetView(), g_object_cache->GetPointSampler());
@ -696,9 +696,9 @@ bool FramebufferManager::PopulateColorReadbackTexture()
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
{
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(), m_copy_color_render_pass,
g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
m_copy_color_shader);
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_copy_color_render_pass, g_object_cache->GetScreenQuadVertexShader(),
VK_NULL_HANDLE, m_copy_color_shader);
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
draw.BeginRenderPass(m_color_copy_framebuffer, rect);
@ -777,9 +777,9 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
if (m_efb_width != EFB_WIDTH || m_efb_height != EFB_HEIGHT)
{
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(), m_copy_depth_render_pass,
g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
m_copy_depth_shader);
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_copy_depth_render_pass, g_object_cache->GetScreenQuadVertexShader(),
VK_NULL_HANDLE, m_copy_depth_shader);
VkRect2D rect = {{0, 0}, {EFB_WIDTH, EFB_HEIGHT}};
draw.BeginRenderPass(m_depth_copy_framebuffer, rect);
@ -1171,7 +1171,7 @@ void FramebufferManager::DrawPokeVertices(const EFBPokeVertex* vertices, size_t
// We don't use the utility shader in order to keep the vertices compact.
PipelineInfo pipeline_info = {};
pipeline_info.vertex_format = m_poke_vertex_format.get();
pipeline_info.pipeline_layout = g_object_cache->GetStandardPipelineLayout();
pipeline_info.pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD);
pipeline_info.vs = m_poke_vertex_shader;
pipeline_info.gs = (m_efb_layers > 1) ? m_poke_geometry_shader : VK_NULL_HANDLE;
pipeline_info.ps = m_poke_fragment_shader;

View File

@ -752,47 +752,32 @@ bool ObjectCache::CreatePipelineLayouts()
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, PUSH_CONSTANT_BUFFER_SIZE};
// Info for each pipeline layout
VkPipelineLayoutCreateInfo standard_info = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
0,
static_cast<u32>(ArraySize(standard_sets)),
standard_sets,
0,
nullptr};
VkPipelineLayoutCreateInfo bbox_info = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
0,
static_cast<u32>(ArraySize(bbox_sets)),
bbox_sets,
0,
nullptr};
VkPipelineLayoutCreateInfo push_constant_info = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
0,
static_cast<u32>(ArraySize(standard_sets)),
standard_sets,
1,
&push_constant_range};
VkPipelineLayoutCreateInfo texture_conversion_info = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
0,
static_cast<u32>(ArraySize(texture_conversion_sets)),
texture_conversion_sets,
1,
&push_constant_range};
VkPipelineLayoutCreateInfo pipeline_layout_info[NUM_PIPELINE_LAYOUTS] = {
// Standard
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(standard_sets)), standard_sets, 0, nullptr},
if ((res = vkCreatePipelineLayout(g_vulkan_context->GetDevice(), &standard_info, nullptr,
&m_standard_pipeline_layout)) != VK_SUCCESS ||
(res = vkCreatePipelineLayout(g_vulkan_context->GetDevice(), &bbox_info, nullptr,
&m_bbox_pipeline_layout)) != VK_SUCCESS ||
(res = vkCreatePipelineLayout(g_vulkan_context->GetDevice(), &push_constant_info, nullptr,
&m_push_constant_pipeline_layout)) != VK_SUCCESS ||
(res = vkCreatePipelineLayout(g_vulkan_context->GetDevice(), &texture_conversion_info,
nullptr, &m_texture_conversion_pipeline_layout)) != VK_SUCCESS)
// BBox
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(bbox_sets)), bbox_sets, 0, nullptr},
// Push Constant
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(standard_sets)), standard_sets, 1, &push_constant_range},
// Texture Conversion
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(texture_conversion_sets)), texture_conversion_sets, 1,
&push_constant_range}};
for (size_t i = 0; i < NUM_PIPELINE_LAYOUTS; i++)
{
LOG_VULKAN_ERROR(res, "vkCreatePipelineLayout failed: ");
return false;
if ((res = vkCreatePipelineLayout(g_vulkan_context->GetDevice(), &pipeline_layout_info[i],
nullptr, &m_pipeline_layouts[i])) != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreatePipelineLayout failed: ");
return false;
}
}
return true;
@ -800,16 +785,11 @@ bool ObjectCache::CreatePipelineLayouts()
void ObjectCache::DestroyPipelineLayouts()
{
if (m_standard_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), m_standard_pipeline_layout, nullptr);
if (m_bbox_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), m_bbox_pipeline_layout, nullptr);
if (m_push_constant_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), m_push_constant_pipeline_layout,
nullptr);
if (m_texture_conversion_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), m_texture_conversion_pipeline_layout,
nullptr);
for (VkPipelineLayout layout : m_pipeline_layouts)
{
if (layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), layout, nullptr);
}
}
bool ObjectCache::CreateUtilityShaderVertexFormat()

View File

@ -62,30 +62,15 @@ public:
ObjectCache();
~ObjectCache();
// We have four shared pipeline layouts:
// - Standard
// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS)
// - 8 combined image samplers (accessible from PS)
// - BBox Enabled
// - Same as standard, plus a single SSBO accessible from PS
// - Push Constant
// - Same as standard, plus 128 bytes of push constants, accessible from all stages.
// - Texture Conversion
// - Same as push constant, plus a single texel buffer accessible from PS.
//
// All three pipeline layouts use the same descriptor set layouts, but the final descriptor set
// (SSBO) is only required when using the BBox Enabled pipeline layout.
//
VkDescriptorSetLayout GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT set) const
// Descriptor set layout accessor. Used for allocating descriptor sets.
VkDescriptorSetLayout GetDescriptorSetLayout(DESCRIPTOR_SET_LAYOUT layout) const
{
return m_descriptor_set_layouts[set];
return m_descriptor_set_layouts[layout];
}
VkPipelineLayout GetStandardPipelineLayout() const { return m_standard_pipeline_layout; }
VkPipelineLayout GetBBoxPipelineLayout() const { return m_bbox_pipeline_layout; }
VkPipelineLayout GetPushConstantPipelineLayout() const { return m_push_constant_pipeline_layout; }
VkPipelineLayout GetTextureConversionPipelineLayout() const
// Pipeline layout accessor. Used to fill in required field in PipelineInfo.
VkPipelineLayout GetPipelineLayout(PIPELINE_LAYOUT layout) const
{
return m_texture_conversion_pipeline_layout;
return m_pipeline_layouts[layout];
}
// Shared utility shader resources
VertexFormat* GetUtilityShaderVertexFormat() const
@ -164,11 +149,7 @@ private:
void DestroySamplers();
std::array<VkDescriptorSetLayout, NUM_DESCRIPTOR_SET_LAYOUTS> m_descriptor_set_layouts = {};
VkPipelineLayout m_standard_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_bbox_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_push_constant_pipeline_layout = VK_NULL_HANDLE;
VkPipelineLayout m_texture_conversion_pipeline_layout = VK_NULL_HANDLE;
std::array<VkPipelineLayout, NUM_PIPELINE_LAYOUTS> m_pipeline_layouts = {};
std::unique_ptr<VertexFormat> m_utility_shader_vertex_format;
std::unique_ptr<StreamBuffer> m_utility_shader_vertex_buffer;

View File

@ -113,9 +113,9 @@ void PaletteTextureConverter::ConvertTexture(VkCommandBuffer command_buffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
// Set up draw
UtilityShaderDraw draw(command_buffer, g_object_cache->GetTextureConversionPipelineLayout(),
render_pass, g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
m_shaders[format]);
UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
render_pass, g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE, m_shaders[format]);
VkRect2D region = {{0, 0}, {width, height}};
draw.BeginRenderPass(dst_framebuffer, region);
@ -133,7 +133,7 @@ void PaletteTextureConverter::ConvertTexture(VkCommandBuffer command_buffer,
// We have to bind the texel buffer descriptor set separately.
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
g_object_cache->GetTextureConversionPipelineLayout(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_TEXTURE_CONVERSION),
DESCRIPTOR_SET_BIND_POINT_STORAGE_OR_TEXEL_BUFFER, 1,
&texel_buffer_descriptor_set, 0, nullptr);

View File

@ -300,8 +300,8 @@ void RasterFont::PrintMultiLineText(VkRenderPass render_pass, const std::string&
return;
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPushConstantPipelineLayout(), render_pass,
m_vertex_shader, VK_NULL_HANDLE, m_fragment_shader);
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
render_pass, m_vertex_shader, VK_NULL_HANDLE, m_fragment_shader);
UtilityShaderVertex* vertices =
draw.ReserveVertices(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, text.length() * 6);

View File

@ -448,7 +448,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
// No need to start a new render pass, but we do need to restore viewport state
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
FramebufferManager::GetInstance()->GetEFBLoadRenderPass(),
g_object_cache->GetPassthroughVertexShader(),
g_object_cache->GetPassthroughGeometryShader(), m_clear_fragment_shader);
@ -879,7 +879,7 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r
// Set up common data
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(), render_pass,
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass,
g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE,
m_blit_fragment_shader);

View File

@ -75,7 +75,7 @@ bool StateTracker::Initialize()
m_pipeline_state.rasterization_state.depth_clamp = VK_TRUE;
// BBox is disabled by default.
m_pipeline_state.pipeline_layout = g_object_cache->GetStandardPipelineLayout();
m_pipeline_state.pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD);
m_num_active_descriptor_sets = NUM_GX_DRAW_DESCRIPTOR_SETS;
m_bbox_enabled = false;
@ -164,8 +164,8 @@ bool StateTracker::PrecachePipelineUID(const SerializedPipelineUID& uid)
// vertex loader that uses this format, since we need it to create a pipeline.
pinfo.vertex_format = VertexFormat::GetOrCreateMatchingFormat(uid.vertex_decl);
pinfo.pipeline_layout = uid.ps_uid.GetUidData()->bounding_box ?
g_object_cache->GetBBoxPipelineLayout() :
g_object_cache->GetStandardPipelineLayout();
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_BBOX) :
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD);
pinfo.vs = g_object_cache->GetVertexShaderForUid(uid.vs_uid);
if (pinfo.vs == VK_NULL_HANDLE)
{
@ -544,7 +544,7 @@ void StateTracker::SetBBoxEnable(bool enable)
// Change the number of active descriptor sets, as well as the pipeline layout
if (enable)
{
m_pipeline_state.pipeline_layout = g_object_cache->GetBBoxPipelineLayout();
m_pipeline_state.pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_BBOX);
m_num_active_descriptor_sets = NUM_GX_DRAW_WITH_BBOX_DESCRIPTOR_SETS;
// The bbox buffer never changes, so we defer descriptor updates until it is enabled.
@ -553,7 +553,7 @@ void StateTracker::SetBBoxEnable(bool enable)
}
else
{
m_pipeline_state.pipeline_layout = g_object_cache->GetStandardPipelineLayout();
m_pipeline_state.pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD);
m_num_active_descriptor_sets = NUM_GX_DRAW_DESCRIPTOR_SETS;
}

View File

@ -233,7 +233,7 @@ void TextureCache::ScaleTextureRectangle(TCacheEntry* dst_texture,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetStandardPipelineLayout(),
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
GetRenderPassForTextureUpdate(dst_texture->GetTexture()),
g_object_cache->GetPassthroughVertexShader(),
g_object_cache->GetPassthroughGeometryShader(), m_copy_shader);
@ -588,7 +588,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPushConstantPipelineLayout(),
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
TextureCache::GetInstance()->GetRenderPassForTextureUpdate(m_texture.get()),
g_object_cache->GetPassthroughVertexShader(), g_object_cache->GetPassthroughGeometryShader(),
is_depth_copy ? TextureCache::GetInstance()->m_efb_depth_to_tex_shader :
@ -880,10 +880,10 @@ void TextureCache::EncodeYUYVTextureToMemory(void* dst_ptr, u32 dst_width, u32 d
// the order the guest is expecting and we don't have to swap it at readback time. The width
// is halved because we're using an RGBA8 texture, but the YUYV data is two bytes per pixel.
u32 output_width = dst_width / 2;
UtilityShaderDraw draw(command_buffer, g_object_cache->GetStandardPipelineLayout(),
m_texture_encoder->GetEncodingRenderPass(),
g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE,
m_rgb_to_yuyv_shader);
UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_texture_encoder->GetEncodingRenderPass(), g_object_cache->GetPassthroughVertexShader(),
VK_NULL_HANDLE, m_rgb_to_yuyv_shader);
VkRect2D region = {{0, 0}, {output_width, dst_height}};
draw.BeginRenderPass(m_texture_encoder->GetEncodingTextureFramebuffer(), region);
draw.SetPSSampler(0, src_texture->GetView(), g_object_cache->GetLinearSampler());
@ -953,10 +953,10 @@ void TextureCache::DecodeYUYVTextureFromMemory(TCacheEntry* dst_texture, const v
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Convert from the YUYV data now in the intermediate texture to RGBA in the destination.
UtilityShaderDraw draw(command_buffer, g_object_cache->GetStandardPipelineLayout(),
m_texture_encoder->GetEncodingRenderPass(),
g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
m_yuyv_to_rgb_shader);
UtilityShaderDraw draw(
command_buffer, g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD),
m_texture_encoder->GetEncodingRenderPass(), g_object_cache->GetScreenQuadVertexShader(),
VK_NULL_HANDLE, m_yuyv_to_rgb_shader);
VkRect2D region = {{0, 0}, {src_width, src_height}};
draw.BeginRenderPass(dst_texture->GetFramebuffer(), region);
draw.SetViewportAndScissor(0, 0, static_cast<int>(src_width), static_cast<int>(src_height));

View File

@ -89,9 +89,9 @@ void TextureEncoder::EncodeTextureToRam(VkImageView src_texture, u8* dest_ptr, u
StateTracker::GetInstance()->EndRenderPass();
UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(),
g_object_cache->GetPushConstantPipelineLayout(), m_encoding_render_pass,
g_object_cache->GetScreenQuadVertexShader(), VK_NULL_HANDLE,
m_texture_encoding_shaders[format]);
g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_PUSH_CONSTANT),
m_encoding_render_pass, g_object_cache->GetScreenQuadVertexShader(),
VK_NULL_HANDLE, m_texture_encoding_shaders[format]);
// Uniform - int4 of left,top,native_width,scale
s32 position_uniform[4] = {src_rect.left, src_rect.top, static_cast<s32>(native_width),