graphics: cleanup

This commit is contained in:
nmzik
2026-07-23 23:21:26 +02:00
parent 7638c25d76
commit a720b28b7f
25 changed files with 422 additions and 342 deletions
@@ -120,11 +120,7 @@ public:
void SetUserDataMarker(HW::UserSgprType type) { m_user_data_marker = type; } void SetUserDataMarker(HW::UserSgprType type) { m_user_data_marker = type; }
[[nodiscard]] HW::UserSgprType GetUserDataMarker() const { return m_user_data_marker; } [[nodiscard]] HW::UserSgprType GetUserDataMarker() const { return m_user_data_marker; }
void SetEmbeddedDataMarker(const uint32_t* buffer, uint32_t num_dw, uint32_t align) {}
void PushMarker(const char* str) {}
void PopMarker() {}
void PrefetchL2(void* addr, uint32_t size) {}
void ResetDeCe(); void ResetDeCe();
void SetCeComplete(bool complete) { m_ce_complete = complete; } void SetCeComplete(bool complete) { m_ce_complete = complete; }
void WaitCe(); void WaitCe();
@@ -2249,9 +2249,6 @@ KYTY_CP_OP_PARSER(CpOpDmaData) {
const uint64_t dst = buffer[3] | (static_cast<uint64_t>(buffer[4]) << 32u); const uint64_t dst = buffer[3] | (static_cast<uint64_t>(buffer[4]) << 32u);
if (control == 0x60000000 && dst == 0x0003022c && (control2 >> 21u) == 0x141u) { if (control == 0x60000000 && dst == 0x0003022c && (control2 >> 21u) == 0x141u) {
auto* addr = reinterpret_cast<void*>(src);
cp.PrefetchL2(addr, control2 & 0x1fffffu);
return 6; return 6;
} }
@@ -2799,11 +2796,10 @@ KYTY_CP_OP_PARSER(CpOpMarker) {
// EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0001000); // EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0001000);
uint32_t id = buffer[0] & 0xfffu; uint32_t id = buffer[0] & 0xfffu;
uint32_t align = (buffer[0] >> 12u) & 0xfu;
uint32_t len_dw = ((cmd_id >> 16u) & 0x3fffu); uint32_t len_dw = ((cmd_id >> 16u) & 0x3fffu);
switch (id) { switch (id) {
case 0x0: cp.SetEmbeddedDataMarker(buffer + 1, len_dw, align); break; case 0x0: break;
case 0x4: cp.SetUserDataMarker(HW::UserSgprType::Vsharp); break; case 0x4: cp.SetUserDataMarker(HW::UserSgprType::Vsharp); break;
case 0xd: cp.SetUserDataMarker(HW::UserSgprType::Region); break; case 0xd: cp.SetUserDataMarker(HW::UserSgprType::Region); break;
case 0x777: { case 0x777: {
@@ -2875,8 +2871,6 @@ KYTY_CP_OP_PARSER(CpOpPopMarker) {
LOGF("Pop marker\n"); LOGF("Pop marker\n");
} }
cp.PopMarker();
return dw_num + 1; return dw_num + 1;
} }
@@ -2892,8 +2886,6 @@ KYTY_CP_OP_PARSER(CpOpPushMarker) {
LOGF("Push marker: %s\n", str); LOGF("Push marker: %s\n", str);
} }
cp.PushMarker(str);
return dw_num + 1; return dw_num + 1;
} }
-4
View File
@@ -1538,10 +1538,6 @@ void GraphicsRunSubmitFlipPreparation() {
g_gpu->SubmitFlipPreparation(); g_gpu->SubmitFlipPreparation();
} }
void GraphicsRunWait() {
GraphicsRunSubmissionLock lock;
}
GraphicsRunSubmissionLock::GraphicsRunSubmissionLock() { GraphicsRunSubmissionLock::GraphicsRunSubmissionLock() {
if (g_gpu == nullptr || g_current_processor != nullptr || if (g_gpu == nullptr || g_current_processor != nullptr ||
g_submission_pause_depth == UINT32_MAX) { g_submission_pause_depth == UINT32_MAX) {
-1
View File
@@ -22,7 +22,6 @@ void GraphicsRunSubmit(uint32_t* cmd_draw_buffer, uint32_t num_draw_dw, uint32_t
void GraphicsRunSubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw, void GraphicsRunSubmitCompute(uint32_t queue, uint32_t* cmd_buffer, uint32_t num_dw,
bool trigger_agc_interrupt_on_done = false); bool trigger_agc_interrupt_on_done = false);
void GraphicsRunSubmitFlipPreparation(); void GraphicsRunSubmitFlipPreparation();
void GraphicsRunWait();
void GraphicsRunDone(); void GraphicsRunDone();
int GraphicsRunGetFrameNum(); int GraphicsRunGetFrameNum();
[[nodiscard]] bool GraphicsRunIsCommandProcessorThread() noexcept; [[nodiscard]] bool GraphicsRunIsCommandProcessorThread() noexcept;
+32 -10
View File
@@ -406,8 +406,8 @@ struct TextureBlockLayout {
static bool GetTextureBlockLayout(uint32_t format, uint32_t tile, TextureBlockLayout& out) { static bool GetTextureBlockLayout(uint32_t format, uint32_t tile, TextureBlockLayout& out) {
uint32_t width_log2 = 0, height_log2 = 0; uint32_t width_log2 = 0, height_log2 = 0;
if (tile == 1 && Gen5Standard256BLayout(format, &out.bytes, &out.texel_width, if (tile == 1 && Gen5Standard256BLayout(format, &out.bytes, &out.texel_width, &out.texel_height,
&out.texel_height, &width_log2, &height_log2)) { &width_log2, &height_log2)) {
out.block_size = 256; out.block_size = 256;
} else if (tile == 5 && Gen5Standard4KBLayout(format, &out.bytes, &out.texel_width, } else if (tile == 5 && Gen5Standard4KBLayout(format, &out.bytes, &out.texel_width,
&out.texel_height, &width_log2, &height_log2)) { &out.texel_height, &width_log2, &height_log2)) {
@@ -555,7 +555,12 @@ bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height
const bool thick4 = family == TileBlockFamily::Standard4KB3D; const bool thick4 = family == TileBlockFamily::Standard4KB3D;
const bool thick64 = const bool thick64 =
family == TileBlockFamily::Standard64KB3D || family == TileBlockFamily::Prt64KB3D; family == TileBlockFamily::Standard64KB3D || family == TileBlockFamily::Prt64KB3D;
const uint32_t max_tail = thick4 ? 5u : (thick64 ? 10u : 12u); uint32_t max_tail = 12u;
if (thick4) {
max_tail = 5u;
} else if (thick64) {
max_tail = 10u;
}
uint32_t tail_width = thick4 ? block.block_width : block.block_width >> 1u; uint32_t tail_width = thick4 ? block.block_width : block.block_width >> 1u;
uint32_t tail_height = thick4 ? block.block_height >> 1u : block.block_height; uint32_t tail_height = thick4 ? block.block_height >> 1u : block.block_height;
if (family == TileBlockFamily::Depth64KB && element.bytes < 4) { if (family == TileBlockFamily::Depth64KB && element.bytes < 4) {
@@ -575,17 +580,22 @@ bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height
out.level_widths[level] = AlignUp(mip_width, block.block_width); out.level_widths[level] = AlignUp(mip_width, block.block_width);
out.level_heights[level] = AlignUp(mip_height, block.block_height); out.level_heights[level] = AlignUp(mip_height, block.block_height);
out.level_sizes[level] = static_cast<uint64_t>(block.block_depth) * out.level_sizes[level] = static_cast<uint64_t>(block.block_depth) *
out.level_widths[level] * out.level_heights[level] * out.level_widths[level] * out.level_heights[level] * element.bytes;
element.bytes;
out.block_slice_size += out.level_sizes[level]; out.block_slice_size += out.level_sizes[level];
} }
const auto bytes_log2 = std::countr_zero(element.bytes); const auto bytes_log2 = std::countr_zero(element.bytes);
const Gen5MipTailLocation* tail_locations = nullptr;
if (thick4) {
tail_locations = GEN5_MIP_TAIL_LOCATIONS_THICK_4KB[bytes_log2];
} else if (thick64) {
tail_locations = GEN5_MIP_TAIL_LOCATIONS_THICK_64KB[bytes_log2];
} else {
tail_locations = GEN5_MIP_TAIL_LOCATIONS_THIN_64KB[bytes_log2];
}
for (uint32_t level = out.first_tail_level; level < levels; ++level) { for (uint32_t level = out.first_tail_level; level < levels; ++level) {
const auto index = level - out.first_tail_level; const auto index = level - out.first_tail_level;
const auto tail = thick4 ? GEN5_MIP_TAIL_LOCATIONS_THICK_4KB[bytes_log2][index] const auto tail = tail_locations[index];
: (thick64 ? GEN5_MIP_TAIL_LOCATIONS_THICK_64KB[bytes_log2][index]
: GEN5_MIP_TAIL_LOCATIONS_THIN_64KB[bytes_log2][index]);
out.level_sizes[level] = block.block_size; out.level_sizes[level] = block.block_size;
out.level_widths[level] = block.block_width; out.level_widths[level] = block.block_width;
out.level_heights[level] = block.block_height; out.level_heights[level] = block.block_height;
@@ -1068,12 +1078,24 @@ bool TileGetBlockLayout(TileBlockFamily family, uint32_t bytes_per_element,
switch (family) { switch (family) {
case TileBlockFamily::Standard256B: case TileBlockFamily::Standard256B:
result.block_size = 256; result.block_size = 256;
result.block_width = bytes_per_element <= 2 ? 16 : (bytes_per_element <= 8 ? 8 : 4); if (bytes_per_element <= 2) {
result.block_width = 16;
} else if (bytes_per_element <= 8) {
result.block_width = 8;
} else {
result.block_width = 4;
}
result.block_height = result.block_size / (result.block_width * bytes_per_element); result.block_height = result.block_size / (result.block_width * bytes_per_element);
break; break;
case TileBlockFamily::Standard4KB: case TileBlockFamily::Standard4KB:
result.block_size = 4096; result.block_size = 4096;
result.block_width = bytes_per_element <= 2 ? 64 : (bytes_per_element <= 8 ? 32 : 16); if (bytes_per_element <= 2) {
result.block_width = 64;
} else if (bytes_per_element <= 8) {
result.block_width = 32;
} else {
result.block_width = 16;
}
result.block_height = result.block_size / (result.block_width * bytes_per_element); result.block_height = result.block_size / (result.block_width * bytes_per_element);
break; break;
case TileBlockFamily::Standard4KB3D: { case TileBlockFamily::Standard4KB3D: {
+11 -5
View File
@@ -100,6 +100,10 @@ CommandBuffer::CommandBuffer()
: m_graphics(GetRenderContext().GetGraphics()), m_slot(g_command_pool.Allocate()), : m_graphics(GetRenderContext().GetGraphics()), m_slot(g_command_pool.Allocate()),
m_host_stream(m_graphics) {} m_host_stream(m_graphics) {}
CommandBuffer::~CommandBuffer() {
Release();
}
void ThreadCommandPool::Create() { void ThreadCommandPool::Create() {
auto& graphics = GetRenderContext().GetGraphics(); auto& graphics = GetRenderContext().GetGraphics();
EXIT_IF(m_pool != nullptr || graphics.queue_family == static_cast<uint32_t>(-1)); EXIT_IF(m_pool != nullptr || graphics.queue_family == static_cast<uint32_t>(-1));
@@ -200,8 +204,11 @@ void CommandBuffer::Release() {
EXIT_NOT_IMPLEMENTED(!IsInvalid()); EXIT_NOT_IMPLEMENTED(!IsInvalid());
} }
void CommandBuffer::DeleteAfterFence(VulkanBuffer& buffer) { void CommandBuffer::RetireBufferAfterFence(std::unique_ptr<VulkanBuffer> buffer) {
m_delete_after_fence.push_back(&buffer); if (IsInvalid() || m_execute || buffer == nullptr || buffer->buffer == nullptr) {
EXIT("cannot retire a buffer on an invalid or submitted command buffer\n");
}
m_retired_buffers.push_back(std::move(buffer));
} }
void CommandBuffer::RetainResourceUntilFence(std::shared_ptr<void> resource) { void CommandBuffer::RetainResourceUntilFence(std::shared_ptr<void> resource) {
@@ -375,11 +382,10 @@ void CommandBuffer::ReleaseResourcesAfterFence() {
} }
void CommandBuffer::DeleteBuffersAfterFence() { void CommandBuffer::DeleteBuffersAfterFence() {
for (auto* buffer: m_delete_after_fence) { for (const auto& buffer: m_retired_buffers) {
GetRenderContext().GetGraphics().DeleteBuffer(*buffer); GetRenderContext().GetGraphics().DeleteBuffer(*buffer);
delete buffer;
} }
m_delete_after_fence.clear(); m_retired_buffers.clear();
} }
void CommandBuffer::BeginRenderPass(VulkanFramebuffer& framebuffer, RenderColorInfo* colors, void CommandBuffer::BeginRenderPass(VulkanFramebuffer& framebuffer, RenderColorInfo* colors,
+5 -6
View File
@@ -9,6 +9,7 @@
#include "graphics/guest_gpu/hardwareContext.h" #include "graphics/guest_gpu/hardwareContext.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include <algorithm>
#include <atomic> #include <atomic>
#include <cmath> #include <cmath>
#include <fmt/format.h> #include <fmt/format.h>
@@ -100,8 +101,6 @@ void sh_print(const char* func, const HW::Shader& /*uc*/) {
LOGF("%s\n", func); LOGF("%s\n", func);
} }
void sh_check(const HW::Shader& /*uc*/) {}
std::vector<std::string> rt_print(const char* func, const HW::RenderTarget& rt) { std::vector<std::string> rt_print(const char* func, const HW::RenderTarget& rt) {
std::vector<std::string> dst; std::vector<std::string> dst;
dst.reserve(53); dst.reserve(53);
@@ -1135,10 +1134,10 @@ static ScissorRect ScissorRectClamp(ScissorRect r, uint32_t width, uint32_t heig
int max_right = static_cast<int>(width); int max_right = static_cast<int>(width);
int max_bottom = static_cast<int>(height); int max_bottom = static_cast<int>(height);
r.left = (r.left < 0 ? 0 : (r.left > max_right ? max_right : r.left)); r.left = std::clamp(r.left, 0, max_right);
r.right = (r.right < 0 ? 0 : (r.right > max_right ? max_right : r.right)); r.right = std::clamp(r.right, 0, max_right);
r.top = (r.top < 0 ? 0 : (r.top > max_bottom ? max_bottom : r.top)); r.top = std::clamp(r.top, 0, max_bottom);
r.bottom = (r.bottom < 0 ? 0 : (r.bottom > max_bottom ? max_bottom : r.bottom)); r.bottom = std::clamp(r.bottom, 0, max_bottom);
if (!ScissorRectValid(r)) { if (!ScissorRectValid(r)) {
r.right = r.left; r.right = r.left;
-1
View File
@@ -33,7 +33,6 @@ bool graphics_debug_dump_enabled();
void uc_print(const char* func, const HW::UserConfig& uc); void uc_print(const char* func, const HW::UserConfig& uc);
void uc_check(const HW::UserConfig& uc); void uc_check(const HW::UserConfig& uc);
void sh_print(const char* func, const HW::Shader& uc); void sh_print(const char* func, const HW::Shader& uc);
void sh_check(const HW::Shader& uc);
std::vector<std::string> rt_print(const char* func, const HW::RenderTarget& rt); std::vector<std::string> rt_print(const char* func, const HW::RenderTarget& rt);
bool RenderIsColorTileModeLinear(uint32_t tile_mode); bool RenderIsColorTileModeLinear(uint32_t tile_mode);
void hw_print(const RenderCommandBuffer& buffer); void hw_print(const RenderCommandBuffer& buffer);
+3 -3
View File
@@ -69,7 +69,7 @@ private:
class CommandBuffer { class CommandBuffer {
public: public:
CommandBuffer(); CommandBuffer();
~CommandBuffer() { Release(); } ~CommandBuffer();
KYTY_CLASS_NO_COPY(CommandBuffer); KYTY_CLASS_NO_COPY(CommandBuffer);
@@ -88,7 +88,7 @@ public:
void WaitForFenceOnly(); void WaitForFenceOnly();
void WaitForFence(); void WaitForFence();
void WaitForFenceAndReset(); void WaitForFenceAndReset();
void DeleteAfterFence(VulkanBuffer& buffer); void RetireBufferAfterFence(std::unique_ptr<VulkanBuffer> buffer);
void RetainResourceUntilFence(std::shared_ptr<void> resource); void RetainResourceUntilFence(std::shared_ptr<void> resource);
void RecycleDescriptorAfterFence(VulkanDescriptorSet& set); void RecycleDescriptorAfterFence(VulkanDescriptorSet& set);
@@ -119,7 +119,7 @@ private:
uint32_t m_debug_arg2 = 0; uint32_t m_debug_arg2 = 0;
uint32_t m_debug_arg3 = 0; uint32_t m_debug_arg3 = 0;
uint64_t m_debug_arg4 = 0; uint64_t m_debug_arg4 = 0;
std::vector<VulkanBuffer*> m_delete_after_fence; std::vector<std::unique_ptr<VulkanBuffer>> m_retired_buffers;
FenceResourceRetainer m_fence_resources; FenceResourceRetainer m_fence_resources;
std::vector<VulkanDescriptorSet*> m_descriptor_sets_after_fence; std::vector<VulkanDescriptorSet*> m_descriptor_sets_after_fence;
HostStreamBuffer m_host_stream; HostStreamBuffer m_host_stream;
@@ -1120,7 +1120,6 @@ void RenderDrawIndex(uint64_t submit_id, RenderCommandBuffer& buffer, uint32_t i
instance_count, render_target_slice_offset, static_cast<uint32_t>(vertex_offset_add), instance_count, render_target_slice_offset, static_cast<uint32_t>(vertex_offset_add),
first_instance); first_instance);
} }
sh_check(sh_ctx);
uc_check(ucfg); uc_check(ucfg);
@@ -1248,7 +1247,6 @@ void RenderDrawIndexAuto(uint64_t submit_id, RenderCommandBuffer& buffer, uint32
index_count, flags, render_target_slice_offset, instance_count, first_vertex, index_count, flags, render_target_slice_offset, instance_count, first_vertex,
first_instance); first_instance);
} }
sh_check(sh_ctx);
uc_check(ucfg); uc_check(ucfg);
+6 -3
View File
@@ -621,9 +621,12 @@ void CreatePipelineInternal(PipelineCache::GraphicsPipeline& pipeline, vk::Rende
} }
case 3: { case 3: {
auto swizzle = vs_input_info.resources[index].DstSelXYZ(); auto swizzle = vs_input_info.resources[index].DstSelXYZ();
auto expected = auto expected = DstSel(4, 5, 6);
(attr_size == 1 ? DstSel(4, 0, 0) switch (attr_size) {
: (attr_size == 2 ? DstSel(4, 5, 0) : DstSel(4, 5, 6))); case 1: expected = DstSel(4, 0, 0); break;
case 2: expected = DstSel(4, 5, 0); break;
default: break;
}
if (swizzle != expected) { if (swizzle != expected) {
log_unsupported_vertex_swizzle(swizzle, expected); log_unsupported_vertex_swizzle(swizzle, expected);
} }
+7 -4
View File
@@ -774,14 +774,16 @@ void CopyImage(CommandBuffer& buffer, std::span<const ImageImageCopy> regions,
compressed_copy_size = compressed_copy_size =
std::max(compressed_copy_size, CompressedImageCopyBufferSize(r, dst_image)); std::max(compressed_copy_size, CompressedImageCopyBufferSize(r, dst_image));
} }
std::unique_ptr<VulkanBuffer> compressed_copy_owner;
VulkanBuffer* compressed_copy_buffer = nullptr; VulkanBuffer* compressed_copy_buffer = nullptr;
if (compressed_copy_size != 0) { if (compressed_copy_size != 0) {
compressed_copy_buffer = new VulkanBuffer; compressed_copy_owner = std::make_unique<VulkanBuffer>();
compressed_copy_buffer = compressed_copy_owner.get();
compressed_copy_buffer->usage = compressed_copy_buffer->usage =
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
compressed_copy_buffer->memory.property = {}; compressed_copy_buffer->memory.property = {};
buffer.GetGraphics().CreateBuffer(compressed_copy_size, *compressed_copy_buffer); buffer.GetGraphics().CreateBuffer(compressed_copy_size, *compressed_copy_buffer);
buffer.DeleteAfterFence(*compressed_copy_buffer); buffer.RetireBufferAfterFence(std::move(compressed_copy_owner));
} }
for (const auto& r: regions) { for (const auto& r: regions) {
@@ -851,12 +853,13 @@ void CopyImageViaBuffer(CommandBuffer& buffer, VulkanImage& src_image,
const auto copy_buffer_size = row_bytes * rows_per_chunk; const auto copy_buffer_size = row_bytes * rows_per_chunk;
auto& graphics = buffer.GetGraphics(); auto& graphics = buffer.GetGraphics();
auto* copy_buffer = new VulkanBuffer; auto copy_buffer_owner = std::make_unique<VulkanBuffer>();
auto* copy_buffer = copy_buffer_owner.get();
copy_buffer->usage = copy_buffer->usage =
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst; vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
copy_buffer->memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal; copy_buffer->memory.property = vk::MemoryPropertyFlagBits::eDeviceLocal;
graphics.CreateBuffer(copy_buffer_size, *copy_buffer); graphics.CreateBuffer(copy_buffer_size, *copy_buffer);
buffer.DeleteAfterFence(*copy_buffer); buffer.RetireBufferAfterFence(std::move(copy_buffer_owner));
auto vk_buffer = buffer.Handle(); auto vk_buffer = buffer.Handle();
const auto src_layout = src_image.layout; const auto src_layout = src_image.layout;
-7
View File
@@ -187,10 +187,6 @@ void RenderDocInit() {
} }
} }
bool RenderDocIsLoaded() {
return g_api != nullptr;
}
void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window) { void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window) {
if (g_api == nullptr) { if (g_api == nullptr) {
return; return;
@@ -281,9 +277,6 @@ void RenderDocOnPresent() {
#else #else
void RenderDocInit() {} void RenderDocInit() {}
bool RenderDocIsLoaded() {
return false;
}
void RenderDocSetActiveWindow(vk::Instance /*instance*/, SDL_Window* /*window*/) {} void RenderDocSetActiveWindow(vk::Instance /*instance*/, SDL_Window* /*window*/) {}
void RenderDocRequestCapture() {} void RenderDocRequestCapture() {}
void RenderDocOnPresent() {} void RenderDocOnPresent() {}
-1
View File
@@ -9,7 +9,6 @@ struct SDL_Window;
namespace Libs::Graphics { namespace Libs::Graphics {
void RenderDocInit(); void RenderDocInit();
bool RenderDocIsLoaded();
void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window); void RenderDocSetActiveWindow(vk::Instance instance, SDL_Window* window);
void RenderDocRequestCapture(); void RenderDocRequestCapture();
void RenderDocOnPresent(); void RenderDocOnPresent();
+62 -33
View File
@@ -212,6 +212,62 @@ const MimgAtomicInfo* LookupAtomic(uint32_t opcode) {
return nullptr; return nullptr;
} }
Opcode DecodeMimgOpcode(uint32_t opcode, const MimgSampleInfo* sample, const MimgGatherInfo* gather,
const MimgAtomicInfo* atomic) {
if (sample != nullptr) {
return Opcode::ImageSample;
}
if (gather != nullptr) {
return gather->decoded;
}
if (atomic != nullptr) {
return atomic->decoded;
}
switch (opcode) {
case 0x00u: return Opcode::ImageLoad;
case 0x01u: return Opcode::ImageLoadMip;
case 0x08u: return Opcode::ImageStore;
case 0x09u: return Opcode::ImageStoreMip;
case 0x0eu: return Opcode::ImageGetResinfo;
case 0x60u: return Opcode::ImageGetLod;
default: return Opcode::Unsupported;
}
}
uint32_t DecodeMimgSampleFlags(const MimgSampleInfo* sample, const MimgGatherInfo* gather) {
if (sample != nullptr) {
return sample->flags;
}
if (gather != nullptr) {
return gather->flags;
}
return 0;
}
uint32_t DecodeMimgAddressComponents(uint32_t opcode, ImageDimension dimension,
const MimgSampleInfo* sample, const MimgGatherInfo* gather,
const MimgAtomicInfo* atomic) {
if (sample != nullptr) {
return ImageSampleAddressComponents(sample->flags, dimension);
}
if (gather != nullptr) {
return ImageSampleAddressComponents(gather->flags, dimension);
}
if (atomic != nullptr) {
return 3u;
}
switch (opcode) {
case 0x01u:
case 0x09u: return ImageCoordComponents(dimension) + 1u;
case 0x00u:
case 0x08u:
case 0x60u: return ImageCoordComponents(dimension);
default: return 0;
}
}
uint32_t CountDmaskComponents(uint32_t dmask) { uint32_t CountDmaskComponents(uint32_t dmask) {
uint32_t count = 0; uint32_t count = 0;
for (uint32_t i = 0; i < 4u; i++) { for (uint32_t i = 0; i < 4u; i++) {
@@ -262,39 +318,22 @@ bool DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
inst.word_count = word_count; inst.word_count = word_count;
inst.family = Family::MIMG; inst.family = Family::MIMG;
inst.opcode_id = opcode; inst.opcode_id = opcode;
inst.opcode = (sample != nullptr ? Opcode::ImageSample inst.opcode = DecodeMimgOpcode(opcode, sample, gather, atomic);
: gather != nullptr ? gather->decoded
: atomic != nullptr ? atomic->decoded
: opcode == 0x00u ? Opcode::ImageLoad
: opcode == 0x01u ? Opcode::ImageLoadMip
: opcode == 0x08u ? Opcode::ImageStore
: opcode == 0x09u ? Opcode::ImageStoreMip
: opcode == 0x0eu ? Opcode::ImageGetResinfo
: opcode == 0x60u ? Opcode::ImageGetLod
: Opcode::Unsupported);
inst.dmask = (word0 >> 8u) & 0xfu; inst.dmask = (word0 >> 8u) & 0xfu;
inst.data_dwords = gather != nullptr ? 4u : CountDmaskComponents(inst.dmask); inst.data_dwords = gather != nullptr ? 4u : CountDmaskComponents(inst.dmask);
inst.glc = ((word0 >> 13u) & 1u) != 0; inst.glc = ((word0 >> 13u) & 1u) != 0;
inst.slc = ((word0 >> 25u) & 1u) != 0; inst.slc = ((word0 >> 25u) & 1u) != 0;
inst.image_sample_flags = (sample != nullptr ? sample->flags inst.image_sample_flags = DecodeMimgSampleFlags(sample, gather);
: gather != nullptr ? gather->flags if (a16) {
: 0u) | inst.image_sample_flags |= ImageSampleFlagA16;
(a16 ? ImageSampleFlagA16 : 0u); }
inst.image_dimension = dimension; inst.image_dimension = dimension;
inst.image_nsa_dwords = nsa_dwords; inst.image_nsa_dwords = nsa_dwords;
for (uint32_t i = 0; i < nsa_dwords * 4u && i < MaxImageNsaAddressComponents; i++) { for (uint32_t i = 0; i < nsa_dwords * 4u && i < MaxImageNsaAddressComponents; i++) {
inst.image_nsa_addr[i] = (code[word_index + 2u + i / 4u] >> ((i % 4u) * 8u)) & 0xffu; inst.image_nsa_addr[i] = (code[word_index + 2u + i / 4u] >> ((i % 4u) * 8u)) & 0xffu;
} }
inst.image_address_components = inst.image_address_components =
sample != nullptr ? ImageSampleAddressComponents(sample->flags, dimension) DecodeMimgAddressComponents(opcode, dimension, sample, gather, atomic);
: gather != nullptr ? ImageSampleAddressComponents(gather->flags, dimension)
: atomic != nullptr ? 3u
: opcode == 0x60u ? ImageCoordComponents(dimension)
: opcode == 0x01u ? ImageCoordComponents(dimension) + 1u
: opcode == 0x00u ? ImageCoordComponents(dimension)
: (opcode == 0x09u ? ImageCoordComponents(dimension) + 1u
: opcode == 0x08u ? ImageCoordComponents(dimension)
: 0u);
SetRawWords(inst, code, word_index, word_count); SetRawWords(inst, code, word_index, word_count);
if (inst.opcode == Opcode::Unsupported) { if (inst.opcode == Opcode::Unsupported) {
@@ -318,14 +357,4 @@ const char* MimgSampleOpcodeName(uint32_t opcode) {
return sample != nullptr ? sample->name : nullptr; return sample != nullptr ? sample->name : nullptr;
} }
uint32_t MimgSampleOpcodeFlags(uint32_t opcode) {
const auto* sample = LookupSample(opcode);
return sample != nullptr ? sample->flags : 0u;
}
uint32_t MimgSampleAddressComponents(uint32_t opcode) {
const auto* sample = LookupSample(opcode);
return sample != nullptr ? sample->address_components : 0u;
}
} // namespace Libs::Graphics::ShaderRecompiler::Decoder } // namespace Libs::Graphics::ShaderRecompiler::Decoder
@@ -9,8 +9,6 @@ bool DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
std::string* error); std::string* error);
const char* MimgSampleOpcodeName(uint32_t opcode); const char* MimgSampleOpcodeName(uint32_t opcode);
uint32_t MimgSampleOpcodeFlags(uint32_t opcode);
uint32_t MimgSampleAddressComponents(uint32_t opcode);
} // namespace Libs::Graphics::ShaderRecompiler::Decoder } // namespace Libs::Graphics::ShaderRecompiler::Decoder
@@ -256,10 +256,12 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime,
base &= ~uint64_t {3}; base &= ~uint64_t {3};
} }
const auto before = static_cast<uint64_t>(-static_cast<int64_t>(address.min_offset)); const auto before = static_cast<uint64_t>(-static_cast<int64_t>(address.min_offset));
const auto binding_base = address.kind == ResourceKind::Flat uint64_t binding_base = 0;
? base & ~(FlatAddressWindowSize - 1u) if (address.kind == ResourceKind::Flat) {
: base >= before ? base - before binding_base = base & ~(FlatAddressWindowSize - 1u);
: 0; } else if (base >= before) {
binding_base = base - before;
}
next.addresses.push_back({base, binding_base}); next.addresses.push_back({base, binding_base});
} else { } else {
if (!runtime.flat_memory_base.has_value()) { if (!runtime.flat_memory_base.has_value()) {
@@ -535,10 +535,12 @@ private:
if (inst.dst.kind == OperandKind::Register && inst.dst.reg.file == RegisterFile::M0) { if (inst.dst.kind == OperandKind::Register && inst.dst.reg.file == RegisterFile::M0) {
const auto before = state; const auto before = state;
const auto op = Operation(inst.op); const auto op = Operation(inst.op);
state.m0 = inst.op == Opcode::MoveU32 && inst.src_count != 0 state.m0 = ScalarProvenance::Unknown;
? OperandValue(inst.src[0], before) if (inst.op == Opcode::MoveU32 && inst.src_count != 0) {
: op != ScalarValueOp::Unknown ? Define(inst, op, before) state.m0 = OperandValue(inst.src[0], before);
: ScalarProvenance::Unknown; } else if (op != ScalarValueOp::Unknown) {
state.m0 = Define(inst, op, before);
}
UpdateScc(inst, before, state); UpdateScc(inst, before, state);
return; return;
} }
@@ -558,10 +560,14 @@ private:
switch (inst.op) { switch (inst.op) {
case Opcode::MoveU32: case Opcode::MoveU32:
case Opcode::MoveF32Bits: case Opcode::MoveF32Bits:
value = inst.src_count == 0 ? ScalarProvenance::Unknown if (inst.src_count != 0) {
: inst.src[0].kind == OperandKind::PcRelativeU32 if (inst.src[0].kind == OperandKind::PcRelativeU32) {
? InternValue({ScalarValueOp::PcRelativeLow, inst.pc, inst.src[0].imm}) value =
: OperandValue(inst.src[0], before); InternValue({ScalarValueOp::PcRelativeLow, inst.pc, inst.src[0].imm});
} else {
value = OperandValue(inst.src[0], before);
}
}
if (inst.op == Opcode::MoveU32 && inst.src_count != 0 && if (inst.op == Opcode::MoveU32 && inst.src_count != 0 &&
inst.src[0].kind == OperandKind::ImmediateU32 && inst.src[0].imm == 0 && inst.src[0].kind == OperandKind::ImmediateU32 && inst.src[0].imm == 0 &&
dst != 0) { dst != 0) {
@@ -180,9 +180,11 @@ bool IsDecodedSgpr(const Decoder::Operand& op) {
} }
uint32_t DecodedSgprReg(const Decoder::Operand& op) { uint32_t DecodedSgprReg(const Decoder::Operand& op) {
return op.kind == Decoder::OperandKind::VccLo switch (op.kind) {
? 106u case Decoder::OperandKind::VccLo: return 106u;
: (op.kind == Decoder::OperandKind::VccHi ? 107u : op.reg); case Decoder::OperandKind::VccHi: return 107u;
default: return op.reg;
}
} }
bool IsDecodedVgpr(const Decoder::Operand& op) { bool IsDecodedVgpr(const Decoder::Operand& op) {
@@ -345,9 +347,8 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded
vertex_index_accumulator && IsDecodedSgpr(inst.src0) && vertex_index_accumulator && IsDecodedSgpr(inst.src0) &&
((inst.opcode == Decoder::Opcode::VAddI32 && IsDecodedVgpr(inst.src1) && ((inst.opcode == Decoder::Opcode::VAddI32 && IsDecodedVgpr(inst.src1) &&
inst.src1.reg == inst.dst.reg) || inst.src1.reg == inst.dst.reg) ||
(user_data_base == 8 && inst.dst.reg == 5 && (user_data_base == 8 && inst.dst.reg == 5 && inst.opcode == Decoder::Opcode::VSadU32 &&
inst.opcode == Decoder::Opcode::VSadU32 && IsDecodedVgpr(inst.src2) && IsDecodedVgpr(inst.src2) && inst.src2.reg == inst.dst.reg &&
inst.src2.reg == inst.dst.reg &&
TryDecodedOperandConstant(sgprs, inst.src1, sad_zero) && sad_zero == 0)); TryDecodedOperandConstant(sgprs, inst.src1, sad_zero) && sad_zero == 0));
if (data.loads.empty() && vertex_offset_add) { if (data.loads.empty() && vertex_offset_add) {
const auto reg = DecodedSgprReg(inst.src0); const auto reg = DecodedSgprReg(inst.src0);
@@ -804,9 +805,10 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
runtime.user_data = std::span<const uint32_t>(user_data, options.user_data_count); runtime.user_data = std::span<const uint32_t>(user_data, options.user_data_count);
runtime.shader_base = options.shader_base != 0 ? options.shader_base runtime.shader_base = options.shader_base != 0 ? options.shader_base
: reinterpret_cast<uint64_t>(code.data()); : reinterpret_cast<uint64_t>(code.data());
runtime.read_memory = options.read_memory != nullptr ? options.read_memory runtime.read_memory = options.read_memory;
: options.user_data == nullptr ? ReadZeroMemory if (runtime.read_memory == nullptr && options.user_data == nullptr) {
: nullptr; runtime.read_memory = ReadZeroMemory;
}
runtime.userdata = options.read_memory_data; runtime.userdata = options.read_memory_data;
runtime.flat_memory_base = options.flat_memory_base; runtime.flat_memory_base = options.flat_memory_base;
if (!IR::MaterializeResources(ir, runtime, resources, error)) { if (!IR::MaterializeResources(ir, runtime, resources, error)) {
@@ -12,9 +12,13 @@ bool PatchSrtReads(Program& program, std::string* error) {
if (!program.srt_plan_complete || program.srt_patching_complete || if (!program.srt_plan_complete || program.srt_patching_complete ||
program.resource_tracking_complete) { program.resource_tracking_complete) {
if (error != nullptr) { if (error != nullptr) {
*error = !program.srt_plan_complete ? "SRT plan is not ready" if (!program.srt_plan_complete) {
: program.srt_patching_complete ? "SRT reads already patched" *error = "SRT plan is not ready";
: "resources already tracked"; } else if (program.srt_patching_complete) {
*error = "SRT reads already patched";
} else {
*error = "resources already tracked";
}
} }
return false; return false;
} }
+24 -44
View File
@@ -553,6 +553,17 @@ bool DecodeVop1Sdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_i
return ReadLiteralOperands(code, word_index, inst, error); return ReadLiteralOperands(code, word_index, inst, error);
} }
void ApplyDppModifier(Operand& operand, uint32_t modifier) {
operand.negate = ((modifier >> 20u) & 0x1u) != 0u;
operand.absolute = ((modifier >> 21u) & 0x1u) != 0u;
operand.dpp = true;
operand.dpp_ctrl = (modifier >> 8u) & 0x1ffu;
operand.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u;
operand.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u;
operand.dpp_bank_mask = (modifier >> 24u) & 0xfu;
operand.dpp_row_mask = (modifier >> 28u) & 0xfu;
}
bool DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index, bool DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
uint32_t opcode, uint32_t vdst, Instruction& inst, std::string* error) { uint32_t opcode, uint32_t vdst, Instruction& inst, std::string* error) {
if (word_index + 1u >= code.size()) { if (word_index + 1u >= code.size()) {
@@ -572,14 +583,7 @@ bool DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
!DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) { !DecodeScalarSource(src0 + 256u, pc, inst.src0, error)) {
return false; return false;
} }
inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; ApplyDppModifier(inst.src0, modifier);
inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u;
inst.src0.dpp = true;
inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu;
inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u;
inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u;
inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu;
inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu;
inst.src_count = 1; inst.src_count = 1;
if (!IsVop1FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute)) { if (!IsVop1FloatSourceOpcode(inst.opcode) && (inst.src0.negate || inst.src0.absolute)) {
@@ -988,14 +992,7 @@ bool DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
return false; return false;
} }
ApplyDefaultVop2F16Destination(inst); ApplyDefaultVop2F16Destination(inst);
inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; ApplyDppModifier(inst.src0, modifier);
inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u;
inst.src0.dpp = true;
inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu;
inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u;
inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u;
inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu;
inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu;
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
@@ -1143,14 +1140,7 @@ bool DecodeVopcDpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
return false; return false;
} }
inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo; inst.dst.kind = IsVopcCompareExec(inst.opcode) ? OperandKind::ExecLo : OperandKind::VccLo;
inst.src0.negate = ((modifier >> 20u) & 0x1u) != 0u; ApplyDppModifier(inst.src0, modifier);
inst.src0.absolute = ((modifier >> 21u) & 0x1u) != 0u;
inst.src0.dpp = true;
inst.src0.dpp_ctrl = (modifier >> 8u) & 0x1ffu;
inst.src0.dpp_fetch_inactive = ((modifier >> 18u) & 0x1u) != 0u;
inst.src0.dpp_bound_ctrl = ((modifier >> 19u) & 0x1u) != 0u;
inst.src0.dpp_bank_mask = (modifier >> 24u) & 0xfu;
inst.src0.dpp_row_mask = (modifier >> 28u) & 0xfu;
inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u;
inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u;
inst.src_count = 2; inst.src_count = 2;
@@ -1249,19 +1239,7 @@ void ApplyVop3pMixAbsModifiers(Instruction& inst) {
} }
} }
void ApplyNativeVop3MadMixModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs, void ApplyNativeVop3TernaryModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs,
uint32_t neg) {
Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2};
for (uint32_t i = 0; i < 3u; i++) {
sources[i]->op_sel = ((op_sel >> i) & 1u) != 0;
sources[i]->op_sel_hi = true;
sources[i]->negate = ((neg >> i) & 1u) != 0;
sources[i]->absolute = ((abs >> i) & 1u) != 0;
}
inst.dst.sdwa_sel = ((op_sel & 0x8u) != 0) ? 5u : 4u;
}
void ApplyNativeVop3F16TernaryModifiers(Instruction& inst, uint32_t op_sel, uint32_t abs,
uint32_t neg) { uint32_t neg) {
Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2}; Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2};
for (uint32_t i = 0; i < 3u; i++) { for (uint32_t i = 0; i < 3u; i++) {
@@ -1601,11 +1579,13 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
HasUnsupportedNativeVop3Modifiers(inst.opcode, permlane, mad_mix, vop3b_uses_sdst, HasUnsupportedNativeVop3Modifiers(inst.opcode, permlane, mad_mix, vop3b_uses_sdst,
scalar_modifier_limits, abs, op_sel, clamp, omod, neg); scalar_modifier_limits, abs, op_sel, clamp, omod, neg);
if (modifiers) { if (modifiers) {
SetUnsupported(inst, Family::VOP3, opcode, const char* reason = "VOP3 source modifiers are not implemented";
permlane && (op_sel & ~0x3u) != 0 if (permlane && (op_sel & ~0x3u) != 0) {
? "VOP3 perm-lane op_sel bits are not implemented" reason = "VOP3 perm-lane op_sel bits are not implemented";
: mad_mix ? "VOP3 mad-mix clamp/omod is not implemented" } else if (mad_mix) {
: "VOP3 source modifiers are not implemented"); reason = "VOP3 mad-mix clamp/omod is not implemented";
}
SetUnsupported(inst, Family::VOP3, opcode, reason);
return true; return true;
} }
if (inst.opcode == Opcode::Unsupported) { if (inst.opcode == Opcode::Unsupported) {
@@ -1703,9 +1683,9 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
return false; return false;
} }
if (mad_mix) { if (mad_mix) {
ApplyNativeVop3MadMixModifiers(inst, op_sel, abs, neg); ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg);
} else if (f16_ternary) { } else if (f16_ternary) {
ApplyNativeVop3F16TernaryModifiers(inst, op_sel, abs, neg); ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg);
} else if (b16_binary) { } else if (b16_binary) {
ApplyNativeVop3B16BinaryModifiers(inst, op_sel); ApplyNativeVop3B16BinaryModifiers(inst, op_sel);
} else if (pack_b32_f16) { } else if (pack_b32_f16) {
@@ -10,6 +10,71 @@
namespace Libs::Graphics::ShaderRecompiler::IR { namespace Libs::Graphics::ShaderRecompiler::IR {
namespace { namespace {
Opcode BufferLoadOpcode(const Decoder::Instruction& decoded) {
switch (decoded.data_bits) {
case 8u: return decoded.data_signed ? Opcode::BufferLoadSbyte : Opcode::BufferLoadUbyte;
case 16u: return decoded.data_signed ? Opcode::BufferLoadSshort : Opcode::BufferLoadUshort;
default: return Opcode::BufferLoadDword;
}
}
Opcode BufferStoreOpcode(uint32_t data_bits) {
switch (data_bits) {
case 8u: return Opcode::BufferStoreByte;
case 16u: return Opcode::BufferStoreShort;
default: return Opcode::BufferStoreDword;
}
}
Opcode DsReadOpcode(const Decoder::Instruction& decoded) {
switch (decoded.data_bits) {
case 8u: return decoded.data_signed ? Opcode::DsReadSbyte : Opcode::DsReadUbyte;
case 16u: return decoded.data_signed ? Opcode::DsReadSshort : Opcode::DsReadUshort;
default: return Opcode::DsReadB32;
}
}
Opcode FlatLoadOpcode(const Decoder::Instruction& decoded) {
switch (decoded.data_bits) {
case 8u: return decoded.data_signed ? Opcode::FlatLoadSbyte : Opcode::FlatLoadUbyte;
case 16u: return decoded.data_signed ? Opcode::FlatLoadSshort : Opcode::FlatLoadUshort;
default: return Opcode::FlatLoadDword;
}
}
Opcode FlatStoreOpcode(uint32_t data_bits) {
switch (data_bits) {
case 8u: return Opcode::FlatStoreByte;
case 16u: return Opcode::FlatStoreShort;
default: return Opcode::FlatStoreDword;
}
}
Opcode DsWriteOpcode(uint32_t data_bits) {
switch (data_bits) {
case 8u: return Opcode::DsWriteByte;
case 16u: return Opcode::DsWriteShort;
default: return Opcode::DsWriteB32;
}
}
Opcode LoweredImageOpcode(Decoder::Opcode opcode) {
switch (opcode) {
case Decoder::Opcode::ImageGetResinfo: return Opcode::ImageGetResinfo;
case Decoder::Opcode::ImageGetLod: return Opcode::ImageGetLod;
case Decoder::Opcode::ImageLoad:
case Decoder::Opcode::ImageLoadMip: return Opcode::ImageLoad;
case Decoder::Opcode::ImageGather4Lz:
case Decoder::Opcode::ImageGather4C:
case Decoder::Opcode::ImageGather4CLz:
case Decoder::Opcode::ImageGather4LzO:
case Decoder::Opcode::ImageGather4CO:
case Decoder::Opcode::ImageGather4CLzO:
case Decoder::Opcode::ImageGather4H: return Opcode::ImageGather4;
default: return Opcode::ImageSample;
}
}
bool LowerScalarBufferLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op, bool LowerScalarBufferLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
std::string* error) { std::string* error) {
for (uint32_t i = 0; i < decoded.data_dwords; i++) { for (uint32_t i = 0; i < decoded.data_dwords; i++) {
@@ -54,12 +119,7 @@ bool LowerBufferAddressSources(const Decoder::Instruction& decoded, Instruction&
} }
bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto ir_op = const auto ir_op = BufferLoadOpcode(decoded);
decoded.data_bits == 8u
? (decoded.data_signed ? Opcode::BufferLoadSbyte : Opcode::BufferLoadUbyte)
: decoded.data_bits == 16u
? (decoded.data_signed ? Opcode::BufferLoadSshort : Opcode::BufferLoadUshort)
: Opcode::BufferLoadDword;
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
const auto typed_format_components = TypedBufferFormatComponentCount(decoded); const auto typed_format_components = TypedBufferFormatComponentCount(decoded);
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
@@ -85,9 +145,7 @@ bool LowerBufferLoad(const Decoder::Instruction& decoded, BasicBlock& block, std
} }
bool LowerBufferStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerBufferStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto ir_op = decoded.data_bits == 8u ? Opcode::BufferStoreByte const auto ir_op = BufferStoreOpcode(decoded.data_bits);
: decoded.data_bits == 16u ? Opcode::BufferStoreShort
: Opcode::BufferStoreDword;
auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
if (decoded.data_bits == 32u) { if (decoded.data_bits == 32u) {
const auto typed_format_components = TypedBufferFormatComponentCount(decoded); const auto typed_format_components = TypedBufferFormatComponentCount(decoded);
@@ -131,11 +189,7 @@ ResourceKind DsMemoryKind(const Decoder::Instruction& decoded) {
} }
bool LowerDsRead(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerDsRead(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto ir_op = decoded.data_bits == 8u const auto ir_op = DsReadOpcode(decoded);
? (decoded.data_signed ? Opcode::DsReadSbyte : Opcode::DsReadUbyte)
: decoded.data_bits == 16u
? (decoded.data_signed ? Opcode::DsReadSshort : Opcode::DsReadUshort)
: Opcode::DsReadB32;
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
Instruction inst; Instruction inst;
@@ -164,8 +218,7 @@ bool LowerDsRead2(const Decoder::Instruction& decoded, BasicBlock& block, uint32
inst.src_count = 1; inst.src_count = 1;
inst.memory = inst.memory =
ByteOffsetMemoryInfo(decoded, DsMemoryKind(decoded), offsets[read] + dword * 4u); ByteOffsetMemoryInfo(decoded, DsMemoryKind(decoded), offsets[read] + dword * 4u);
if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, index), inst.dst, if (!LowerRegisterOperand(OffsetDecodedRegister(decoded.dst, index), inst.dst, error) ||
error) ||
!LowerSourceOperand(decoded.src0, inst.src[0], error)) { !LowerSourceOperand(decoded.src0, inst.src[0], error)) {
return false; return false;
} }
@@ -309,11 +362,7 @@ bool LowerImageAtomicU32(const Decoder::Instruction& decoded, BasicBlock& block,
bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto kind = FlatSegmentResourceKind(decoded.memory_segment); const auto kind = FlatSegmentResourceKind(decoded.memory_segment);
const auto ir_op = decoded.data_bits == 8u const auto ir_op = FlatLoadOpcode(decoded);
? (decoded.data_signed ? Opcode::FlatLoadSbyte : Opcode::FlatLoadUbyte)
: decoded.data_bits == 16u
? (decoded.data_signed ? Opcode::FlatLoadSshort : Opcode::FlatLoadUshort)
: Opcode::FlatLoadDword;
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
if (decoded.data_bits == 32u && count > 1u) { if (decoded.data_bits == 32u && count > 1u) {
Instruction inst; Instruction inst;
@@ -356,9 +405,7 @@ bool LowerFlatLoad(const Decoder::Instruction& decoded, BasicBlock& block, std::
bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto kind = FlatSegmentResourceKind(decoded.memory_segment); const auto kind = FlatSegmentResourceKind(decoded.memory_segment);
const auto ir_op = decoded.data_bits == 8u ? Opcode::FlatStoreByte const auto ir_op = FlatStoreOpcode(decoded.data_bits);
: decoded.data_bits == 16u ? Opcode::FlatStoreShort
: Opcode::FlatStoreDword;
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
for (uint32_t dword = 0; dword < count; dword++) { for (uint32_t dword = 0; dword < count; dword++) {
Instruction inst; Instruction inst;
@@ -382,9 +429,7 @@ bool LowerFlatStore(const Decoder::Instruction& decoded, BasicBlock& block, std:
} }
bool LowerDsWrite(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) { bool LowerDsWrite(const Decoder::Instruction& decoded, BasicBlock& block, std::string* error) {
const auto ir_op = decoded.data_bits == 8u ? Opcode::DsWriteByte const auto ir_op = DsWriteOpcode(decoded.data_bits);
: decoded.data_bits == 16u ? Opcode::DsWriteShort
: Opcode::DsWriteB32;
const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u; const auto count = decoded.data_bits == 32u ? decoded.data_dwords : 1u;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
Instruction inst; Instruction inst;
@@ -445,20 +490,7 @@ bool LowerImageOperation(const Decoder::Instruction& decoded, BasicBlock& block,
return true; return true;
} }
inst.op = decoded.opcode == Decoder::Opcode::ImageGetResinfo ? Opcode::ImageGetResinfo inst.op = LoweredImageOpcode(decoded.opcode);
: decoded.opcode == Decoder::Opcode::ImageGetLod ? Opcode::ImageGetLod
: decoded.opcode == Decoder::Opcode::ImageLoad ||
decoded.opcode == Decoder::Opcode::ImageLoadMip
? Opcode::ImageLoad
: decoded.opcode == Decoder::Opcode::ImageGather4Lz ||
decoded.opcode == Decoder::Opcode::ImageGather4C ||
decoded.opcode == Decoder::Opcode::ImageGather4CLz ||
decoded.opcode == Decoder::Opcode::ImageGather4LzO ||
decoded.opcode == Decoder::Opcode::ImageGather4CO ||
decoded.opcode == Decoder::Opcode::ImageGather4CLzO ||
decoded.opcode == Decoder::Opcode::ImageGather4H
? Opcode::ImageGather4
: Opcode::ImageSample;
inst.src_count = 1; inst.src_count = 1;
inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Image); inst.memory = MemoryInfoFromDecoded(decoded, ResourceKind::Image);
if (!LowerRegisterOperand(decoded.dst, inst.dst, error) || if (!LowerRegisterOperand(decoded.dst, inst.dst, error) ||
@@ -11,9 +11,12 @@ void EmitPerInvocationMask(EmitterState& state, const IR::Operand& dst, uint32_t
} }
uint32_t EmitLogicalBinary(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs) { uint32_t EmitLogicalBinary(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs) {
const auto logical_opcode = opcode == OpBitwiseAnd ? OpLogicalAnd uint32_t logical_opcode = OpLogicalNotEqual;
: opcode == OpBitwiseOr ? OpLogicalOr switch (opcode) {
: OpLogicalNotEqual; case OpBitwiseAnd: logical_opcode = OpLogicalAnd; break;
case OpBitwiseOr: logical_opcode = OpLogicalOr; break;
default: break;
}
const auto value = state.builder.AllocateId(); const auto value = state.builder.AllocateId();
state.builder.AddFunction({logical_opcode, state.bool_type, value, lhs, rhs}); state.builder.AddFunction({logical_opcode, state.bool_type, value, lhs, rhs});
return value; return value;
@@ -470,7 +473,8 @@ uint32_t EmitSignExtendLow16U32(EmitterState& state, uint32_t value) {
uint32_t EmitU16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane, uint32_t EmitU16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane,
bool sign_extend) { bool sign_extend) {
const auto raw = EmitValueLoad(state, operand); const auto raw = EmitValueLoad(state, operand);
const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel;
const auto lane = selected_lane ? 1u : 0u;
auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw;
bits = EmitAndConstant(state, bits, 0xffffu); bits = EmitAndConstant(state, bits, 0xffffu);
if (high_lane ? operand.negate_hi : operand.negate) { if (high_lane ? operand.negate_hi : operand.negate) {
@@ -502,8 +506,12 @@ void EmitMinMaxU16(EmitterState& state, const IR::Instruction& inst, bool signed
const auto rhs = EmitU16LaneBits(state, inst.src[1], false, signed_value); const auto rhs = EmitU16LaneBits(state, inst.src[1], false, signed_value);
const auto cond = state.builder.AllocateId(); const auto cond = state.builder.AllocateId();
const auto ret = state.builder.AllocateId(); const auto ret = state.builder.AllocateId();
const auto op = signed_value ? (max_value ? OpSGreaterThan : OpSLessThan) uint32_t op = 0;
: (max_value ? OpUGreaterThan : OpULessThan); if (signed_value) {
op = max_value ? OpSGreaterThan : OpSLessThan;
} else {
op = max_value ? OpUGreaterThan : OpULessThan;
}
state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs}); state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs});
state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs}); state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs});
EmitStoreU32(state, inst.dst, EmitAndConstant(state, ret, 0xffffu)); EmitStoreU32(state, inst.dst, EmitAndConstant(state, ret, 0xffffu));
@@ -2042,7 +2050,8 @@ uint32_t EmitPackedF16Lane(EmitterState& state, const IR::Operand& operand, bool
const auto raw = EmitValueLoad(state, operand); const auto raw = EmitValueLoad(state, operand);
const auto unpacked = state.builder.AllocateId(); const auto unpacked = state.builder.AllocateId();
auto value = state.builder.AllocateId(); auto value = state.builder.AllocateId();
const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel;
const auto lane = selected_lane ? 1u : 0u;
state.builder.AddFunction( state.builder.AddFunction(
{OpExtInst, state.vec2_float_type, unpacked, state.glsl_std450, GlslUnpackHalf2x16, raw}); {OpExtInst, state.vec2_float_type, unpacked, state.glsl_std450, GlslUnpackHalf2x16, raw});
state.builder.AddFunction({OpCompositeExtract, state.float_type, value, unpacked, lane}); state.builder.AddFunction({OpCompositeExtract, state.float_type, value, unpacked, lane});
@@ -2070,7 +2079,8 @@ void EmitCompareF16(EmitterState& state, const IR::Instruction& inst, uint32_t o
uint32_t EmitPackedF16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane) { uint32_t EmitPackedF16LaneBits(EmitterState& state, const IR::Operand& operand, bool high_lane) {
const auto raw = EmitValueLoad(state, operand); const auto raw = EmitValueLoad(state, operand);
const auto lane = high_lane ? (operand.op_sel_hi ? 1u : 0u) : (operand.op_sel ? 1u : 0u); const auto selected_lane = high_lane ? operand.op_sel_hi : operand.op_sel;
const auto lane = selected_lane ? 1u : 0u;
auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw; auto bits = lane != 0u ? EmitShiftRightConstant(state, raw, 16) : raw;
bits = EmitAndConstant(state, bits, 0xffffu); bits = EmitAndConstant(state, bits, 0xffffu);
if (operand.absolute) { if (operand.absolute) {
@@ -2403,8 +2413,12 @@ uint32_t EmitPackedInteger16Select(EmitterState& state, uint32_t lhs, uint32_t r
bool signed_compare, bool max_value) { bool signed_compare, bool max_value) {
const auto cond = state.builder.AllocateId(); const auto cond = state.builder.AllocateId();
const auto ret = state.builder.AllocateId(); const auto ret = state.builder.AllocateId();
const auto op = signed_compare ? (max_value ? OpSGreaterThanEqual : OpSLessThan) uint32_t op = 0;
: (max_value ? OpUGreaterThanEqual : OpULessThan); if (signed_compare) {
op = max_value ? OpSGreaterThanEqual : OpSLessThan;
} else {
op = max_value ? OpUGreaterThanEqual : OpULessThan;
}
state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs}); state.builder.AddFunction({op, state.bool_type, cond, lhs, rhs});
state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs}); state.builder.AddFunction({OpSelect, state.uint_type, ret, cond, lhs, rhs});
return ret; return ret;
@@ -2419,9 +2433,12 @@ uint32_t EmitPackedInteger16Lane(EmitterState& state, const IR::Instruction& ins
const auto arithmetic = opcode == IR::Opcode::PackedAshrrevI16; const auto arithmetic = opcode == IR::Opcode::PackedAshrrevI16;
const auto value = EmitU16LaneBits(state, inst.src[1], high_lane, arithmetic); const auto value = EmitU16LaneBits(state, inst.src[1], high_lane, arithmetic);
const auto ret = state.builder.AllocateId(); const auto ret = state.builder.AllocateId();
const auto shift_op = opcode == IR::Opcode::PackedLshlrevB16 ? OpShiftLeftLogical uint32_t shift_op = OpShiftRightLogical;
: arithmetic ? OpShiftRightArithmetic switch (opcode) {
: OpShiftRightLogical; case IR::Opcode::PackedLshlrevB16: shift_op = OpShiftLeftLogical; break;
case IR::Opcode::PackedAshrrevI16: shift_op = OpShiftRightArithmetic; break;
default: break;
}
state.builder.AddFunction({shift_op, state.uint_type, ret, value, count}); state.builder.AddFunction({shift_op, state.uint_type, ret, value, count});
return ret; return ret;
} }
@@ -23,6 +23,23 @@ uint32_t ConstantImageGatherHorizontalOffsets(EmitterState& state) {
return value; return value;
} }
IR::DescriptorBindingKind StorageImageBindingKind(ImageViewKind view, bool uint_image) {
switch (view) {
case ImageViewKind::Dim2D:
return uint_image ? IR::DescriptorBindingKind::StorageUint2D
: IR::DescriptorBindingKind::Storage2D;
case ImageViewKind::Dim2DArray:
return uint_image ? IR::DescriptorBindingKind::StorageUint2DArray
: IR::DescriptorBindingKind::Storage2DArray;
case ImageViewKind::Dim3D:
return uint_image ? IR::DescriptorBindingKind::StorageUint3D
: IR::DescriptorBindingKind::Storage3D;
default:
return uint_image ? IR::DescriptorBindingKind::StorageUint2D
: IR::DescriptorBindingKind::Storage2D;
}
}
uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resource, uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resource,
uint32_t array_index, bool uint_image, uint32_t array_index, bool uint_image,
ImageViewKind view) { ImageViewKind view) {
@@ -31,8 +48,7 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc
uint32_t variable = uint32_t variable =
uint_image ? state.storage_image_uint_variable : state.storage_image_variable; uint_image ? state.storage_image_uint_variable : state.storage_image_variable;
uint32_t image_type = uint_image ? state.storage_image_uint_type : state.storage_image_type; uint32_t image_type = uint_image ? state.storage_image_uint_type : state.storage_image_type;
IR::DescriptorBindingKind kind = uint_image ? IR::DescriptorBindingKind::StorageUint2D const auto kind = StorageImageBindingKind(view, uint_image);
: IR::DescriptorBindingKind::Storage2D;
switch (view) { switch (view) {
case ImageViewKind::Dim2D: break; case ImageViewKind::Dim2D: break;
case ImageViewKind::Dim2DArray: case ImageViewKind::Dim2DArray:
@@ -42,8 +58,6 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc
: state.storage_image_2d_array_variable; : state.storage_image_2d_array_variable;
image_type = uint_image ? state.storage_image_uint_2d_array_type image_type = uint_image ? state.storage_image_uint_2d_array_type
: state.storage_image_2d_array_type; : state.storage_image_2d_array_type;
kind = uint_image ? IR::DescriptorBindingKind::StorageUint2DArray
: IR::DescriptorBindingKind::Storage2DArray;
break; break;
case ImageViewKind::Dim3D: case ImageViewKind::Dim3D:
pointer_type = uint_image ? state.ptr_uniform_storage_image_uint_3d pointer_type = uint_image ? state.ptr_uniform_storage_image_uint_3d
@@ -52,8 +66,6 @@ uint32_t LoadStorageImageDescriptorAtIndex(EmitterState& state, uint32_t resourc
uint_image ? state.storage_image_uint_3d_variable : state.storage_image_3d_variable; uint_image ? state.storage_image_uint_3d_variable : state.storage_image_3d_variable;
image_type = image_type =
uint_image ? state.storage_image_uint_3d_type : state.storage_image_3d_type; uint_image ? state.storage_image_uint_3d_type : state.storage_image_3d_type;
kind = uint_image ? IR::DescriptorBindingKind::StorageUint3D
: IR::DescriptorBindingKind::Storage3D;
break; break;
} }
const auto pointer = const auto pointer =
@@ -170,15 +182,7 @@ void EmitImageLoad(EmitterState& state, const IR::Instruction& inst) {
void EmitImageStore(EmitterState& state, const IR::Instruction& inst) { void EmitImageStore(EmitterState& state, const IR::Instruction& inst) {
const auto uint_image = inst.memory.kind == IR::ResourceKind::StorageImageUint; const auto uint_image = inst.memory.kind == IR::ResourceKind::StorageImageUint;
const auto view = StorageImageViewKind(state, inst.memory, uint_image, inst.pc); const auto view = StorageImageViewKind(state, inst.memory, uint_image, inst.pc);
const auto binding = ResourceForDescriptor( const auto binding = ResourceForDescriptor(state, StorageImageBindingKind(view, uint_image),
state,
uint_image
? (view == ImageViewKind::Dim2DArray ? IR::DescriptorBindingKind::StorageUint2DArray
: view == ImageViewKind::Dim3D ? IR::DescriptorBindingKind::StorageUint3D
: IR::DescriptorBindingKind::StorageUint2D)
: (view == ImageViewKind::Dim2DArray ? IR::DescriptorBindingKind::Storage2DArray
: view == ImageViewKind::Dim3D ? IR::DescriptorBindingKind::Storage3D
: IR::DescriptorBindingKind::Storage2D),
inst.memory.resource); inst.memory.resource);
const auto image = LoadStorageImageDescriptorAtIndex(state, inst.memory.resource, const auto image = LoadStorageImageDescriptorAtIndex(state, inst.memory.resource,
binding.array_index, uint_image, view); binding.array_index, uint_image, view);
@@ -274,9 +278,12 @@ void EmitImageSample(EmitterState& state, const IR::Instruction& inst) {
const auto sample = state.builder.AllocateId(); const auto sample = state.builder.AllocateId();
const auto dref = HasImageSampleFlag(inst, Decoder::ImageSampleFlagCompare); const auto dref = HasImageSampleFlag(inst, Decoder::ImageSampleFlagCompare);
const bool integer = inst.memory.kind == IR::ResourceKind::ImageUint; const bool integer = inst.memory.kind == IR::ResourceKind::ImageUint;
const auto result_type = dref ? state.float_type uint32_t result_type = state.vec4_float_type;
: integer ? state.vec4_uint_type if (dref) {
: state.vec4_float_type; result_type = state.float_type;
} else if (integer) {
result_type = state.vec4_uint_type;
}
const auto explicit_lod = ImageSampleNeedsExplicitLod(state, inst); const auto explicit_lod = ImageSampleNeedsExplicitLod(state, inst);
const auto opcode = ImageSampleOpcode(state, inst); const auto opcode = ImageSampleOpcode(state, inst);
const auto coord = const auto coord =
@@ -65,8 +65,7 @@ DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uin
const auto target = state.builder.AllocateId(); const auto target = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction(
{OpBitwiseAnd, state.uint_type, quad_base, subid, ConstantU32(state, 0xfffffffcu)}); {OpBitwiseAnd, state.uint_type, quad_base, subid, ConstantU32(state, 0xfffffffcu)});
state.builder.AddFunction( state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 3)});
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 3)});
state.builder.AddFunction( state.builder.AddFunction(
{OpShiftLeftLogical, state.uint_type, shift, lane, ConstantU32(state, 1)}); {OpShiftLeftLogical, state.uint_type, shift, lane, ConstantU32(state, 1)});
state.builder.AddFunction( state.builder.AddFunction(
@@ -86,8 +85,7 @@ DppTargetLane EmitDppRowShiftTargetLane(EmitterState& state, uint32_t subid, uin
const auto valid = state.builder.AllocateId(); const auto valid = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction(
{OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)}); {OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)});
state.builder.AddFunction( state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)});
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)});
if (left) { if (left) {
state.builder.AddFunction( state.builder.AddFunction(
{OpIAdd, state.uint_type, lane_shifted, lane, ConstantU32(state, amount)}); {OpIAdd, state.uint_type, lane_shifted, lane, ConstantU32(state, amount)});
@@ -114,8 +112,7 @@ DppTargetLane EmitDppRowRotateRightTargetLane(EmitterState& state, uint32_t subi
const auto target = state.builder.AllocateId(); const auto target = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction(
{OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)}); {OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)});
state.builder.AddFunction( state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)});
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)});
state.builder.AddFunction( state.builder.AddFunction(
{OpUGreaterThanEqual, state.bool_type, in_high, lane, ConstantU32(state, amount)}); {OpUGreaterThanEqual, state.bool_type, in_high, lane, ConstantU32(state, amount)});
state.builder.AddFunction({OpISub, state.uint_type, minus, lane, ConstantU32(state, amount)}); state.builder.AddFunction({OpISub, state.uint_type, minus, lane, ConstantU32(state, amount)});
@@ -235,8 +232,7 @@ uint32_t EmitLaneMaskPartU32(EmitterState& state, uint32_t part) {
const auto subid = EmitSubgroupLocalInvocationId(state); const auto subid = EmitSubgroupLocalInvocationId(state);
const auto lane = state.builder.AllocateId(); const auto lane = state.builder.AllocateId();
const auto bit = state.builder.AllocateId(); const auto bit = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)});
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)});
state.builder.AddFunction( state.builder.AddFunction(
{OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane}); {OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane});
if (part == 0) { if (part == 0) {
@@ -265,8 +261,7 @@ uint32_t EmitThreadMaskBelowPartU32(EmitterState& state, uint32_t part) {
const auto lane = state.builder.AllocateId(); const auto lane = state.builder.AllocateId();
const auto bit = state.builder.AllocateId(); const auto bit = state.builder.AllocateId();
const auto below = state.builder.AllocateId(); const auto below = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction({OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)});
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 31)});
state.builder.AddFunction( state.builder.AddFunction(
{OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane}); {OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), lane});
state.builder.AddFunction({OpISub, state.uint_type, below, bit, ConstantU32(state, 1)}); state.builder.AddFunction({OpISub, state.uint_type, below, bit, ConstantU32(state, 1)});
@@ -527,9 +522,12 @@ uint32_t EmitFloatLoad(EmitterState& state, const IR::Operand& operand) {
uint32_t ApplyResultModifiersF32(EmitterState& state, uint32_t value, const IR::Operand& dst) { uint32_t ApplyResultModifiersF32(EmitterState& state, uint32_t value, const IR::Operand& dst) {
uint32_t result = value; uint32_t result = value;
if (dst.omod != 0) { if (dst.omod != 0) {
const uint32_t bits = dst.omod == 1u ? 0x40000000u uint32_t bits = 0x3f000000u;
: dst.omod == 2u ? 0x40800000u switch (dst.omod) {
: 0x3f000000u; case 1u: bits = 0x40000000u; break;
case 2u: bits = 0x40800000u; break;
default: break;
}
const auto scaled = state.builder.AllocateId(); const auto scaled = state.builder.AllocateId();
state.builder.AddFunction( state.builder.AddFunction(
{OpFMul, state.float_type, scaled, result, ConstantF32(state, bits)}); {OpFMul, state.float_type, scaled, result, ConstantF32(state, bits)});