mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-26 21:06:53 +01:00
graphics: cleanup
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)});
|
||||||
|
|||||||
Reference in New Issue
Block a user