summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/backend/spirv/emit_context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp86
1 files changed, 80 insertions, 6 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 3c84e6466..723455462 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -7,11 +7,14 @@
#include <climits>
#include <string_view>
+#include <boost/container/static_vector.hpp>
+
#include <fmt/format.h>
#include "common/common_types.h"
#include "common/div_ceil.h"
#include "shader_recompiler/backend/spirv/emit_context.h"
+#include "shader_recompiler/backend/spirv/emit_spirv.h"
namespace Shader::Backend::SPIRV {
namespace {
@@ -474,8 +477,9 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie
EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_info_,
IR::Program& program, Bindings& bindings)
- : Sirit::Module(profile_.supported_spirv), profile{profile_},
- runtime_info{runtime_info_}, stage{program.stage} {
+ : Sirit::Module(profile_.supported_spirv), profile{profile_}, runtime_info{runtime_info_},
+ stage{program.stage}, texture_rescaling_index{bindings.texture_scaling_index},
+ image_rescaling_index{bindings.image_scaling_index} {
const bool is_unified{profile.unified_descriptor_binding};
u32& uniform_binding{is_unified ? bindings.unified : bindings.uniform_buffer};
u32& storage_binding{is_unified ? bindings.unified : bindings.storage_buffer};
@@ -492,10 +496,11 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
DefineStorageBuffers(program.info, storage_binding);
DefineTextureBuffers(program.info, texture_binding);
DefineImageBuffers(program.info, image_binding);
- DefineTextures(program.info, texture_binding);
- DefineImages(program.info, image_binding);
+ DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
+ DefineImages(program.info, image_binding, bindings.image_scaling_index);
DefineAttributeMemAccess(program.info);
DefineGlobalMemoryFunctions(program.info);
+ DefineRescalingInput(program.info);
}
EmitContext::~EmitContext() = default;
@@ -996,6 +1001,73 @@ void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
define(&StorageDefinitions::U32x4, storage_types.U32x4, U32[4], sizeof(u32[4]));
}
+void EmitContext::DefineRescalingInput(const Info& info) {
+ if (!info.uses_rescaling_uniform) {
+ return;
+ }
+ if (profile.unified_descriptor_binding) {
+ DefineRescalingInputPushConstant();
+ } else {
+ DefineRescalingInputUniformConstant();
+ }
+}
+
+void EmitContext::DefineRescalingInputPushConstant() {
+ boost::container::static_vector<Id, 3> members{};
+ u32 member_index{0};
+
+ rescaling_textures_type = TypeArray(U32[1], Const(4u));
+ Decorate(rescaling_textures_type, spv::Decoration::ArrayStride, 4u);
+ members.push_back(rescaling_textures_type);
+ rescaling_textures_member_index = member_index++;
+
+ rescaling_images_type = TypeArray(U32[1], Const(NUM_IMAGE_SCALING_WORDS));
+ Decorate(rescaling_images_type, spv::Decoration::ArrayStride, 4u);
+ members.push_back(rescaling_images_type);
+ rescaling_images_member_index = member_index++;
+
+ if (stage != Stage::Compute) {
+ members.push_back(F32[1]);
+ rescaling_downfactor_member_index = member_index++;
+ }
+ const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))};
+ Decorate(push_constant_struct, spv::Decoration::Block);
+ Name(push_constant_struct, "ResolutionInfo");
+
+ MemberDecorate(push_constant_struct, rescaling_textures_member_index, spv::Decoration::Offset,
+ static_cast<u32>(offsetof(RescalingLayout, rescaling_textures)));
+ MemberName(push_constant_struct, rescaling_textures_member_index, "rescaling_textures");
+
+ MemberDecorate(push_constant_struct, rescaling_images_member_index, spv::Decoration::Offset,
+ static_cast<u32>(offsetof(RescalingLayout, rescaling_images)));
+ MemberName(push_constant_struct, rescaling_images_member_index, "rescaling_images");
+
+ if (stage != Stage::Compute) {
+ MemberDecorate(push_constant_struct, rescaling_downfactor_member_index,
+ spv::Decoration::Offset,
+ static_cast<u32>(offsetof(RescalingLayout, down_factor)));
+ MemberName(push_constant_struct, rescaling_downfactor_member_index, "down_factor");
+ }
+ const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)};
+ rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant);
+ Name(rescaling_push_constants, "rescaling_push_constants");
+
+ if (profile.supported_spirv >= 0x00010400) {
+ interfaces.push_back(rescaling_push_constants);
+ }
+}
+
+void EmitContext::DefineRescalingInputUniformConstant() {
+ const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, F32[4])};
+ rescaling_uniform_constant =
+ AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant);
+ Decorate(rescaling_uniform_constant, spv::Decoration::Location, 0u);
+
+ if (profile.supported_spirv >= 0x00010400) {
+ interfaces.push_back(rescaling_uniform_constant);
+ }
+}
+
void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
if (info.constant_buffer_descriptors.empty()) {
return;
@@ -1184,7 +1256,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
}
}
-void EmitContext::DefineTextures(const Info& info, u32& binding) {
+void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_index) {
textures.reserve(info.texture_descriptors.size());
for (const TextureDescriptor& desc : info.texture_descriptors) {
const Id image_type{ImageType(*this, desc)};
@@ -1206,13 +1278,14 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) {
interfaces.push_back(id);
}
++binding;
+ ++scaling_index;
}
if (info.uses_atomic_image_u32) {
image_u32 = TypePointer(spv::StorageClass::Image, U32[1]);
}
}
-void EmitContext::DefineImages(const Info& info, u32& binding) {
+void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_index) {
images.reserve(info.image_descriptors.size());
for (const ImageDescriptor& desc : info.image_descriptors) {
if (desc.count != 1) {
@@ -1233,6 +1306,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding) {
interfaces.push_back(id);
}
++binding;
+ ++scaling_index;
}
}