Implementing a lot of the pipeline state setting.
This commit is contained in:
parent
97174dbe4d
commit
731ff52773
|
@ -188,8 +188,9 @@ BufferCache::~BufferCache() {
|
||||||
vkDestroyBuffer(device_, transient_vertex_buffer_, nullptr);
|
vkDestroyBuffer(device_, transient_vertex_buffer_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceSize BufferCache::UploadConstantRegisters(
|
std::pair<VkDeviceSize, VkDeviceSize> BufferCache::UploadConstantRegisters(
|
||||||
const Shader::ConstantRegisterMap& constant_register_map) {
|
const Shader::ConstantRegisterMap& vertex_constant_register_map,
|
||||||
|
const Shader::ConstantRegisterMap& pixel_constant_register_map) {
|
||||||
// Fat struct, including all registers:
|
// Fat struct, including all registers:
|
||||||
// struct {
|
// struct {
|
||||||
// vec4 float[512];
|
// vec4 float[512];
|
||||||
|
@ -202,7 +203,7 @@ VkDeviceSize BufferCache::UploadConstantRegisters(
|
||||||
auto offset = AllocateTransientData(uniform_buffer_alignment_, total_size);
|
auto offset = AllocateTransientData(uniform_buffer_alignment_, total_size);
|
||||||
if (offset == VK_WHOLE_SIZE) {
|
if (offset == VK_WHOLE_SIZE) {
|
||||||
// OOM.
|
// OOM.
|
||||||
return VK_WHOLE_SIZE;
|
return {VK_WHOLE_SIZE, VK_WHOLE_SIZE};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over all the registers.
|
// Copy over all the registers.
|
||||||
|
@ -219,7 +220,7 @@ VkDeviceSize BufferCache::UploadConstantRegisters(
|
||||||
32 * 4);
|
32 * 4);
|
||||||
dest_ptr += 32 * 4;
|
dest_ptr += 32 * 4;
|
||||||
|
|
||||||
return offset;
|
return {offset, offset};
|
||||||
|
|
||||||
// Packed upload code.
|
// Packed upload code.
|
||||||
// This is not currently supported by the shaders, but would be awesome.
|
// This is not currently supported by the shaders, but would be awesome.
|
||||||
|
|
|
@ -47,8 +47,10 @@ class BufferCache {
|
||||||
// The registers are tightly packed in order as [floats, ints, bools].
|
// The registers are tightly packed in order as [floats, ints, bools].
|
||||||
// Returns an offset that can be used with the transient_descriptor_set or
|
// Returns an offset that can be used with the transient_descriptor_set or
|
||||||
// VK_WHOLE_SIZE if the constants could not be uploaded (OOM).
|
// VK_WHOLE_SIZE if the constants could not be uploaded (OOM).
|
||||||
VkDeviceSize UploadConstantRegisters(
|
// The returned offsets may alias.
|
||||||
const Shader::ConstantRegisterMap& constant_register_map);
|
std::pair<VkDeviceSize, VkDeviceSize> UploadConstantRegisters(
|
||||||
|
const Shader::ConstantRegisterMap& vertex_constant_register_map,
|
||||||
|
const Shader::ConstantRegisterMap& pixel_constant_register_map);
|
||||||
|
|
||||||
// Uploads index buffer data from guest memory, possibly eliding with
|
// Uploads index buffer data from guest memory, possibly eliding with
|
||||||
// recently uploaded data or cached copies.
|
// recently uploaded data or cached copies.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,10 +57,19 @@ class PipelineCache {
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Creates or retrieves an existing pipeline for the currently configured
|
||||||
|
// state.
|
||||||
|
VkPipeline GetPipeline(const RenderState* render_state);
|
||||||
|
|
||||||
// Gets a geometry shader used to emulate the given primitive type.
|
// Gets a geometry shader used to emulate the given primitive type.
|
||||||
// Returns nullptr if the primitive doesn't need to be emulated.
|
// Returns nullptr if the primitive doesn't need to be emulated.
|
||||||
VkShaderModule GetGeometryShader(PrimitiveType primitive_type);
|
VkShaderModule GetGeometryShader(PrimitiveType primitive_type);
|
||||||
|
|
||||||
|
// Sets required dynamic state on the command buffer.
|
||||||
|
// Only state that has changed since the last call will be set unless
|
||||||
|
// full_update is true.
|
||||||
|
bool SetDynamicState(VkCommandBuffer command_buffer, bool full_update);
|
||||||
|
|
||||||
RegisterFile* register_file_ = nullptr;
|
RegisterFile* register_file_ = nullptr;
|
||||||
VkDevice device_ = nullptr;
|
VkDevice device_ = nullptr;
|
||||||
|
|
||||||
|
@ -80,6 +89,11 @@ class PipelineCache {
|
||||||
|
|
||||||
// TODO(benvanik): geometry shader cache.
|
// TODO(benvanik): geometry shader cache.
|
||||||
|
|
||||||
|
// Previously used pipeline. This matches our current state settings
|
||||||
|
// and allows us to quickly(ish) reuse the pipeline if no registers have
|
||||||
|
// changed.
|
||||||
|
VkPipeline current_pipeline_ = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class UpdateStatus {
|
enum class UpdateStatus {
|
||||||
kCompatible,
|
kCompatible,
|
||||||
|
@ -87,13 +101,21 @@ class PipelineCache {
|
||||||
kError,
|
kError,
|
||||||
};
|
};
|
||||||
|
|
||||||
UpdateStatus UpdateShaders(PrimitiveType prim_type);
|
|
||||||
UpdateStatus UpdateRenderTargets();
|
UpdateStatus UpdateRenderTargets();
|
||||||
UpdateStatus UpdateState(PrimitiveType prim_type);
|
UpdateStatus UpdateState(VulkanShader* vertex_shader,
|
||||||
|
VulkanShader* pixel_shader,
|
||||||
|
PrimitiveType primitive_type);
|
||||||
|
|
||||||
|
UpdateStatus UpdateShaderStages(VulkanShader* vertex_shader,
|
||||||
|
VulkanShader* pixel_shader,
|
||||||
|
PrimitiveType primitive_type);
|
||||||
|
UpdateStatus UpdateVertexInputState(VulkanShader* vertex_shader);
|
||||||
|
UpdateStatus UpdateInputAssemblyState(PrimitiveType primitive_type);
|
||||||
UpdateStatus UpdateViewportState();
|
UpdateStatus UpdateViewportState();
|
||||||
UpdateStatus UpdateRasterizerState(PrimitiveType prim_type);
|
UpdateStatus UpdateRasterizationState(PrimitiveType primitive_type);
|
||||||
UpdateStatus UpdateBlendState();
|
UpdateStatus UpdateMultisampleState();
|
||||||
UpdateStatus UpdateDepthStencilState();
|
UpdateStatus UpdateDepthStencilState();
|
||||||
|
UpdateStatus UpdateColorBlendState();
|
||||||
|
|
||||||
bool SetShadowRegister(uint32_t* dest, uint32_t register_name);
|
bool SetShadowRegister(uint32_t* dest, uint32_t register_name);
|
||||||
bool SetShadowRegister(float* dest, uint32_t register_name);
|
bool SetShadowRegister(float* dest, uint32_t register_name);
|
||||||
|
@ -113,6 +135,45 @@ class PipelineCache {
|
||||||
UpdateRenderTargetsRegisters() { Reset(); }
|
UpdateRenderTargetsRegisters() { Reset(); }
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
} update_render_targets_regs_;
|
} update_render_targets_regs_;
|
||||||
|
|
||||||
|
struct UpdateShaderStagesRegisters {
|
||||||
|
PrimitiveType prim_type;
|
||||||
|
uint32_t pa_su_sc_mode_cntl;
|
||||||
|
uint32_t sq_program_cntl;
|
||||||
|
uint32_t sq_context_misc;
|
||||||
|
VulkanShader* vertex_shader;
|
||||||
|
VulkanShader* pixel_shader;
|
||||||
|
|
||||||
|
UpdateShaderStagesRegisters() { Reset(); }
|
||||||
|
void Reset() {
|
||||||
|
sq_program_cntl = 0;
|
||||||
|
vertex_shader = pixel_shader = nullptr;
|
||||||
|
}
|
||||||
|
} update_shader_stages_regs_;
|
||||||
|
VkPipelineShaderStageCreateInfo update_shader_stages_info_[3];
|
||||||
|
uint32_t update_shader_stages_stage_count_ = 0;
|
||||||
|
|
||||||
|
struct UpdateVertexInputStateRegisters {
|
||||||
|
VulkanShader* vertex_shader;
|
||||||
|
|
||||||
|
UpdateVertexInputStateRegisters() { Reset(); }
|
||||||
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
|
} update_vertex_input_state_regs_;
|
||||||
|
VkPipelineVertexInputStateCreateInfo update_vertex_input_state_info_;
|
||||||
|
VkVertexInputBindingDescription update_vertex_input_state_binding_descrs_[64];
|
||||||
|
VkVertexInputAttributeDescription
|
||||||
|
update_vertex_input_state_attrib_descrs_[64];
|
||||||
|
|
||||||
|
struct UpdateInputAssemblyStateRegisters {
|
||||||
|
PrimitiveType primitive_type;
|
||||||
|
uint32_t pa_su_sc_mode_cntl;
|
||||||
|
uint32_t multi_prim_ib_reset_index;
|
||||||
|
|
||||||
|
UpdateInputAssemblyStateRegisters() { Reset(); }
|
||||||
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
|
} update_input_assembly_state_regs_;
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo update_input_assembly_state_info_;
|
||||||
|
|
||||||
struct UpdateViewportStateRegisters {
|
struct UpdateViewportStateRegisters {
|
||||||
// uint32_t pa_cl_clip_cntl;
|
// uint32_t pa_cl_clip_cntl;
|
||||||
uint32_t rb_surface_info;
|
uint32_t rb_surface_info;
|
||||||
|
@ -131,23 +192,26 @@ class PipelineCache {
|
||||||
UpdateViewportStateRegisters() { Reset(); }
|
UpdateViewportStateRegisters() { Reset(); }
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
} update_viewport_state_regs_;
|
} update_viewport_state_regs_;
|
||||||
struct UpdateRasterizerStateRegisters {
|
VkPipelineViewportStateCreateInfo update_viewport_state_info_;
|
||||||
|
|
||||||
|
struct UpdateRasterizationStateRegisters {
|
||||||
uint32_t pa_su_sc_mode_cntl;
|
uint32_t pa_su_sc_mode_cntl;
|
||||||
uint32_t pa_sc_screen_scissor_tl;
|
uint32_t pa_sc_screen_scissor_tl;
|
||||||
uint32_t pa_sc_screen_scissor_br;
|
uint32_t pa_sc_screen_scissor_br;
|
||||||
uint32_t multi_prim_ib_reset_index;
|
uint32_t multi_prim_ib_reset_index;
|
||||||
PrimitiveType prim_type;
|
PrimitiveType prim_type;
|
||||||
|
|
||||||
UpdateRasterizerStateRegisters() { Reset(); }
|
UpdateRasterizationStateRegisters() { Reset(); }
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
} update_rasterizer_state_regs_;
|
} update_rasterization_state_regs_;
|
||||||
struct UpdateBlendStateRegisters {
|
VkPipelineRasterizationStateCreateInfo update_rasterization_state_info_;
|
||||||
uint32_t rb_blendcontrol[4];
|
|
||||||
float rb_blend_rgba[4];
|
|
||||||
|
|
||||||
UpdateBlendStateRegisters() { Reset(); }
|
struct UpdateMultisampleStateeRegisters {
|
||||||
|
UpdateMultisampleStateeRegisters() { Reset(); }
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
} update_blend_state_regs_;
|
} update_multisample_state_regs_;
|
||||||
|
VkPipelineMultisampleStateCreateInfo update_multisample_state_info_;
|
||||||
|
|
||||||
struct UpdateDepthStencilStateRegisters {
|
struct UpdateDepthStencilStateRegisters {
|
||||||
uint32_t rb_depthcontrol;
|
uint32_t rb_depthcontrol;
|
||||||
uint32_t rb_stencilrefmask;
|
uint32_t rb_stencilrefmask;
|
||||||
|
@ -155,20 +219,40 @@ class PipelineCache {
|
||||||
UpdateDepthStencilStateRegisters() { Reset(); }
|
UpdateDepthStencilStateRegisters() { Reset(); }
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
} update_depth_stencil_state_regs_;
|
} update_depth_stencil_state_regs_;
|
||||||
struct UpdateShadersRegisters {
|
VkPipelineDepthStencilStateCreateInfo update_depth_stencil_state_info_;
|
||||||
PrimitiveType prim_type;
|
|
||||||
uint32_t pa_su_sc_mode_cntl;
|
|
||||||
uint32_t sq_program_cntl;
|
|
||||||
uint32_t sq_context_misc;
|
|
||||||
VulkanShader* vertex_shader;
|
|
||||||
VulkanShader* pixel_shader;
|
|
||||||
|
|
||||||
UpdateShadersRegisters() { Reset(); }
|
struct UpdateColorBlendStateRegisters {
|
||||||
void Reset() {
|
uint32_t rb_colorcontrol;
|
||||||
sq_program_cntl = 0;
|
uint32_t rb_color_mask;
|
||||||
vertex_shader = pixel_shader = nullptr;
|
uint32_t rb_blendcontrol[4];
|
||||||
}
|
|
||||||
} update_shaders_regs_;
|
UpdateColorBlendStateRegisters() { Reset(); }
|
||||||
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
|
} update_color_blend_state_regs_;
|
||||||
|
VkPipelineColorBlendStateCreateInfo update_color_blend_state_info_;
|
||||||
|
VkPipelineColorBlendAttachmentState update_color_blend_attachment_states_[4];
|
||||||
|
|
||||||
|
struct SetDynamicStateRegisters {
|
||||||
|
uint32_t pa_sc_window_offset;
|
||||||
|
|
||||||
|
uint32_t pa_su_sc_mode_cntl;
|
||||||
|
uint32_t pa_sc_window_scissor_tl;
|
||||||
|
uint32_t pa_sc_window_scissor_br;
|
||||||
|
|
||||||
|
uint32_t rb_surface_info;
|
||||||
|
uint32_t pa_cl_vte_cntl;
|
||||||
|
float pa_cl_vport_xoffset;
|
||||||
|
float pa_cl_vport_yoffset;
|
||||||
|
float pa_cl_vport_zoffset;
|
||||||
|
float pa_cl_vport_xscale;
|
||||||
|
float pa_cl_vport_yscale;
|
||||||
|
float pa_cl_vport_zscale;
|
||||||
|
|
||||||
|
float rb_blend_rgba[4];
|
||||||
|
|
||||||
|
SetDynamicStateRegisters() { Reset(); }
|
||||||
|
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
||||||
|
} set_dynamic_state_registers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vulkan
|
} // namespace vulkan
|
||||||
|
|
|
@ -321,12 +321,11 @@ bool VulkanCommandProcessor::PopulateConstants(VkCommandBuffer command_buffer,
|
||||||
VulkanShader* pixel_shader) {
|
VulkanShader* pixel_shader) {
|
||||||
// Upload the constants the shaders require.
|
// Upload the constants the shaders require.
|
||||||
// These are optional, and if none are defined 0 will be returned.
|
// These are optional, and if none are defined 0 will be returned.
|
||||||
VkDeviceSize vertex_constant_offset = buffer_cache_->UploadConstantRegisters(
|
auto constant_offsets = buffer_cache_->UploadConstantRegisters(
|
||||||
vertex_shader->constant_register_map());
|
vertex_shader->constant_register_map(),
|
||||||
VkDeviceSize pixel_constant_offset = buffer_cache_->UploadConstantRegisters(
|
|
||||||
pixel_shader->constant_register_map());
|
pixel_shader->constant_register_map());
|
||||||
if (vertex_constant_offset == VK_WHOLE_SIZE ||
|
if (constant_offsets.first == VK_WHOLE_SIZE ||
|
||||||
pixel_constant_offset == VK_WHOLE_SIZE) {
|
constant_offsets.second == VK_WHOLE_SIZE) {
|
||||||
// Shader wants constants but we couldn't upload them.
|
// Shader wants constants but we couldn't upload them.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -334,12 +333,14 @@ bool VulkanCommandProcessor::PopulateConstants(VkCommandBuffer command_buffer,
|
||||||
// Configure constant uniform access to point at our offsets.
|
// Configure constant uniform access to point at our offsets.
|
||||||
auto constant_descriptor_set = buffer_cache_->constant_descriptor_set();
|
auto constant_descriptor_set = buffer_cache_->constant_descriptor_set();
|
||||||
auto pipeline_layout = pipeline_cache_->pipeline_layout();
|
auto pipeline_layout = pipeline_cache_->pipeline_layout();
|
||||||
uint32_t constant_offsets[2] = {static_cast<uint32_t>(vertex_constant_offset),
|
uint32_t set_constant_offsets[2] = {
|
||||||
static_cast<uint32_t>(pixel_constant_offset)};
|
static_cast<uint32_t>(constant_offsets.first),
|
||||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
static_cast<uint32_t>(constant_offsets.second)};
|
||||||
pipeline_layout, 0, 1, &constant_descriptor_set,
|
vkCmdBindDescriptorSets(
|
||||||
static_cast<uint32_t>(xe::countof(constant_offsets)),
|
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1,
|
||||||
constant_offsets);
|
&constant_descriptor_set,
|
||||||
|
static_cast<uint32_t>(xe::countof(set_constant_offsets)),
|
||||||
|
set_constant_offsets);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue