diff options
| author | 2019-09-18 01:50:40 -0300 | |
|---|---|---|
| committer | 2019-09-21 17:33:52 -0300 | |
| commit | 44000971e271e350638611b0265a3fed7bcced2a (patch) | |
| tree | b224df1c5477a7e31cb0176d9299b635c6363f61 /src/video_core/shader | |
| parent | shader/image: Implement SULD and remove irrelevant code (diff) | |
| download | yuzu-44000971e271e350638611b0265a3fed7bcced2a.tar.gz yuzu-44000971e271e350638611b0265a3fed7bcced2a.tar.xz yuzu-44000971e271e350638611b0265a3fed7bcced2a.zip | |
gl_shader_decompiler: Use uint for images and fix SUATOM
In the process remove implementation of SUATOM.MIN and SUATOM.MAX as
these require a distinction between U32 and S32. These have to be
implemented with imageCompSwap loop.
Diffstat (limited to 'src/video_core/shader')
| -rw-r--r-- | src/video_core/shader/decode/image.cpp | 66 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 46 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 9 |
3 files changed, 52 insertions, 69 deletions
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index e611f9f3b..95ec1cdd9 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -101,32 +101,35 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 101 | UNIMPLEMENTED_IF(instr.suatom_d.is_ba != 0); | 101 | UNIMPLEMENTED_IF(instr.suatom_d.is_ba != 0); |
| 102 | 102 | ||
| 103 | const OperationCode operation_code = [instr] { | 103 | const OperationCode operation_code = [instr] { |
| 104 | switch (instr.suatom_d.operation) { | 104 | switch (instr.suatom_d.operation_type) { |
| 105 | case Tegra::Shader::ImageAtomicOperation::Add: | 105 | case Tegra::Shader::ImageAtomicOperationType::S32: |
| 106 | return OperationCode::AtomicImageAdd; | 106 | case Tegra::Shader::ImageAtomicOperationType::U32: |
| 107 | case Tegra::Shader::ImageAtomicOperation::Min: | 107 | switch (instr.suatom_d.operation) { |
| 108 | return OperationCode::AtomicImageMin; | 108 | case Tegra::Shader::ImageAtomicOperation::Add: |
| 109 | case Tegra::Shader::ImageAtomicOperation::Max: | 109 | return OperationCode::AtomicImageAdd; |
| 110 | return OperationCode::AtomicImageMax; | 110 | case Tegra::Shader::ImageAtomicOperation::And: |
| 111 | case Tegra::Shader::ImageAtomicOperation::And: | 111 | return OperationCode::AtomicImageAnd; |
| 112 | return OperationCode::AtomicImageAnd; | 112 | case Tegra::Shader::ImageAtomicOperation::Or: |
| 113 | case Tegra::Shader::ImageAtomicOperation::Or: | 113 | return OperationCode::AtomicImageOr; |
| 114 | return OperationCode::AtomicImageOr; | 114 | case Tegra::Shader::ImageAtomicOperation::Xor: |
| 115 | case Tegra::Shader::ImageAtomicOperation::Xor: | 115 | return OperationCode::AtomicImageXor; |
| 116 | return OperationCode::AtomicImageXor; | 116 | case Tegra::Shader::ImageAtomicOperation::Exch: |
| 117 | case Tegra::Shader::ImageAtomicOperation::Exch: | 117 | return OperationCode::AtomicImageExchange; |
| 118 | return OperationCode::AtomicImageExchange; | 118 | } |
| 119 | default: | 119 | default: |
| 120 | UNIMPLEMENTED_MSG("Unimplemented operation={}", | 120 | break; |
| 121 | static_cast<u32>(instr.suatom_d.operation.Value())); | ||
| 122 | return OperationCode::AtomicImageAdd; | ||
| 123 | } | 121 | } |
| 122 | UNIMPLEMENTED_MSG("Unimplemented operation={} type={}", | ||
| 123 | static_cast<u64>(instr.suatom_d.operation.Value()), | ||
| 124 | static_cast<u64>(instr.suatom_d.operation_type.Value())); | ||
| 125 | return OperationCode::AtomicImageAdd; | ||
| 124 | }(); | 126 | }(); |
| 125 | 127 | ||
| 126 | Node value = GetRegister(instr.gpr0); | 128 | Node value = GetRegister(instr.gpr0); |
| 127 | 129 | ||
| 128 | const auto type = instr.suatom_d.image_type; | 130 | const auto type = instr.suatom_d.image_type; |
| 129 | const auto& image{GetImage(instr.image, type, instr.suatom_d.size)}; | 131 | auto& image = GetImage(instr.image, type); |
| 132 | image.MarkAtomic(); | ||
| 130 | 133 | ||
| 131 | MetaImage meta{image, {std::move(value)}}; | 134 | MetaImage meta{image, {std::move(value)}}; |
| 132 | SetRegister(bb, instr.gpr0, Operation(operation_code, meta, GetCoordinates(type))); | 135 | SetRegister(bb, instr.gpr0, Operation(operation_code, meta, GetCoordinates(type))); |
| @@ -139,35 +142,32 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 139 | return pc; | 142 | return pc; |
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type, | 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { |
| 143 | std::optional<Tegra::Shader::ImageAtomicSize> size) { | ||
| 144 | const auto offset{static_cast<std::size_t>(image.index.Value())}; | 146 | const auto offset{static_cast<std::size_t>(image.index.Value())}; |
| 145 | if (const auto image = TryUseExistingImage(offset, type, size)) { | 147 | if (const auto image = TryUseExistingImage(offset, type)) { |
| 146 | return *image; | 148 | return *image; |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | const std::size_t next_index{used_images.size()}; | 151 | const std::size_t next_index{used_images.size()}; |
| 150 | return used_images.emplace(offset, Image{offset, next_index, type, size}).first->second; | 152 | return used_images.emplace(offset, Image{offset, next_index, type}).first->second; |
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type, | 155 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { |
| 154 | std::optional<Tegra::Shader::ImageAtomicSize> size) { | ||
| 155 | const Node image_register{GetRegister(reg)}; | 156 | const Node image_register{GetRegister(reg)}; |
| 156 | const auto [base_image, cbuf_index, cbuf_offset]{ | 157 | const auto [base_image, cbuf_index, cbuf_offset]{ |
| 157 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; | 158 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; |
| 158 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; | 159 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; |
| 159 | 160 | ||
| 160 | if (const auto image = TryUseExistingImage(cbuf_key, type, size)) { | 161 | if (const auto image = TryUseExistingImage(cbuf_key, type)) { |
| 161 | return *image; | 162 | return *image; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | const std::size_t next_index{used_images.size()}; | 165 | const std::size_t next_index{used_images.size()}; |
| 165 | return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type, size}) | 166 | return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type}) |
| 166 | .first->second; | 167 | .first->second; |
| 167 | } | 168 | } |
| 168 | 169 | ||
| 169 | Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type, | 170 | Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) { |
| 170 | std::optional<Tegra::Shader::ImageAtomicSize> size) { | ||
| 171 | auto it = used_images.find(offset); | 171 | auto it = used_images.find(offset); |
| 172 | if (it == used_images.end()) { | 172 | if (it == used_images.end()) { |
| 173 | return nullptr; | 173 | return nullptr; |
| @@ -175,14 +175,6 @@ Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type, | |||
| 175 | auto& image = it->second; | 175 | auto& image = it->second; |
| 176 | ASSERT(image.GetType() == type); | 176 | ASSERT(image.GetType() == type); |
| 177 | 177 | ||
| 178 | if (size) { | ||
| 179 | // We know the size, if it's known it has to be the same as before, otherwise we can set it. | ||
| 180 | if (image.IsSizeKnown()) { | ||
| 181 | ASSERT(image.GetSize() == size); | ||
| 182 | } else { | ||
| 183 | image.SetSize(*size); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | return ℑ | 178 | return ℑ |
| 187 | } | 179 | } |
| 188 | 180 | ||
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index e5b75783d..338bab17c 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -149,11 +149,10 @@ enum class OperationCode { | |||
| 149 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | 149 | TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 |
| 150 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 | 150 | TexelFetch, /// (MetaTexture, int[N], int) -> float4 |
| 151 | 151 | ||
| 152 | ImageLoad, /// (MetaImage, int[N] coords) -> void | 152 | ImageLoad, /// (MetaImage, int[N] coords) -> void |
| 153 | ImageStore, /// (MetaImage, int[N] coords) -> void | 153 | ImageStore, /// (MetaImage, int[N] coords) -> void |
| 154 | |||
| 154 | AtomicImageAdd, /// (MetaImage, int[N] coords) -> void | 155 | AtomicImageAdd, /// (MetaImage, int[N] coords) -> void |
| 155 | AtomicImageMin, /// (MetaImage, int[N] coords) -> void | ||
| 156 | AtomicImageMax, /// (MetaImage, int[N] coords) -> void | ||
| 157 | AtomicImageAnd, /// (MetaImage, int[N] coords) -> void | 156 | AtomicImageAnd, /// (MetaImage, int[N] coords) -> void |
| 158 | AtomicImageOr, /// (MetaImage, int[N] coords) -> void | 157 | AtomicImageOr, /// (MetaImage, int[N] coords) -> void |
| 159 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void | 158 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void |
| @@ -295,21 +294,18 @@ private: | |||
| 295 | 294 | ||
| 296 | class Image final { | 295 | class Image final { |
| 297 | public: | 296 | public: |
| 298 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, | 297 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type) |
| 299 | std::optional<Tegra::Shader::ImageAtomicSize> size) | 298 | : offset{offset}, index{index}, type{type}, is_bindless{false} {} |
| 300 | : offset{offset}, index{index}, type{type}, is_bindless{false}, size{size} {} | ||
| 301 | 299 | ||
| 302 | constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | 300 | constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, |
| 303 | Tegra::Shader::ImageType type, | 301 | Tegra::Shader::ImageType type) |
| 304 | std::optional<Tegra::Shader::ImageAtomicSize> size) | ||
| 305 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | 302 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, |
| 306 | is_bindless{true}, size{size} {} | 303 | is_bindless{true} {} |
| 307 | 304 | ||
| 308 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, | 305 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, |
| 309 | bool is_bindless, bool is_written, bool is_read, | 306 | bool is_bindless, bool is_written, bool is_read, bool is_atomic) |
| 310 | std::optional<Tegra::Shader::ImageAtomicSize> size) | ||
| 311 | : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, | 307 | : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, |
| 312 | is_written{is_written}, is_read{is_read}, size{size} {} | 308 | is_written{is_written}, is_read{is_read}, is_atomic{is_atomic} {} |
| 313 | 309 | ||
| 314 | void MarkWrite() { | 310 | void MarkWrite() { |
| 315 | is_written = true; | 311 | is_written = true; |
| @@ -319,8 +315,10 @@ public: | |||
| 319 | is_read = true; | 315 | is_read = true; |
| 320 | } | 316 | } |
| 321 | 317 | ||
| 322 | void SetSize(Tegra::Shader::ImageAtomicSize size_) { | 318 | void MarkAtomic() { |
| 323 | size = size_; | 319 | MarkWrite(); |
| 320 | MarkRead(); | ||
| 321 | is_atomic = true; | ||
| 324 | } | 322 | } |
| 325 | 323 | ||
| 326 | constexpr std::size_t GetOffset() const { | 324 | constexpr std::size_t GetOffset() const { |
| @@ -347,21 +345,17 @@ public: | |||
| 347 | return is_read; | 345 | return is_read; |
| 348 | } | 346 | } |
| 349 | 347 | ||
| 350 | constexpr std::pair<u32, u32> GetBindlessCBuf() const { | 348 | constexpr bool IsAtomic() const { |
| 351 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | 349 | return is_atomic; |
| 352 | } | ||
| 353 | |||
| 354 | constexpr bool IsSizeKnown() const { | ||
| 355 | return size.has_value(); | ||
| 356 | } | 350 | } |
| 357 | 351 | ||
| 358 | constexpr Tegra::Shader::ImageAtomicSize GetSize() const { | 352 | constexpr std::pair<u32, u32> GetBindlessCBuf() const { |
| 359 | return size.value(); | 353 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; |
| 360 | } | 354 | } |
| 361 | 355 | ||
| 362 | constexpr bool operator<(const Image& rhs) const { | 356 | constexpr bool operator<(const Image& rhs) const { |
| 363 | return std::tie(offset, index, type, size, is_bindless) < | 357 | return std::tie(offset, index, type, is_bindless) < |
| 364 | std::tie(rhs.offset, rhs.index, rhs.type, rhs.size, rhs.is_bindless); | 358 | std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless); |
| 365 | } | 359 | } |
| 366 | 360 | ||
| 367 | private: | 361 | private: |
| @@ -371,7 +365,7 @@ private: | |||
| 371 | bool is_bindless{}; | 365 | bool is_bindless{}; |
| 372 | bool is_written{}; | 366 | bool is_written{}; |
| 373 | bool is_read{}; | 367 | bool is_read{}; |
| 374 | std::optional<Tegra::Shader::ImageAtomicSize> size{}; | 368 | bool is_atomic{}; |
| 375 | }; | 369 | }; |
| 376 | 370 | ||
| 377 | struct GlobalMemoryBase { | 371 | struct GlobalMemoryBase { |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 6aed9bb84..c3e147eea 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -276,16 +276,13 @@ private: | |||
| 276 | bool is_shadow); | 276 | bool is_shadow); |
| 277 | 277 | ||
| 278 | /// Accesses an image. | 278 | /// Accesses an image. |
| 279 | Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type, | 279 | Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); |
| 280 | std::optional<Tegra::Shader::ImageAtomicSize> size = {}); | ||
| 281 | 280 | ||
| 282 | /// Access a bindless image sampler. | 281 | /// Access a bindless image sampler. |
| 283 | Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type, | 282 | Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); |
| 284 | std::optional<Tegra::Shader::ImageAtomicSize> size = {}); | ||
| 285 | 283 | ||
| 286 | /// Tries to access an existing image, updating it's state as needed | 284 | /// Tries to access an existing image, updating it's state as needed |
| 287 | Image* TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type, | 285 | Image* TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type); |
| 288 | std::optional<Tegra::Shader::ImageAtomicSize> size); | ||
| 289 | 286 | ||
| 290 | /// Extracts a sequence of bits from a node | 287 | /// Extracts a sequence of bits from a node |
| 291 | Node BitfieldExtract(Node value, u32 offset, u32 bits); | 288 | Node BitfieldExtract(Node value, u32 offset, u32 bits); |