From a3b4c77fdb82b1396a4002e074a647555bb4f88f Mon Sep 17 00:00:00 2001 From: Triang3l Date: Mon, 11 May 2020 16:30:09 +0300 Subject: [PATCH] [GPU] Add texture_util::SwizzleSigns for later --- src/xenia/gpu/d3d12/texture_cache.cc | 1 + src/xenia/gpu/dxbc_shader_translator_fetch.cc | 1 + src/xenia/gpu/texture_util.cc | 37 +++++++++++++++++++ src/xenia/gpu/texture_util.h | 11 ++++++ src/xenia/gpu/xenos.h | 6 +++ 5 files changed, 56 insertions(+) diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index a3b4af3ea..7a0c61400 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -2160,6 +2160,7 @@ void TextureCache::BindingInfoFromFetchConstant( *swizzle_out = swizzle; } + // TODO(Triang3l): Move to texture_util::SwizzleSigns. if (has_unsigned_out != nullptr) { *has_unsigned_out = fetch.sign_x != TextureSign::kSigned || fetch.sign_y != TextureSign::kSigned || diff --git a/src/xenia/gpu/dxbc_shader_translator_fetch.cc b/src/xenia/gpu/dxbc_shader_translator_fetch.cc index 9ccc212bd..4057c2e71 100644 --- a/src/xenia/gpu/dxbc_shader_translator_fetch.cc +++ b/src/xenia/gpu/dxbc_shader_translator_fetch.cc @@ -2520,6 +2520,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction( // linearization must be done on color values in 0...1 range, and this // is closer to the storage format, while exponent bias is closer to the // actual usage in shaders. + // TODO(Triang3l): Signs should be pre-swizzled. for (uint32_t i = 0; i < 4; ++i) { // Extract the sign values from dword 0 ([0].x or [1].z) of the fetch // constant (in bits 2:9, 2 bits per component) to sign_temp.x. diff --git a/src/xenia/gpu/texture_util.cc b/src/xenia/gpu/texture_util.cc index f6b96a883..be0e37a5c 100644 --- a/src/xenia/gpu/texture_util.cc +++ b/src/xenia/gpu/texture_util.cc @@ -340,6 +340,43 @@ int32_t GetTiledOffset3D(int32_t x, int32_t y, int32_t z, uint32_t width, return address; } +uint32_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch, + bool* any_unsigned_out, bool* any_signed_out) { + uint32_t signs = 0; + bool any_unsigned = false, any_signed = false; + // 0b00 or 0b01 for each component, whether it's constant 0/1. + uint32_t constant_mask = 0b00000000; + for (uint32_t i = 0; i < 4; ++i) { + uint32_t swizzle = (fetch.swizzle >> (i * 3)) & 0b111; + if (swizzle & 0b100) { + constant_mask |= 1 << (i * 2); + } else { + TextureSign sign = + TextureSign((fetch.dword_0 >> (2 + swizzle * 2)) & 0b11); + signs |= uint32_t(sign) << (i * 2); + if (sign == TextureSign::kSigned) { + any_signed = true; + } else { + any_unsigned = true; + } + } + } + if (any_signed && !any_unsigned) { + // If only signed and constant components, reading just from the signed host + // view is enough. + signs |= uint32_t(TextureSign::kSigned) * constant_mask; + } else { + signs |= uint32_t(TextureSign::kUnsigned) * constant_mask; + } + if (any_unsigned_out) { + *any_unsigned_out = any_unsigned; + } + if (any_signed_out) { + *any_signed_out = any_signed; + } + return signs; +} + } // namespace texture_util } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/texture_util.h b/src/xenia/gpu/texture_util.h index ecd99b07b..a406d4f6d 100644 --- a/src/xenia/gpu/texture_util.h +++ b/src/xenia/gpu/texture_util.h @@ -88,6 +88,17 @@ int32_t GetTiledOffset2D(int32_t x, int32_t y, uint32_t width, int32_t GetTiledOffset3D(int32_t x, int32_t y, int32_t z, uint32_t width, uint32_t height, uint32_t bpb_log2); +// Returns four packed TextureSign values swizzled according to the swizzle in +// the fetch constant, so the shader can apply TextureSigns after reading a +// pre-swizzled texture. 0/1 elements are considered unsigned (and not biased), +// however, if all non-constant components are signed, 0/1 are considered signed +// too (because in backends, unsigned and signed textures may use separate views +// with different formats, so just one view is used for both signed and constant +// components). +uint32_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch, + bool* any_unsigned_out = nullptr, + bool* any_signed_out = nullptr); + } // namespace texture_util } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/xenos.h b/src/xenia/gpu/xenos.h index e2e7525ac..11081663c 100644 --- a/src/xenia/gpu/xenos.h +++ b/src/xenia/gpu/xenos.h @@ -657,6 +657,12 @@ XEPACKEDUNION(xe_gpu_vertex_fetch_t, { XEPACKEDUNION(xe_gpu_texture_fetch_t, { XEPACKEDSTRUCTANONYMOUS({ FetchConstantType type : 2; // +0 dword_0 + // Likely before the swizzle, seems logical from R5xx (SIGNED_COMP0/1/2/3 + // set the signedness of components 0/1/2/3, while SEL_ALPHA/RED/GREEN/BLUE + // specify "swizzling for each channel at the input of the pixel shader", + // which can be texture components 0/1/2/3 or constant 0/1) and R6xx + // (signedness is FORMAT_COMP_X/Y/Z/W, while the swizzle is DST_SEL_X/Y/Z/W, + // which is named in resources the same as DST_SEL in fetch clauses). TextureSign sign_x : 2; // +2 TextureSign sign_y : 2; // +4 TextureSign sign_z : 2; // +6