aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp34
-rw-r--r--src/shader_recompiler/shader_info.h9
-rw-r--r--src/video_core/renderer_opengl/gl_compute_pipeline.cpp25
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp25
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp22
6 files changed, 82 insertions, 55 deletions
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index 514cd9b2b6..db8f1ac716 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -345,7 +345,8 @@ static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr
// Cached variants of existing helpers
// A handle computed per draw has no descriptor to read at translation time: assume an ordinary
-// floating-point 2D texture, the instruction's own type deciding the rest.
+// floating-point 2D texture, the instruction's own type deciding the rest (see the TexturePass
+// ImageQueryDimensions case, which has none).
static inline TextureType ReadTextureTypeCached(Environment& env, const ConstBufferAddr& cbuf) {
if (cbuf.handle_program != ~0U) return TextureType::Color2D;
return env.ReadTextureType(GetTextureHandleCached(env, cbuf));
@@ -1010,7 +1011,8 @@ public:
desc.secondary_cbuf_offset == existing.secondary_cbuf_offset &&
desc.secondary_shift_left == existing.secondary_shift_left &&
desc.count == existing.count && desc.size_shift == existing.size_shift &&
- desc.has_secondary == existing.has_secondary;
+ desc.has_secondary == existing.has_secondary &&
+ desc.handle_program == existing.handle_program;
});
}
@@ -1018,7 +1020,8 @@ public:
const u32 index{Add(image_buffer_descriptors, desc, [&desc](const auto& existing) {
return desc.format == existing.format && desc.cbuf_index == existing.cbuf_index &&
desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count &&
- desc.size_shift == existing.size_shift;
+ desc.size_shift == existing.size_shift &&
+ desc.handle_program == existing.handle_program;
})};
image_buffer_descriptors[index].is_written |= desc.is_written;
image_buffer_descriptors[index].is_read |= desc.is_read;
@@ -1050,7 +1053,8 @@ public:
return desc.type == existing.type && desc.format == existing.format &&
desc.cbuf_index == existing.cbuf_index &&
desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count &&
- desc.size_shift == existing.size_shift;
+ desc.size_shift == existing.size_shift &&
+ desc.handle_program == existing.handle_program;
})};
image_descriptors[index].is_written |= desc.is_written;
image_descriptors[index].is_read |= desc.is_read;
@@ -1186,6 +1190,18 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
has_last_is_integer = true;
return last_is_integer;
}};
+ // A handle program has no descriptor to read a type from, and ImageQueryDimensions carries
+ // none: it takes the type of another instruction using the same handle.
+ std::unordered_map<u32, TextureType> handle_program_types;
+ for (const TextureInst& texture_inst : to_replace) {
+ const IR::Opcode opcode{IndexedInstruction(*texture_inst.inst)};
+ if (texture_inst.cbuf.handle_program != ~0U && opcode != IR::Opcode::ImageQueryDimensions &&
+ !IsStorageImageOpcode(opcode)) {
+ handle_program_types.try_emplace(
+ texture_inst.cbuf.handle_program,
+ texture_inst.inst->Flags<IR::TextureInstInfo>().type.Value());
+ }
+ }
for (TextureInst& texture_inst : to_replace) {
// TODO: Handle arrays
IR::Inst* const inst{texture_inst.inst};
@@ -1196,7 +1212,12 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
bool is_multisample{false};
switch (inst->GetOpcode()) {
case IR::Opcode::ImageQueryDimensions:
- flags.type.Assign(ReadTextureTypeCached(env, cbuf));
+ if (const auto it{handle_program_types.find(cbuf.handle_program)};
+ it != handle_program_types.end()) {
+ flags.type.Assign(it->second);
+ } else {
+ flags.type.Assign(ReadTextureTypeCached(env, cbuf));
+ }
inst->SetFlags(flags);
break;
case IR::Opcode::ImageSampleImplicitLod:
@@ -1261,6 +1282,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
.cbuf_offset = cbuf.offset,
.count = count,
.size_shift = size_shift,
+ .handle_program = cbuf.handle_program,
});
} else {
index = descriptors.Add(ImageDescriptor{
@@ -1273,6 +1295,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
.cbuf_offset = cbuf.offset,
.count = count,
.size_shift = size_shift,
+ .handle_program = cbuf.handle_program,
});
}
break;
@@ -1289,6 +1312,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
.secondary_shift_left = cbuf.secondary_shift_left,
.count = count,
.size_shift = size_shift,
+ .handle_program = cbuf.handle_program,
});
} else {
count = std::min(count, sampled_dynamic_cap);
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index eeb8d768d7..e2b341b0c3 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -189,6 +189,9 @@ struct TextureBufferDescriptor {
u32 secondary_shift_left;
u32 count;
u32 size_shift;
+ /// Index in Info::handle_programs when the handle is computed at draw time (read from a
+ /// storage buffer), ~0 when it is the constant buffer word.
+ u32 handle_program{~0U};
auto operator<=>(const TextureBufferDescriptor&) const = default;
};
@@ -203,6 +206,9 @@ struct ImageBufferDescriptor {
u32 cbuf_offset;
u32 count;
u32 size_shift;
+ /// Index in Info::handle_programs when the handle is computed at draw time (read from a
+ /// storage buffer), ~0 when it is the constant buffer word.
+ u32 handle_program{~0U};
auto operator<=>(const ImageBufferDescriptor&) const = default;
};
@@ -240,6 +246,9 @@ struct ImageDescriptor {
u32 cbuf_offset;
u32 count;
u32 size_shift;
+ /// Index in Info::handle_programs when the handle is computed at draw time (read from a
+ /// storage buffer), ~0 when it is the constant buffer word.
+ u32 handle_program{~0U};
auto operator<=>(const ImageDescriptor&) const = default;
};
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
index eb134e86b5..5fc10cfce2 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
@@ -106,19 +106,18 @@ void ComputePipeline::Configure() {
const auto& cbufs{qmd.const_buffer_config};
const bool via_header_index{qmd.linked_tsc != 0};
const auto read_handle{[&](const auto& desc, u32 index) {
- if constexpr (std::is_same_v<decltype(desc), const Shader::TextureDescriptor&>) {
- if (desc.handle_program != ~0U) {
- // Read by the shader from a storage buffer: computed for this dispatch.
- return TexturePair(VideoCommon::EvaluateTextureHandle(
- info, desc.handle_program, *gpu_memory,
- [&](u32 cbuf) -> GPUVAddr {
- return cbuf < cbufs.size() &&
- ((qmd.const_buffer_enable_mask >> cbuf) & 1) != 0
- ? cbufs[cbuf].Address()
- : GPUVAddr{};
- }),
- via_header_index);
- }
+ if (desc.handle_program != ~0U) {
+ // Read by the shader from a storage buffer: computed for this dispatch.
+ return TexturePair(VideoCommon::EvaluateTextureHandle(
+ info, desc.handle_program, *gpu_memory,
+ [&](u32 cbuf) -> GPUVAddr {
+ return cbuf < cbufs.size() &&
+ ((qmd.const_buffer_enable_mask >> cbuf) &
+ 1) != 0
+ ? cbufs[cbuf].Address()
+ : GPUVAddr{};
+ }),
+ via_header_index);
}
ASSERT(((qmd.const_buffer_enable_mask >> desc.cbuf_index) & 1) != 0);
const u32 index_offset{index << desc.size_shift};
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 81950279d5..4e02f0569b 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -309,18 +309,16 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
}
const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
const auto read_handle{[&](const auto& desc, u32 index) {
- if constexpr (std::is_same_v<decltype(desc), const Shader::TextureDescriptor&>) {
- if (desc.handle_program != ~0U) {
- // Read by the shader from a storage buffer: computed for this draw.
- return TexturePair(VideoCommon::EvaluateTextureHandle(
- info, desc.handle_program, *gpu_memory,
- [&](u32 cbuf) -> GPUVAddr {
- return cbuf < cbufs.size() && cbufs[cbuf].enabled
- ? cbufs[cbuf].address
- : GPUVAddr{};
- }),
- via_header_index);
- }
+ if (desc.handle_program != ~0U) {
+ // Read by the shader from a storage buffer: computed for this draw.
+ return TexturePair(VideoCommon::EvaluateTextureHandle(
+ info, desc.handle_program, *gpu_memory,
+ [&](u32 cbuf) -> GPUVAddr {
+ return cbuf < cbufs.size() && cbufs[cbuf].enabled
+ ? cbufs[cbuf].address
+ : GPUVAddr{};
+ }),
+ via_header_index);
}
ASSERT(cbufs[desc.cbuf_index].enabled);
const u32 index_offset{index << desc.size_shift};
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 1cfe391ba6..3a3861930c 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -176,19 +176,18 @@ bool ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
const auto& cbufs{qmd.const_buffer_config};
const bool via_header_index{qmd.linked_tsc != 0};
const auto read_handle{[&](const auto& desc, u32 index) {
- if constexpr (std::is_same_v<decltype(desc), const Shader::TextureDescriptor&>) {
- if (desc.handle_program != ~0U) {
- // Read by the shader from a storage buffer: computed for this dispatch.
- return TexturePair(VideoCommon::EvaluateTextureHandle(
- info, desc.handle_program, gpu_memory,
- [&](u32 cbuf) -> GPUVAddr {
- return cbuf < cbufs.size() &&
- ((qmd.const_buffer_enable_mask >> cbuf) & 1) != 0
- ? cbufs[cbuf].Address()
- : GPUVAddr{};
- }),
- via_header_index);
- }
+ if (desc.handle_program != ~0U) {
+ // Read by the shader from a storage buffer: computed for this dispatch.
+ return TexturePair(VideoCommon::EvaluateTextureHandle(
+ info, desc.handle_program, gpu_memory,
+ [&](u32 cbuf) -> GPUVAddr {
+ return cbuf < cbufs.size() &&
+ ((qmd.const_buffer_enable_mask >> cbuf) &
+ 1) != 0
+ ? cbufs[cbuf].Address()
+ : GPUVAddr{};
+ }),
+ via_header_index);
}
ASSERT(((qmd.const_buffer_enable_mask >> desc.cbuf_index) & 1) != 0);
const u32 index_offset{index << desc.size_shift};
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index fa273f6ef9..4bd2e2735e 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -400,18 +400,16 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
}
const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
const auto read_handle{[&](const auto& desc, u32 index) {
- if constexpr (std::is_same_v<decltype(desc), const Shader::TextureDescriptor&>) {
- if (desc.handle_program != ~0U) {
- // Read by the shader from a storage buffer: computed for this draw.
- return TexturePair(VideoCommon::EvaluateTextureHandle(
- info, desc.handle_program, *gpu_memory,
- [&](u32 cbuf) -> GPUVAddr {
- return cbuf < cbufs.size() && cbufs[cbuf].enabled
- ? cbufs[cbuf].address
- : GPUVAddr{};
- }),
- via_header_index);
- }
+ if (desc.handle_program != ~0U) {
+ // Read by the shader from a storage buffer: computed for this draw.
+ return TexturePair(VideoCommon::EvaluateTextureHandle(
+ info, desc.handle_program, *gpu_memory,
+ [&](u32 cbuf) -> GPUVAddr {
+ return cbuf < cbufs.size() && cbufs[cbuf].enabled
+ ? cbufs[cbuf].address
+ : GPUVAddr{};
+ }),
+ via_header_index);
}
ASSERT(cbufs[desc.cbuf_index].enabled);
const u32 index_offset{index << desc.size_shift};