Implementing a lot of the pipeline state setting.

This commit is contained in:
Ben Vanik 2016-02-20 12:59:18 -08:00
parent 97174dbe4d
commit 731ff52773
5 changed files with 850 additions and 411 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
} }