[Vulkan] All guest draw uniform buffer bindings in a single descriptor set
Reduce the number of bound descriptor sets from 10 to 6, which is still above the minimum limit of 4, but closer
This commit is contained in:
parent
88c055eb30
commit
e4de8663c4
|
@ -257,8 +257,9 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
"xe_uniform_system_constants");
|
"xe_uniform_system_constants");
|
||||||
builder_->addDecoration(uniform_system_constants_,
|
builder_->addDecoration(uniform_system_constants_,
|
||||||
spv::DecorationDescriptorSet,
|
spv::DecorationDescriptorSet,
|
||||||
kDescriptorSetSystemConstants);
|
int(kDescriptorSetConstants));
|
||||||
builder_->addDecoration(uniform_system_constants_, spv::DecorationBinding, 0);
|
builder_->addDecoration(uniform_system_constants_, spv::DecorationBinding,
|
||||||
|
int(kConstantBufferSystem));
|
||||||
if (features_.spirv_version >= spv::Spv_1_4) {
|
if (features_.spirv_version >= spv::Spv_1_4) {
|
||||||
main_interface_.push_back(uniform_system_constants_);
|
main_interface_.push_back(uniform_system_constants_);
|
||||||
}
|
}
|
||||||
|
@ -285,12 +286,13 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
uniform_float_constants_ = builder_->createVariable(
|
uniform_float_constants_ = builder_->createVariable(
|
||||||
spv::NoPrecision, spv::StorageClassUniform, type_float_constants,
|
spv::NoPrecision, spv::StorageClassUniform, type_float_constants,
|
||||||
"xe_uniform_float_constants");
|
"xe_uniform_float_constants");
|
||||||
|
builder_->addDecoration(uniform_float_constants_,
|
||||||
|
spv::DecorationDescriptorSet,
|
||||||
|
int(kDescriptorSetConstants));
|
||||||
builder_->addDecoration(
|
builder_->addDecoration(
|
||||||
uniform_float_constants_, spv::DecorationDescriptorSet,
|
uniform_float_constants_, spv::DecorationBinding,
|
||||||
int(is_pixel_shader() ? kDescriptorSetFloatConstantsPixel
|
int(is_pixel_shader() ? kConstantBufferFloatPixel
|
||||||
: kDescriptorSetFloatConstantsVertex));
|
: kConstantBufferFloatVertex));
|
||||||
builder_->addDecoration(uniform_float_constants_, spv::DecorationBinding,
|
|
||||||
0);
|
|
||||||
if (features_.spirv_version >= spv::Spv_1_4) {
|
if (features_.spirv_version >= spv::Spv_1_4) {
|
||||||
main_interface_.push_back(uniform_float_constants_);
|
main_interface_.push_back(uniform_float_constants_);
|
||||||
}
|
}
|
||||||
|
@ -326,9 +328,9 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
"xe_uniform_bool_loop_constants");
|
"xe_uniform_bool_loop_constants");
|
||||||
builder_->addDecoration(uniform_bool_loop_constants_,
|
builder_->addDecoration(uniform_bool_loop_constants_,
|
||||||
spv::DecorationDescriptorSet,
|
spv::DecorationDescriptorSet,
|
||||||
int(kDescriptorSetBoolLoopConstants));
|
int(kDescriptorSetConstants));
|
||||||
builder_->addDecoration(uniform_bool_loop_constants_, spv::DecorationBinding,
|
builder_->addDecoration(uniform_bool_loop_constants_, spv::DecorationBinding,
|
||||||
0);
|
int(kConstantBufferBoolLoop));
|
||||||
if (features_.spirv_version >= spv::Spv_1_4) {
|
if (features_.spirv_version >= spv::Spv_1_4) {
|
||||||
main_interface_.push_back(uniform_bool_loop_constants_);
|
main_interface_.push_back(uniform_bool_loop_constants_);
|
||||||
}
|
}
|
||||||
|
@ -352,8 +354,9 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
"xe_uniform_fetch_constants");
|
"xe_uniform_fetch_constants");
|
||||||
builder_->addDecoration(uniform_fetch_constants_,
|
builder_->addDecoration(uniform_fetch_constants_,
|
||||||
spv::DecorationDescriptorSet,
|
spv::DecorationDescriptorSet,
|
||||||
int(kDescriptorSetFetchConstants));
|
int(kDescriptorSetConstants));
|
||||||
builder_->addDecoration(uniform_fetch_constants_, spv::DecorationBinding, 0);
|
builder_->addDecoration(uniform_fetch_constants_, spv::DecorationBinding,
|
||||||
|
int(kConstantBufferFetch));
|
||||||
if (features_.spirv_version >= spv::Spv_1_4) {
|
if (features_.spirv_version >= spv::Spv_1_4) {
|
||||||
main_interface_.push_back(uniform_fetch_constants_);
|
main_interface_.push_back(uniform_fetch_constants_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,16 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
float color_exp_bias[4];
|
float color_exp_bias[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ConstantBuffer : uint32_t {
|
||||||
|
kConstantBufferSystem,
|
||||||
|
kConstantBufferFloatVertex,
|
||||||
|
kConstantBufferFloatPixel,
|
||||||
|
kConstantBufferBoolLoop,
|
||||||
|
kConstantBufferFetch,
|
||||||
|
|
||||||
|
kConstantBufferCount,
|
||||||
|
};
|
||||||
|
|
||||||
// The minimum limit for maxPerStageDescriptorStorageBuffers is 4, and for
|
// The minimum limit for maxPerStageDescriptorStorageBuffers is 4, and for
|
||||||
// maxStorageBufferRange it's 128 MB. These are the values of those limits on
|
// maxStorageBufferRange it's 128 MB. These are the values of those limits on
|
||||||
// Arm Mali as of November 2020. Xenia needs 512 MB shared memory to be bound,
|
// Arm Mali as of November 2020. Xenia needs 512 MB shared memory to be bound,
|
||||||
|
@ -159,18 +169,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
|
|
||||||
// Never changed.
|
// Never changed.
|
||||||
kDescriptorSetSharedMemoryAndEdram,
|
kDescriptorSetSharedMemoryAndEdram,
|
||||||
// Pretty rarely used and rarely changed - flow control constants.
|
// Changed in case of changes in the data.
|
||||||
kDescriptorSetBoolLoopConstants,
|
kDescriptorSetConstants,
|
||||||
// May stay the same across many draws.
|
|
||||||
kDescriptorSetSystemConstants,
|
|
||||||
// Less frequently changed (per-material).
|
|
||||||
kDescriptorSetFloatConstantsPixel,
|
|
||||||
// Quite frequently changed (for one object drawn multiple times, for
|
|
||||||
// instance - may contain projection matrices).
|
|
||||||
kDescriptorSetFloatConstantsVertex,
|
|
||||||
// Very frequently changed, especially for UI draws, and for models drawn in
|
|
||||||
// multiple parts - contains vertex and texture fetch constants.
|
|
||||||
kDescriptorSetFetchConstants,
|
|
||||||
|
|
||||||
// Mutable part of the pipeline layout:
|
// Mutable part of the pipeline layout:
|
||||||
kDescriptorSetMutableLayoutsStart,
|
kDescriptorSetMutableLayoutsStart,
|
||||||
|
|
|
@ -59,7 +59,8 @@ VulkanCommandProcessor::VulkanCommandProcessor(
|
||||||
transient_descriptor_allocator_uniform_buffer_(
|
transient_descriptor_allocator_uniform_buffer_(
|
||||||
*static_cast<const ui::vulkan::VulkanProvider*>(
|
*static_cast<const ui::vulkan::VulkanProvider*>(
|
||||||
graphics_system->provider()),
|
graphics_system->provider()),
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32768, 32768),
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
SpirvShaderTranslator::kConstantBufferCount * 32768, 32768),
|
||||||
transient_descriptor_allocator_storage_buffer_(
|
transient_descriptor_allocator_storage_buffer_(
|
||||||
*static_cast<const ui::vulkan::VulkanProvider*>(
|
*static_cast<const ui::vulkan::VulkanProvider*>(
|
||||||
graphics_system->provider()),
|
graphics_system->provider()),
|
||||||
|
@ -176,84 +177,61 @@ bool VulkanCommandProcessor::SetupContext() {
|
||||||
"and the EDRAM");
|
"and the EDRAM");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Transient: uniform buffer for the guest vertex shader stages.
|
// Guest draw constants.
|
||||||
|
VkDescriptorSetLayoutBinding descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferCount] = {};
|
||||||
|
for (uint32_t i = 0; i < SpirvShaderTranslator::kConstantBufferCount; ++i) {
|
||||||
|
VkDescriptorSetLayoutBinding& constants_binding =
|
||||||
|
descriptor_set_layout_bindings_constants[i];
|
||||||
|
constants_binding.binding = i;
|
||||||
|
constants_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
constants_binding.descriptorCount = 1;
|
||||||
|
constants_binding.pImmutableSamplers = nullptr;
|
||||||
|
}
|
||||||
|
descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferSystem]
|
||||||
|
.stageFlags =
|
||||||
|
guest_shader_stages |
|
||||||
|
(device_features.tessellationShader
|
||||||
|
? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
|
||||||
|
: 0) |
|
||||||
|
(device_features.geometryShader ? VK_SHADER_STAGE_GEOMETRY_BIT : 0);
|
||||||
|
descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFloatVertex]
|
||||||
|
.stageFlags = guest_shader_vertex_stages_;
|
||||||
|
descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFloatPixel]
|
||||||
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferBoolLoop]
|
||||||
|
.stageFlags = guest_shader_stages;
|
||||||
|
descriptor_set_layout_bindings_constants
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFetch]
|
||||||
|
.stageFlags = guest_shader_stages;
|
||||||
|
descriptor_set_layout_create_info.bindingCount =
|
||||||
|
uint32_t(xe::countof(descriptor_set_layout_bindings_constants));
|
||||||
|
descriptor_set_layout_create_info.pBindings =
|
||||||
|
descriptor_set_layout_bindings_constants;
|
||||||
|
if (dfn.vkCreateDescriptorSetLayout(
|
||||||
|
device, &descriptor_set_layout_create_info, nullptr,
|
||||||
|
&descriptor_set_layout_constants_) != VK_SUCCESS) {
|
||||||
|
XELOGE(
|
||||||
|
"Failed to create a Vulkan descriptor set layout for guest draw "
|
||||||
|
"constant buffers");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Transient: uniform buffer for compute shaders.
|
||||||
VkDescriptorSetLayoutBinding descriptor_set_layout_binding_transient;
|
VkDescriptorSetLayoutBinding descriptor_set_layout_binding_transient;
|
||||||
descriptor_set_layout_binding_transient.binding = 0;
|
descriptor_set_layout_binding_transient.binding = 0;
|
||||||
descriptor_set_layout_binding_transient.descriptorType =
|
descriptor_set_layout_binding_transient.descriptorType =
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
descriptor_set_layout_binding_transient.descriptorCount = 1;
|
descriptor_set_layout_binding_transient.descriptorCount = 1;
|
||||||
descriptor_set_layout_binding_transient.stageFlags =
|
descriptor_set_layout_binding_transient.stageFlags =
|
||||||
guest_shader_vertex_stages_;
|
VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
descriptor_set_layout_binding_transient.pImmutableSamplers = nullptr;
|
descriptor_set_layout_binding_transient.pImmutableSamplers = nullptr;
|
||||||
descriptor_set_layout_create_info.bindingCount = 1;
|
descriptor_set_layout_create_info.bindingCount = 1;
|
||||||
descriptor_set_layout_create_info.pBindings =
|
descriptor_set_layout_create_info.pBindings =
|
||||||
&descriptor_set_layout_binding_transient;
|
&descriptor_set_layout_binding_transient;
|
||||||
if (dfn.vkCreateDescriptorSetLayout(
|
|
||||||
device, &descriptor_set_layout_create_info, nullptr,
|
|
||||||
&descriptor_set_layouts_single_transient_[size_t(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestVertex)]) !=
|
|
||||||
VK_SUCCESS) {
|
|
||||||
XELOGE(
|
|
||||||
"Failed to create a Vulkan descriptor set layout for a uniform buffer "
|
|
||||||
"bound to the guest vertex shader stages");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Transient: uniform buffer for fragment shaders.
|
|
||||||
descriptor_set_layout_binding_transient.descriptorType =
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags =
|
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
||||||
if (dfn.vkCreateDescriptorSetLayout(
|
|
||||||
device, &descriptor_set_layout_create_info, nullptr,
|
|
||||||
&descriptor_set_layouts_single_transient_[size_t(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferFragment)]) !=
|
|
||||||
VK_SUCCESS) {
|
|
||||||
XELOGE(
|
|
||||||
"Failed to create a Vulkan descriptor set layout for a uniform buffer "
|
|
||||||
"bound to the fragment shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Transient: uniform buffer for the guest shader stages.
|
|
||||||
descriptor_set_layout_binding_transient.descriptorType =
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags = guest_shader_stages;
|
|
||||||
if (dfn.vkCreateDescriptorSetLayout(
|
|
||||||
device, &descriptor_set_layout_create_info, nullptr,
|
|
||||||
&descriptor_set_layouts_single_transient_[size_t(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestShader)]) !=
|
|
||||||
VK_SUCCESS) {
|
|
||||||
XELOGE(
|
|
||||||
"Failed to create a Vulkan descriptor set layout for a uniform buffer "
|
|
||||||
"bound to the guest shader stages");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Transient: system constants.
|
|
||||||
descriptor_set_layout_binding_transient.descriptorType =
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags = guest_shader_stages;
|
|
||||||
if (device_features.tessellationShader) {
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags |=
|
|
||||||
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
|
|
||||||
}
|
|
||||||
if (device_features.geometryShader) {
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags |=
|
|
||||||
VK_SHADER_STAGE_GEOMETRY_BIT;
|
|
||||||
}
|
|
||||||
if (dfn.vkCreateDescriptorSetLayout(
|
|
||||||
device, &descriptor_set_layout_create_info, nullptr,
|
|
||||||
&descriptor_set_layouts_single_transient_[size_t(
|
|
||||||
SingleTransientDescriptorLayout ::
|
|
||||||
kUniformBufferSystemConstants)]) != VK_SUCCESS) {
|
|
||||||
XELOGE(
|
|
||||||
"Failed to create a Vulkan descriptor set layout for the system "
|
|
||||||
"constants uniform buffer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Transient: uniform buffer for compute shaders.
|
|
||||||
descriptor_set_layout_binding_transient.descriptorType =
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
||||||
descriptor_set_layout_binding_transient.stageFlags =
|
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT;
|
|
||||||
if (dfn.vkCreateDescriptorSetLayout(
|
if (dfn.vkCreateDescriptorSetLayout(
|
||||||
device, &descriptor_set_layout_create_info, nullptr,
|
device, &descriptor_set_layout_create_info, nullptr,
|
||||||
&descriptor_set_layouts_single_transient_[size_t(
|
&descriptor_set_layouts_single_transient_[size_t(
|
||||||
|
@ -1052,6 +1030,9 @@ void VulkanCommandProcessor::ShutdownContext() {
|
||||||
dfn.vkDestroyDescriptorSetLayout, device,
|
dfn.vkDestroyDescriptorSetLayout, device,
|
||||||
descriptor_set_layout_single_transient);
|
descriptor_set_layout_single_transient);
|
||||||
}
|
}
|
||||||
|
ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyDescriptorSetLayout,
|
||||||
|
device,
|
||||||
|
descriptor_set_layout_constants_);
|
||||||
ui::vulkan::util::DestroyAndNullHandle(
|
ui::vulkan::util::DestroyAndNullHandle(
|
||||||
dfn.vkDestroyDescriptorSetLayout, device,
|
dfn.vkDestroyDescriptorSetLayout, device,
|
||||||
descriptor_set_layout_shared_memory_and_edram_);
|
descriptor_set_layout_shared_memory_and_edram_);
|
||||||
|
@ -1134,27 +1115,25 @@ void VulkanCommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
|
||||||
float_constant_index -= 256;
|
float_constant_index -= 256;
|
||||||
if (current_float_constant_map_pixel_[float_constant_index >> 6] &
|
if (current_float_constant_map_pixel_[float_constant_index >> 6] &
|
||||||
(1ull << (float_constant_index & 63))) {
|
(1ull << (float_constant_index & 63))) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &= ~(
|
||||||
~(UINT32_C(1)
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatPixel);
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (current_float_constant_map_vertex_[float_constant_index >> 6] &
|
if (current_float_constant_map_vertex_[float_constant_index >> 6] &
|
||||||
(1ull << (float_constant_index & 63))) {
|
(1ull << (float_constant_index & 63))) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &= ~(
|
||||||
~(UINT32_C(1)
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatVertex);
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (index >= XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031 &&
|
} else if (index >= XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031 &&
|
||||||
index <= XE_GPU_REG_SHADER_CONSTANT_LOOP_31) {
|
index <= XE_GPU_REG_SHADER_CONSTANT_LOOP_31) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &= ~(
|
current_constant_buffers_up_to_date_ &=
|
||||||
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetBoolLoopConstants);
|
~(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferBoolLoop);
|
||||||
} else if (index >= XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 &&
|
} else if (index >= XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 &&
|
||||||
index <= XE_GPU_REG_SHADER_CONSTANT_FETCH_31_5) {
|
index <= XE_GPU_REG_SHADER_CONSTANT_FETCH_31_5) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &=
|
||||||
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetFetchConstants);
|
~(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFetch);
|
||||||
if (texture_cache_) {
|
if (texture_cache_) {
|
||||||
texture_cache_->TextureFetchConstantWritten(
|
texture_cache_->TextureFetchConstantWritten(
|
||||||
(index - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0) / 6);
|
(index - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0) / 6);
|
||||||
|
@ -1890,24 +1869,8 @@ VulkanCommandProcessor::GetPipelineLayout(size_t texture_count_pixel,
|
||||||
descriptor_set_layouts
|
descriptor_set_layouts
|
||||||
[SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram] =
|
[SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram] =
|
||||||
descriptor_set_layout_shared_memory_and_edram_;
|
descriptor_set_layout_shared_memory_and_edram_;
|
||||||
descriptor_set_layouts
|
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetConstants] =
|
||||||
[SpirvShaderTranslator::kDescriptorSetBoolLoopConstants] =
|
descriptor_set_layout_constants_;
|
||||||
GetSingleTransientDescriptorLayout(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestShader);
|
|
||||||
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetSystemConstants] =
|
|
||||||
GetSingleTransientDescriptorLayout(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferSystemConstants);
|
|
||||||
descriptor_set_layouts
|
|
||||||
[SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel] =
|
|
||||||
GetSingleTransientDescriptorLayout(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferFragment);
|
|
||||||
descriptor_set_layouts
|
|
||||||
[SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex] =
|
|
||||||
GetSingleTransientDescriptorLayout(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestVertex);
|
|
||||||
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetFetchConstants] =
|
|
||||||
GetSingleTransientDescriptorLayout(
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestShader);
|
|
||||||
// Mutable layouts.
|
// Mutable layouts.
|
||||||
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetSamplersVertex] =
|
descriptor_set_layouts[SpirvShaderTranslator::kDescriptorSetSamplersVertex] =
|
||||||
descriptor_set_layout_samplers_vertex;
|
descriptor_set_layout_samplers_vertex;
|
||||||
|
@ -2774,6 +2737,7 @@ bool VulkanCommandProcessor::BeginSubmission(bool is_guest_command) {
|
||||||
sizeof(current_float_constant_map_pixel_));
|
sizeof(current_float_constant_map_pixel_));
|
||||||
std::memset(current_graphics_descriptor_sets_, 0,
|
std::memset(current_graphics_descriptor_sets_, 0,
|
||||||
sizeof(current_graphics_descriptor_sets_));
|
sizeof(current_graphics_descriptor_sets_));
|
||||||
|
current_constant_buffers_up_to_date_ = 0;
|
||||||
current_graphics_descriptor_sets_
|
current_graphics_descriptor_sets_
|
||||||
[SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram] =
|
[SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram] =
|
||||||
shared_memory_and_edram_descriptor_set_;
|
shared_memory_and_edram_descriptor_set_;
|
||||||
|
@ -2797,6 +2761,16 @@ bool VulkanCommandProcessor::BeginSubmission(bool is_guest_command) {
|
||||||
.push_back(used_transient_descriptor.set);
|
.push_back(used_transient_descriptor.set);
|
||||||
single_transient_descriptors_used_.pop_front();
|
single_transient_descriptors_used_.pop_front();
|
||||||
}
|
}
|
||||||
|
while (!constants_transient_descriptors_used_.empty()) {
|
||||||
|
const std::pair<uint64_t, VkDescriptorSet>& used_transient_descriptor =
|
||||||
|
constants_transient_descriptors_used_.front();
|
||||||
|
if (used_transient_descriptor.first > frame_completed_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
constants_transient_descriptors_free_.push_back(
|
||||||
|
used_transient_descriptor.second);
|
||||||
|
constants_transient_descriptors_used_.pop_front();
|
||||||
|
}
|
||||||
while (!texture_transient_descriptor_sets_used_.empty()) {
|
while (!texture_transient_descriptor_sets_used_.empty()) {
|
||||||
const UsedTextureTransientDescriptorSet& used_transient_descriptor_set =
|
const UsedTextureTransientDescriptorSet& used_transient_descriptor_set =
|
||||||
texture_transient_descriptor_sets_used_.front();
|
texture_transient_descriptor_sets_used_.front();
|
||||||
|
@ -3092,6 +3066,8 @@ void VulkanCommandProcessor::ClearTransientDescriptorPools() {
|
||||||
transient_descriptor_allocator_sampler_.Reset();
|
transient_descriptor_allocator_sampler_.Reset();
|
||||||
transient_descriptor_allocator_sampled_image_.Reset();
|
transient_descriptor_allocator_sampled_image_.Reset();
|
||||||
|
|
||||||
|
constants_transient_descriptors_free_.clear();
|
||||||
|
constants_transient_descriptors_used_.clear();
|
||||||
for (std::vector<VkDescriptorSet>& transient_descriptors_free :
|
for (std::vector<VkDescriptorSet>& transient_descriptors_free :
|
||||||
single_transient_descriptors_free_) {
|
single_transient_descriptors_free_) {
|
||||||
transient_descriptors_free.clear();
|
transient_descriptors_free.clear();
|
||||||
|
@ -3520,8 +3496,8 @@ void VulkanCommandProcessor::UpdateSystemConstantValues(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &=
|
||||||
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetSystemConstants);
|
~(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3537,7 +3513,7 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
const ui::vulkan::VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||||
VkDevice device = provider.device();
|
VkDevice device = provider.device();
|
||||||
|
|
||||||
// Invalidate descriptors for changed data.
|
// Invalidate constant buffers and descriptors for changed data.
|
||||||
|
|
||||||
// Float constants.
|
// Float constants.
|
||||||
// These are the constant base addresses/ranges for shaders.
|
// These are the constant base addresses/ranges for shaders.
|
||||||
|
@ -3559,10 +3535,8 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
// If no float constants at all, any buffer can be reused for them, so not
|
// If no float constants at all, any buffer can be reused for them, so not
|
||||||
// invalidating.
|
// invalidating.
|
||||||
if (float_constant_count_vertex) {
|
if (float_constant_count_vertex) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &=
|
||||||
~(
|
~(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatVertex);
|
||||||
UINT32_C(1)
|
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3577,9 +3551,8 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
current_float_constant_map_pixel_[i] =
|
current_float_constant_map_pixel_[i] =
|
||||||
float_constant_map_pixel.float_bitmap[i];
|
float_constant_map_pixel.float_bitmap[i];
|
||||||
if (float_constant_count_pixel) {
|
if (float_constant_count_pixel) {
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &=
|
current_constant_buffers_up_to_date_ &= ~(
|
||||||
~(UINT32_C(1)
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatPixel);
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3588,6 +3561,141 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
sizeof(current_float_constant_map_pixel_));
|
sizeof(current_float_constant_map_pixel_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write the new constant buffers.
|
||||||
|
constexpr uint32_t kAllConstantBuffersMask =
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferCount) - 1;
|
||||||
|
assert_zero(current_constant_buffers_up_to_date_ & ~kAllConstantBuffersMask);
|
||||||
|
if ((current_constant_buffers_up_to_date_ & kAllConstantBuffersMask) !=
|
||||||
|
kAllConstantBuffersMask) {
|
||||||
|
current_graphics_descriptor_set_values_up_to_date_ &=
|
||||||
|
~(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetConstants);
|
||||||
|
size_t uniform_buffer_alignment = size_t(
|
||||||
|
provider.device_properties().limits.minUniformBufferOffsetAlignment);
|
||||||
|
// System constants.
|
||||||
|
if (!(current_constant_buffers_up_to_date_ &
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferSystem))) {
|
||||||
|
VkDescriptorBufferInfo& buffer_info = current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferSystem];
|
||||||
|
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||||
|
frame_current_, sizeof(SpirvShaderTranslator::SystemConstants),
|
||||||
|
uniform_buffer_alignment, buffer_info.buffer, buffer_info.offset);
|
||||||
|
if (!mapping) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer_info.range = sizeof(SpirvShaderTranslator::SystemConstants);
|
||||||
|
std::memcpy(mapping, &system_constants_,
|
||||||
|
sizeof(SpirvShaderTranslator::SystemConstants));
|
||||||
|
current_constant_buffers_up_to_date_ |=
|
||||||
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferSystem;
|
||||||
|
}
|
||||||
|
// Vertex shader float constants.
|
||||||
|
if (!(current_constant_buffers_up_to_date_ &
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatVertex))) {
|
||||||
|
VkDescriptorBufferInfo& buffer_info = current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFloatVertex];
|
||||||
|
// Even if the shader doesn't need any float constants, a valid binding
|
||||||
|
// must still be provided (the pipeline layout always has float constants,
|
||||||
|
// for both the vertex shader and the pixel shader), so if the first draw
|
||||||
|
// in the frame doesn't have float constants at all, still allocate a
|
||||||
|
// dummy buffer.
|
||||||
|
size_t float_constants_size =
|
||||||
|
sizeof(float) * 4 *
|
||||||
|
std::max(float_constant_count_vertex, UINT32_C(1));
|
||||||
|
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||||
|
frame_current_, float_constants_size, uniform_buffer_alignment,
|
||||||
|
buffer_info.buffer, buffer_info.offset);
|
||||||
|
if (!mapping) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer_info.range = VkDeviceSize(float_constants_size);
|
||||||
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
|
uint64_t float_constant_map_entry =
|
||||||
|
current_float_constant_map_vertex_[i];
|
||||||
|
uint32_t float_constant_index;
|
||||||
|
while (xe::bit_scan_forward(float_constant_map_entry,
|
||||||
|
&float_constant_index)) {
|
||||||
|
float_constant_map_entry &= ~(1ull << float_constant_index);
|
||||||
|
std::memcpy(mapping,
|
||||||
|
®s[XE_GPU_REG_SHADER_CONSTANT_000_X + (i << 8) +
|
||||||
|
(float_constant_index << 2)]
|
||||||
|
.f32,
|
||||||
|
sizeof(float) * 4);
|
||||||
|
mapping += sizeof(float) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_constant_buffers_up_to_date_ |=
|
||||||
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatVertex;
|
||||||
|
}
|
||||||
|
// Pixel shader float constants.
|
||||||
|
if (!(current_constant_buffers_up_to_date_ &
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatPixel))) {
|
||||||
|
VkDescriptorBufferInfo& buffer_info = current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFloatPixel];
|
||||||
|
size_t float_constants_size =
|
||||||
|
sizeof(float) * 4 * std::max(float_constant_count_pixel, UINT32_C(1));
|
||||||
|
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||||
|
frame_current_, float_constants_size, uniform_buffer_alignment,
|
||||||
|
buffer_info.buffer, buffer_info.offset);
|
||||||
|
if (!mapping) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer_info.range = VkDeviceSize(float_constants_size);
|
||||||
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
|
uint64_t float_constant_map_entry =
|
||||||
|
current_float_constant_map_pixel_[i];
|
||||||
|
uint32_t float_constant_index;
|
||||||
|
while (xe::bit_scan_forward(float_constant_map_entry,
|
||||||
|
&float_constant_index)) {
|
||||||
|
float_constant_map_entry &= ~(1ull << float_constant_index);
|
||||||
|
std::memcpy(mapping,
|
||||||
|
®s[XE_GPU_REG_SHADER_CONSTANT_256_X + (i << 8) +
|
||||||
|
(float_constant_index << 2)]
|
||||||
|
.f32,
|
||||||
|
sizeof(float) * 4);
|
||||||
|
mapping += sizeof(float) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_constant_buffers_up_to_date_ |=
|
||||||
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFloatPixel;
|
||||||
|
}
|
||||||
|
// Bool and loop constants.
|
||||||
|
if (!(current_constant_buffers_up_to_date_ &
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferBoolLoop))) {
|
||||||
|
VkDescriptorBufferInfo& buffer_info = current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferBoolLoop];
|
||||||
|
constexpr size_t kBoolLoopConstantsSize = sizeof(uint32_t) * (8 + 32);
|
||||||
|
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||||
|
frame_current_, kBoolLoopConstantsSize, uniform_buffer_alignment,
|
||||||
|
buffer_info.buffer, buffer_info.offset);
|
||||||
|
if (!mapping) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer_info.range = VkDeviceSize(kBoolLoopConstantsSize);
|
||||||
|
std::memcpy(mapping, ®s[XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031].u32,
|
||||||
|
kBoolLoopConstantsSize);
|
||||||
|
current_constant_buffers_up_to_date_ |=
|
||||||
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferBoolLoop;
|
||||||
|
}
|
||||||
|
// Fetch constants.
|
||||||
|
if (!(current_constant_buffers_up_to_date_ &
|
||||||
|
(UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFetch))) {
|
||||||
|
VkDescriptorBufferInfo& buffer_info = current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferFetch];
|
||||||
|
constexpr size_t kFetchConstantsSize = sizeof(uint32_t) * 6 * 32;
|
||||||
|
uint8_t* mapping = uniform_buffer_pool_->Request(
|
||||||
|
frame_current_, kFetchConstantsSize, uniform_buffer_alignment,
|
||||||
|
buffer_info.buffer, buffer_info.offset);
|
||||||
|
if (!mapping) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer_info.range = VkDeviceSize(kFetchConstantsSize);
|
||||||
|
std::memcpy(mapping, ®s[XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0].u32,
|
||||||
|
kFetchConstantsSize);
|
||||||
|
current_constant_buffers_up_to_date_ |=
|
||||||
|
UINT32_C(1) << SpirvShaderTranslator::kConstantBufferFetch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Textures and samplers.
|
// Textures and samplers.
|
||||||
const std::vector<VulkanShader::SamplerBinding>& samplers_vertex =
|
const std::vector<VulkanShader::SamplerBinding>& samplers_vertex =
|
||||||
vertex_shader->GetSamplerBindingsAfterTranslation();
|
vertex_shader->GetSamplerBindingsAfterTranslation();
|
||||||
|
@ -3694,158 +3802,57 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
|
|
||||||
// Write the new descriptor sets.
|
// Write the new descriptor sets.
|
||||||
|
|
||||||
VkWriteDescriptorSet
|
// Consecutive bindings updated via a single VkWriteDescriptorSet must have
|
||||||
write_descriptor_sets[SpirvShaderTranslator::kDescriptorSetCount];
|
// identical stage flags, but for the constants they vary.
|
||||||
|
std::array<VkWriteDescriptorSet,
|
||||||
|
SpirvShaderTranslator::kDescriptorSetCount - 1 +
|
||||||
|
SpirvShaderTranslator::kConstantBufferCount>
|
||||||
|
write_descriptor_sets;
|
||||||
uint32_t write_descriptor_set_count = 0;
|
uint32_t write_descriptor_set_count = 0;
|
||||||
uint32_t write_descriptor_set_bits = 0;
|
uint32_t write_descriptor_set_bits = 0;
|
||||||
assert_not_zero(
|
assert_not_zero(
|
||||||
current_graphics_descriptor_set_values_up_to_date_ &
|
current_graphics_descriptor_set_values_up_to_date_ &
|
||||||
(UINT32_C(1)
|
(UINT32_C(1)
|
||||||
<< SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram));
|
<< SpirvShaderTranslator::kDescriptorSetSharedMemoryAndEdram));
|
||||||
// Bool and loop constants.
|
// Constant buffers.
|
||||||
VkDescriptorBufferInfo buffer_info_bool_loop_constants;
|
|
||||||
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
||||||
(UINT32_C(1)
|
(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetConstants))) {
|
||||||
<< SpirvShaderTranslator::kDescriptorSetBoolLoopConstants))) {
|
VkDescriptorSet constants_descriptor_set;
|
||||||
VkWriteDescriptorSet& write_bool_loop_constants =
|
if (!constants_transient_descriptors_free_.empty()) {
|
||||||
write_descriptor_sets[write_descriptor_set_count++];
|
constants_descriptor_set = constants_transient_descriptors_free_.back();
|
||||||
constexpr size_t kBoolLoopConstantsSize = sizeof(uint32_t) * (8 + 32);
|
constants_transient_descriptors_free_.pop_back();
|
||||||
uint8_t* mapping_bool_loop_constants = WriteTransientUniformBufferBinding(
|
} else {
|
||||||
kBoolLoopConstantsSize,
|
constants_descriptor_set =
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestShader,
|
transient_descriptor_allocator_uniform_buffer_.Allocate(
|
||||||
buffer_info_bool_loop_constants, write_bool_loop_constants);
|
descriptor_set_layout_constants_,
|
||||||
if (!mapping_bool_loop_constants) {
|
SpirvShaderTranslator::kConstantBufferCount);
|
||||||
return false;
|
if (constants_descriptor_set == VK_NULL_HANDLE) {
|
||||||
}
|
return false;
|
||||||
std::memcpy(mapping_bool_loop_constants,
|
|
||||||
®s[XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031].u32,
|
|
||||||
kBoolLoopConstantsSize);
|
|
||||||
write_descriptor_set_bits |=
|
|
||||||
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetBoolLoopConstants;
|
|
||||||
current_graphics_descriptor_sets_
|
|
||||||
[SpirvShaderTranslator::kDescriptorSetBoolLoopConstants] =
|
|
||||||
write_bool_loop_constants.dstSet;
|
|
||||||
}
|
|
||||||
// System constants.
|
|
||||||
VkDescriptorBufferInfo buffer_info_system_constants;
|
|
||||||
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
|
||||||
(UINT32_C(1)
|
|
||||||
<< SpirvShaderTranslator::kDescriptorSetSystemConstants))) {
|
|
||||||
VkWriteDescriptorSet& write_system_constants =
|
|
||||||
write_descriptor_sets[write_descriptor_set_count++];
|
|
||||||
uint8_t* mapping_system_constants = WriteTransientUniformBufferBinding(
|
|
||||||
sizeof(SpirvShaderTranslator::SystemConstants),
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferSystemConstants,
|
|
||||||
buffer_info_system_constants, write_system_constants);
|
|
||||||
if (!mapping_system_constants) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::memcpy(mapping_system_constants, &system_constants_,
|
|
||||||
sizeof(SpirvShaderTranslator::SystemConstants));
|
|
||||||
write_descriptor_set_bits |=
|
|
||||||
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetSystemConstants;
|
|
||||||
current_graphics_descriptor_sets_
|
|
||||||
[SpirvShaderTranslator::kDescriptorSetSystemConstants] =
|
|
||||||
write_system_constants.dstSet;
|
|
||||||
}
|
|
||||||
// Pixel shader float constants.
|
|
||||||
VkDescriptorBufferInfo buffer_info_float_constant_pixel;
|
|
||||||
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
|
||||||
(UINT32_C(1)
|
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel))) {
|
|
||||||
// Even if the shader doesn't need any float constants, a valid binding must
|
|
||||||
// still be provided (the pipeline layout always has float constants, for
|
|
||||||
// both the vertex shader and the pixel shader), so if the first draw in the
|
|
||||||
// frame doesn't have float constants at all, still allocate an empty
|
|
||||||
// buffer.
|
|
||||||
VkWriteDescriptorSet& write_float_constants_pixel =
|
|
||||||
write_descriptor_sets[write_descriptor_set_count++];
|
|
||||||
uint8_t* mapping_float_constants_pixel = WriteTransientUniformBufferBinding(
|
|
||||||
sizeof(float) * 4 * std::max(float_constant_count_pixel, UINT32_C(1)),
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferFragment,
|
|
||||||
buffer_info_float_constant_pixel, write_float_constants_pixel);
|
|
||||||
if (!mapping_float_constants_pixel) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
|
||||||
uint64_t float_constant_map_entry = current_float_constant_map_pixel_[i];
|
|
||||||
uint32_t float_constant_index;
|
|
||||||
while (xe::bit_scan_forward(float_constant_map_entry,
|
|
||||||
&float_constant_index)) {
|
|
||||||
float_constant_map_entry &= ~(1ull << float_constant_index);
|
|
||||||
std::memcpy(mapping_float_constants_pixel,
|
|
||||||
®s[XE_GPU_REG_SHADER_CONSTANT_256_X + (i << 8) +
|
|
||||||
(float_constant_index << 2)]
|
|
||||||
.f32,
|
|
||||||
sizeof(float) * 4);
|
|
||||||
mapping_float_constants_pixel += sizeof(float) * 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_descriptor_set_bits |=
|
constants_transient_descriptors_used_.emplace_back(
|
||||||
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel;
|
frame_current_, constants_descriptor_set);
|
||||||
current_graphics_descriptor_sets_
|
// Consecutive bindings updated via a single VkWriteDescriptorSet must have
|
||||||
[SpirvShaderTranslator::kDescriptorSetFloatConstantsPixel] =
|
// identical stage flags, but for the constants they vary.
|
||||||
write_float_constants_pixel.dstSet;
|
for (uint32_t i = 0; i < SpirvShaderTranslator::kConstantBufferCount; ++i) {
|
||||||
}
|
VkWriteDescriptorSet& write_constants =
|
||||||
// Vertex shader float constants.
|
write_descriptor_sets[write_descriptor_set_count++];
|
||||||
VkDescriptorBufferInfo buffer_info_float_constant_vertex;
|
write_constants.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
write_constants.pNext = nullptr;
|
||||||
(UINT32_C(1)
|
write_constants.dstSet = constants_descriptor_set;
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex))) {
|
write_constants.dstBinding = i;
|
||||||
VkWriteDescriptorSet& write_float_constants_vertex =
|
write_constants.dstArrayElement = 0;
|
||||||
write_descriptor_sets[write_descriptor_set_count++];
|
write_constants.descriptorCount = 1;
|
||||||
uint8_t* mapping_float_constants_vertex =
|
write_constants.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
WriteTransientUniformBufferBinding(
|
write_constants.pImageInfo = nullptr;
|
||||||
sizeof(float) * 4 *
|
write_constants.pBufferInfo = ¤t_constant_buffer_infos_[i];
|
||||||
std::max(float_constant_count_vertex, UINT32_C(1)),
|
write_constants.pTexelBufferView = nullptr;
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestVertex,
|
|
||||||
buffer_info_float_constant_vertex, write_float_constants_vertex);
|
|
||||||
if (!mapping_float_constants_vertex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
|
||||||
uint64_t float_constant_map_entry = current_float_constant_map_vertex_[i];
|
|
||||||
uint32_t float_constant_index;
|
|
||||||
while (xe::bit_scan_forward(float_constant_map_entry,
|
|
||||||
&float_constant_index)) {
|
|
||||||
float_constant_map_entry &= ~(1ull << float_constant_index);
|
|
||||||
std::memcpy(mapping_float_constants_vertex,
|
|
||||||
®s[XE_GPU_REG_SHADER_CONSTANT_000_X + (i << 8) +
|
|
||||||
(float_constant_index << 2)]
|
|
||||||
.f32,
|
|
||||||
sizeof(float) * 4);
|
|
||||||
mapping_float_constants_vertex += sizeof(float) * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write_descriptor_set_bits |=
|
write_descriptor_set_bits |=
|
||||||
UINT32_C(1)
|
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetConstants;
|
||||||
<< SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex;
|
|
||||||
current_graphics_descriptor_sets_
|
current_graphics_descriptor_sets_
|
||||||
[SpirvShaderTranslator::kDescriptorSetFloatConstantsVertex] =
|
[SpirvShaderTranslator::kDescriptorSetConstants] =
|
||||||
write_float_constants_vertex.dstSet;
|
constants_descriptor_set;
|
||||||
}
|
|
||||||
// Fetch constants.
|
|
||||||
VkDescriptorBufferInfo buffer_info_fetch_constants;
|
|
||||||
if (!(current_graphics_descriptor_set_values_up_to_date_ &
|
|
||||||
(UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetFetchConstants))) {
|
|
||||||
VkWriteDescriptorSet& write_fetch_constants =
|
|
||||||
write_descriptor_sets[write_descriptor_set_count++];
|
|
||||||
constexpr size_t kFetchConstantsSize = sizeof(uint32_t) * 6 * 32;
|
|
||||||
uint8_t* mapping_fetch_constants = WriteTransientUniformBufferBinding(
|
|
||||||
kFetchConstantsSize,
|
|
||||||
SingleTransientDescriptorLayout::kUniformBufferGuestShader,
|
|
||||||
buffer_info_fetch_constants, write_fetch_constants);
|
|
||||||
if (!mapping_fetch_constants) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::memcpy(mapping_fetch_constants,
|
|
||||||
®s[XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0].u32,
|
|
||||||
kFetchConstantsSize);
|
|
||||||
write_descriptor_set_bits |=
|
|
||||||
UINT32_C(1) << SpirvShaderTranslator::kDescriptorSetFetchConstants;
|
|
||||||
current_graphics_descriptor_sets_
|
|
||||||
[SpirvShaderTranslator::kDescriptorSetFetchConstants] =
|
|
||||||
write_fetch_constants.dstSet;
|
|
||||||
}
|
}
|
||||||
// Vertex shader samplers.
|
// Vertex shader samplers.
|
||||||
if (write_vertex_samplers) {
|
if (write_vertex_samplers) {
|
||||||
|
@ -3926,7 +3933,7 @@ bool VulkanCommandProcessor::UpdateBindings(const VulkanShader* vertex_shader,
|
||||||
// Write.
|
// Write.
|
||||||
if (write_descriptor_set_count) {
|
if (write_descriptor_set_count) {
|
||||||
dfn.vkUpdateDescriptorSets(device, write_descriptor_set_count,
|
dfn.vkUpdateDescriptorSets(device, write_descriptor_set_count,
|
||||||
write_descriptor_sets, 0, nullptr);
|
write_descriptor_sets.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
// Only make valid if all descriptor sets have been allocated and written
|
// Only make valid if all descriptor sets have been allocated and written
|
||||||
// successfully.
|
// successfully.
|
||||||
|
|
|
@ -49,10 +49,6 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
public:
|
public:
|
||||||
// Single-descriptor layouts for use within a single frame.
|
// Single-descriptor layouts for use within a single frame.
|
||||||
enum class SingleTransientDescriptorLayout {
|
enum class SingleTransientDescriptorLayout {
|
||||||
kUniformBufferGuestVertex,
|
|
||||||
kUniformBufferFragment,
|
|
||||||
kUniformBufferGuestShader,
|
|
||||||
kUniformBufferSystemConstants,
|
|
||||||
kUniformBufferCompute,
|
kUniformBufferCompute,
|
||||||
kStorageBufferCompute,
|
kStorageBufferCompute,
|
||||||
kCount,
|
kCount,
|
||||||
|
@ -530,6 +526,7 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
VkDescriptorSetLayout descriptor_set_layout_empty_ = VK_NULL_HANDLE;
|
VkDescriptorSetLayout descriptor_set_layout_empty_ = VK_NULL_HANDLE;
|
||||||
VkDescriptorSetLayout descriptor_set_layout_shared_memory_and_edram_ =
|
VkDescriptorSetLayout descriptor_set_layout_shared_memory_and_edram_ =
|
||||||
VK_NULL_HANDLE;
|
VK_NULL_HANDLE;
|
||||||
|
VkDescriptorSetLayout descriptor_set_layout_constants_ = VK_NULL_HANDLE;
|
||||||
std::array<VkDescriptorSetLayout,
|
std::array<VkDescriptorSetLayout,
|
||||||
size_t(SingleTransientDescriptorLayout::kCount)>
|
size_t(SingleTransientDescriptorLayout::kCount)>
|
||||||
descriptor_set_layouts_single_transient_{};
|
descriptor_set_layouts_single_transient_{};
|
||||||
|
@ -551,6 +548,10 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
std::array<std::vector<VkDescriptorSet>,
|
std::array<std::vector<VkDescriptorSet>,
|
||||||
size_t(SingleTransientDescriptorLayout::kCount)>
|
size_t(SingleTransientDescriptorLayout::kCount)>
|
||||||
single_transient_descriptors_free_;
|
single_transient_descriptors_free_;
|
||||||
|
// <Usage frame, set>.
|
||||||
|
std::deque<std::pair<uint64_t, VkDescriptorSet>>
|
||||||
|
constants_transient_descriptors_used_;
|
||||||
|
std::vector<VkDescriptorSet> constants_transient_descriptors_free_;
|
||||||
|
|
||||||
ui::vulkan::SingleTypeDescriptorSetAllocator
|
ui::vulkan::SingleTypeDescriptorSetAllocator
|
||||||
transient_descriptor_allocator_sampled_image_;
|
transient_descriptor_allocator_sampled_image_;
|
||||||
|
@ -701,6 +702,11 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
|
|
||||||
// Pipeline layout of the current guest graphics pipeline.
|
// Pipeline layout of the current guest graphics pipeline.
|
||||||
const PipelineLayout* current_guest_graphics_pipeline_layout_;
|
const PipelineLayout* current_guest_graphics_pipeline_layout_;
|
||||||
|
VkDescriptorBufferInfo current_constant_buffer_infos_
|
||||||
|
[SpirvShaderTranslator::kConstantBufferCount];
|
||||||
|
// Whether up-to-date data has been written to constant (uniform) buffers, and
|
||||||
|
// the buffer infos in current_constant_buffer_infos_ point to them.
|
||||||
|
uint32_t current_constant_buffers_up_to_date_;
|
||||||
VkDescriptorSet current_graphics_descriptor_sets_
|
VkDescriptorSet current_graphics_descriptor_sets_
|
||||||
[SpirvShaderTranslator::kDescriptorSetCount];
|
[SpirvShaderTranslator::kDescriptorSetCount];
|
||||||
// Whether descriptor sets in current_graphics_descriptor_sets_ point to
|
// Whether descriptor sets in current_graphics_descriptor_sets_ point to
|
||||||
|
|
Loading…
Reference in New Issue