[Vulkan] Use locally generated texture binding indices instead of GPU indices

This commit is contained in:
DrChat 2018-02-22 19:47:51 -06:00
parent da4cf1bc80
commit 77da785d70
5 changed files with 68 additions and 31 deletions

View File

@ -54,7 +54,9 @@ void ShaderTranslator::Reset() {
register_count_ = 64; register_count_ = 64;
total_attrib_count_ = 0; total_attrib_count_ = 0;
vertex_bindings_.clear(); vertex_bindings_.clear();
unique_vertex_bindings_ = 0;
texture_bindings_.clear(); texture_bindings_.clear();
unique_texture_bindings_ = 0;
std::memset(&constant_register_map_, 0, sizeof(constant_register_map_)); std::memset(&constant_register_map_, 0, sizeof(constant_register_map_));
for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) { for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) {
writes_color_targets_[i] = false; writes_color_targets_[i] = false;
@ -300,7 +302,7 @@ void ShaderTranslator::GatherVertexBindingInformation(
if (!attrib) { if (!attrib) {
assert_not_zero(fetch_instr.attributes.stride); assert_not_zero(fetch_instr.attributes.stride);
VertexBinding vertex_binding; VertexBinding vertex_binding;
vertex_binding.binding_index = static_cast<int>(vertex_bindings_.size()); vertex_binding.binding_index = int(vertex_bindings_.size());
vertex_binding.fetch_constant = op.fetch_constant_index(); vertex_binding.fetch_constant = op.fetch_constant_index();
vertex_binding.stride_words = fetch_instr.attributes.stride; vertex_binding.stride_words = fetch_instr.attributes.stride;
vertex_binding.attributes.push_back({}); vertex_binding.attributes.push_back({});
@ -328,9 +330,23 @@ void ShaderTranslator::GatherTextureBindingInformation(
break; break;
} }
Shader::TextureBinding binding; Shader::TextureBinding binding;
binding.binding_index = texture_bindings_.size(); binding.binding_index = -1;
ParseTextureFetchInstruction(op, &binding.fetch_instr); ParseTextureFetchInstruction(op, &binding.fetch_instr);
binding.fetch_constant = binding.fetch_instr.operands[1].storage_index; binding.fetch_constant = binding.fetch_instr.operands[1].storage_index;
// Check and see if this fetch constant was previously used...
for (auto& tex_binding : texture_bindings_) {
if (tex_binding.fetch_constant == binding.fetch_constant) {
binding.binding_index = tex_binding.binding_index;
break;
}
}
if (binding.binding_index == -1) {
// Assign a unique binding index.
binding.binding_index = unique_texture_bindings_++;
}
texture_bindings_.emplace_back(std::move(binding)); texture_bindings_.emplace_back(std::move(binding));
} }

View File

@ -212,6 +212,9 @@ class ShaderTranslator {
int total_attrib_count_ = 0; int total_attrib_count_ = 0;
std::vector<Shader::VertexBinding> vertex_bindings_; std::vector<Shader::VertexBinding> vertex_bindings_;
std::vector<Shader::TextureBinding> texture_bindings_; std::vector<Shader::TextureBinding> texture_bindings_;
uint32_t unique_vertex_bindings_ = 0;
uint32_t unique_texture_bindings_ = 0;
Shader::ConstantRegisterMap constant_register_map_ = {0}; Shader::ConstantRegisterMap constant_register_map_ = {0};
bool writes_color_targets_[4] = {false, false, false, false}; bool writes_color_targets_[4] = {false, false, false, false};

View File

@ -189,32 +189,42 @@ void SpirvShaderTranslator::StartTranslation() {
push_consts_ = b.createVariable(spv::StorageClass::StorageClassPushConstant, push_consts_ = b.createVariable(spv::StorageClass::StorageClassPushConstant,
push_constants_type, "push_consts"); push_constants_type, "push_consts");
image_2d_type_ = if (!texture_bindings().empty()) {
b.makeImageType(float_type_, spv::Dim::Dim2D, false, false, false, 1, image_2d_type_ =
spv::ImageFormat::ImageFormatUnknown); b.makeImageType(float_type_, spv::Dim::Dim2D, false, false, false, 1,
image_3d_type_ = spv::ImageFormat::ImageFormatUnknown);
b.makeImageType(float_type_, spv::Dim::Dim3D, false, false, false, 1, image_3d_type_ =
spv::ImageFormat::ImageFormatUnknown); b.makeImageType(float_type_, spv::Dim::Dim3D, false, false, false, 1,
image_cube_type_ = spv::ImageFormat::ImageFormatUnknown);
b.makeImageType(float_type_, spv::Dim::DimCube, false, false, false, 1, image_cube_type_ =
spv::ImageFormat::ImageFormatUnknown); b.makeImageType(float_type_, spv::Dim::DimCube, false, false, false, 1,
spv::ImageFormat::ImageFormatUnknown);
// Texture bindings // Texture bindings
Id tex_t[] = {b.makeSampledImageType(image_2d_type_), Id tex_t[] = {b.makeSampledImageType(image_2d_type_),
b.makeSampledImageType(image_3d_type_), b.makeSampledImageType(image_3d_type_),
b.makeSampledImageType(image_cube_type_)}; b.makeSampledImageType(image_cube_type_)};
Id tex_a_t[] = {b.makeArrayType(tex_t[0], b.makeUintConstant(32), 0), uint32_t num_tex_bindings = uint32_t(texture_bindings().size());
b.makeArrayType(tex_t[1], b.makeUintConstant(32), 0), Id tex_a_t[] = {
b.makeArrayType(tex_t[2], b.makeUintConstant(32), 0)}; b.makeArrayType(tex_t[0], b.makeUintConstant(num_tex_bindings), 0),
b.makeArrayType(tex_t[1], b.makeUintConstant(num_tex_bindings), 0),
b.makeArrayType(tex_t[2], b.makeUintConstant(num_tex_bindings), 0)};
// Create 3 texture types, all aliased on the same binding // Create 3 texture types, all aliased on the same binding
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
tex_[i] = b.createVariable(spv::StorageClass::StorageClassUniformConstant, tex_[i] = b.createVariable(
tex_a_t[i], spv::StorageClass::StorageClassUniformConstant, tex_a_t[i],
xe::format_string("textures%dD", i + 2).c_str()); xe::format_string("textures%dD", i + 2).c_str());
b.addDecoration(tex_[i], spv::Decoration::DecorationDescriptorSet, 1); b.addDecoration(tex_[i], spv::Decoration::DecorationDescriptorSet, 1);
b.addDecoration(tex_[i], spv::Decoration::DecorationBinding, 0); b.addDecoration(tex_[i], spv::Decoration::DecorationBinding, 0);
}
// Set up the map from binding -> ssbo index
for (const auto& binding : texture_bindings()) {
tex_binding_map_[binding.fetch_constant] =
uint32_t(binding.binding_index);
}
} }
// Interpolators. // Interpolators.
@ -1760,7 +1770,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
switch (instr.opcode) { switch (instr.opcode) {
case FetchOpcode::kTextureFetch: { case FetchOpcode::kTextureFetch: {
auto texture_index = b.makeUintConstant(instr.operands[1].storage_index); auto texture_index =
b.makeUintConstant(tex_binding_map_[instr.operands[1].storage_index]);
auto texture_ptr = auto texture_ptr =
b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, b.createAccessChain(spv::StorageClass::StorageClassUniformConstant,
tex_[dim_idx], std::vector<Id>({texture_index})); tex_[dim_idx], std::vector<Id>({texture_index}));
@ -1829,7 +1840,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
false, false, false, false, params); false, false, false, false, params);
} break; } break;
case FetchOpcode::kGetTextureGradients: { case FetchOpcode::kGetTextureGradients: {
auto texture_index = b.makeUintConstant(instr.operands[2].storage_index); auto texture_index =
b.makeUintConstant(tex_binding_map_[instr.operands[2].storage_index]);
auto texture_ptr = auto texture_ptr =
b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, b.createAccessChain(spv::StorageClass::StorageClassUniformConstant,
tex_[dim_idx], std::vector<Id>({texture_index})); tex_[dim_idx], std::vector<Id>({texture_index}));
@ -1849,7 +1861,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
} break; } break;
case FetchOpcode::kGetTextureWeights: { case FetchOpcode::kGetTextureWeights: {
// fract(src0 * textureSize); // fract(src0 * textureSize);
auto texture_index = b.makeUintConstant(instr.operands[1].storage_index); auto texture_index =
b.makeUintConstant(tex_binding_map_[instr.operands[1].storage_index]);
auto texture_ptr = auto texture_ptr =
b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, b.createAccessChain(spv::StorageClass::StorageClassUniformConstant,
tex_[dim_idx], std::vector<Id>({texture_index})); tex_[dim_idx], std::vector<Id>({texture_index}));

View File

@ -12,6 +12,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "third_party/glslang-spirv/SpvBuilder.h" #include "third_party/glslang-spirv/SpvBuilder.h"
@ -157,8 +158,9 @@ class SpirvShaderTranslator : public ShaderTranslator {
spv::Id frag_outputs_ = 0, frag_depth_ = 0; spv::Id frag_outputs_ = 0, frag_depth_ = 0;
spv::Id samplers_ = 0; spv::Id samplers_ = 0;
spv::Id tex_[3] = {0}; // Images {2D, 3D, Cube} spv::Id tex_[3] = {0}; // Images {2D, 3D, Cube}
spv::Id vtx_ = 0; // Vertex buffer array (32 runtime arrays) std::unordered_map<uint32_t, uint32_t> tex_binding_map_;
std::map<uint32_t, uint32_t> vtx_binding_map_; spv::Id vtx_ = 0; // Vertex buffer array (32 runtime arrays)
std::unordered_map<uint32_t, uint32_t> vtx_binding_map_;
// SPIR-V IDs that are part of the in/out interface. // SPIR-V IDs that are part of the in/out interface.
std::vector<spv::Id> interface_ids_; std::vector<spv::Id> interface_ids_;

View File

@ -1442,11 +1442,14 @@ bool TextureCache::SetupTextureBinding(VkCommandBuffer command_buffer,
&update_set_info->image_writes[update_set_info->image_write_count]; &update_set_info->image_writes[update_set_info->image_write_count];
update_set_info->image_write_count++; update_set_info->image_write_count++;
// Sanity check, we only have 32 binding slots.
assert(binding.binding_index < 32);
image_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; image_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
image_write->pNext = nullptr; image_write->pNext = nullptr;
// image_write->dstSet is set later... // image_write->dstSet is set later...
image_write->dstBinding = 0; image_write->dstBinding = 0;
image_write->dstArrayElement = binding.fetch_constant; image_write->dstArrayElement = uint32_t(binding.binding_index);
image_write->descriptorCount = 1; image_write->descriptorCount = 1;
image_write->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; image_write->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
image_write->pImageInfo = image_info; image_write->pImageInfo = image_info;