|
4 | 4 | #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
5 | 5 |
|
6 | 6 | LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
|
7 |
| - : LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer), m_format(format) |
| 7 | + : LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer), m_baseTexture(texture) |
8 | 8 | {
|
9 |
| - MTL::TextureType textureType; |
10 |
| - switch (dim) |
11 |
| - { |
12 |
| - case Latte::E_DIM::DIM_1D: |
13 |
| - textureType = MTL::TextureType1D; |
14 |
| - break; |
15 |
| - case Latte::E_DIM::DIM_2D: |
16 |
| - case Latte::E_DIM::DIM_2D_MSAA: |
17 |
| - textureType = MTL::TextureType2D; |
18 |
| - break; |
19 |
| - case Latte::E_DIM::DIM_2D_ARRAY: |
20 |
| - textureType = MTL::TextureType2DArray; |
21 |
| - break; |
22 |
| - case Latte::E_DIM::DIM_3D: |
23 |
| - textureType = MTL::TextureType3D; |
24 |
| - break; |
25 |
| - case Latte::E_DIM::DIM_CUBEMAP: |
26 |
| - textureType = MTL::TextureTypeCube; // TODO: check this |
27 |
| - break; |
28 |
| - default: |
29 |
| - cemu_assert_unimplemented(); |
30 |
| - textureType = MTL::TextureType2D; |
31 |
| - break; |
32 |
| - } |
33 |
| - |
34 |
| - uint32 baseLevel = firstMip; |
35 |
| - uint32 levelCount = this->numMip; |
36 |
| - uint32 baseLayer; |
37 |
| - uint32 layerCount; |
38 |
| - // TODO: check if base texture is 3D texture as well |
39 |
| - if (textureType == MTL::TextureType3D) |
40 |
| - { |
41 |
| - cemu_assert_debug(firstMip == 0); |
42 |
| - cemu_assert_debug(this->numSlice == baseTexture->depth); |
43 |
| - baseLayer = 0; |
44 |
| - layerCount = 1; |
45 |
| - } |
46 |
| - else |
47 |
| - { |
48 |
| - baseLayer = firstSlice; |
49 |
| - layerCount = this->numSlice; |
50 |
| - } |
51 |
| - |
52 |
| - // TODO: swizzle |
53 |
| - |
54 |
| - auto formatInfo = GetMtlPixelFormatInfo(format, texture->IsDepth()); |
55 |
| - m_texture = texture->GetTexture()->newTextureView(formatInfo.pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount)); |
56 | 9 | }
|
57 | 10 |
|
58 | 11 | LatteTextureViewMtl::~LatteTextureViewMtl()
|
59 | 12 | {
|
60 |
| - m_texture->release(); |
| 13 | + for (sint32 i = 0; i < std::size(m_viewCache); i++) |
| 14 | + { |
| 15 | + if (m_viewCache[i].key != INVALID_SWIZZLE) |
| 16 | + m_viewCache[i].texture->release(); |
| 17 | + } |
| 18 | + |
| 19 | + for (auto& [key, texture] : m_fallbackViewCache) |
| 20 | + { |
| 21 | + texture->release(); |
| 22 | + } |
| 23 | +} |
| 24 | + |
| 25 | +MTL::Texture* LatteTextureViewMtl::GetSwizzledView(uint32 gpuSamplerSwizzle) |
| 26 | +{ |
| 27 | + // Mask out |
| 28 | + gpuSamplerSwizzle &= 0x0FFF0000; |
| 29 | + |
| 30 | + if (gpuSamplerSwizzle == RGBA_SWIZZLE) |
| 31 | + { |
| 32 | + return m_baseTexture->GetTexture(); |
| 33 | + } |
| 34 | + else |
| 35 | + { |
| 36 | + // First, try to find a view in the cache |
| 37 | + |
| 38 | + // Fast cache |
| 39 | + sint32 freeIndex = -1; |
| 40 | + for (sint32 i = 0; i < std::size(m_viewCache); i++) |
| 41 | + { |
| 42 | + if (m_viewCache[i].key == gpuSamplerSwizzle) |
| 43 | + { |
| 44 | + return m_viewCache[i].texture; |
| 45 | + } |
| 46 | + else if (m_viewCache[i].key == INVALID_SWIZZLE && freeIndex == -1) |
| 47 | + { |
| 48 | + freeIndex = i; |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + // Fallback cache |
| 53 | + auto it = m_fallbackViewCache.find(gpuSamplerSwizzle); |
| 54 | + if (it != m_fallbackViewCache.end()) |
| 55 | + { |
| 56 | + return it->second; |
| 57 | + } |
| 58 | + |
| 59 | + MTL::Texture* texture = CreateSwizzledView(gpuSamplerSwizzle); |
| 60 | + if (freeIndex != -1) |
| 61 | + m_viewCache[freeIndex] = {gpuSamplerSwizzle, texture}; |
| 62 | + else |
| 63 | + it->second = texture; |
| 64 | + |
| 65 | + return texture; |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +MTL::Texture* LatteTextureViewMtl::CreateSwizzledView(uint32 gpuSamplerSwizzle) |
| 70 | +{ |
| 71 | + uint32 compSelR = (gpuSamplerSwizzle >> 16) & 0x7; |
| 72 | + uint32 compSelG = (gpuSamplerSwizzle >> 19) & 0x7; |
| 73 | + uint32 compSelB = (gpuSamplerSwizzle >> 22) & 0x7; |
| 74 | + uint32 compSelA = (gpuSamplerSwizzle >> 25) & 0x7; |
| 75 | + // TODO: adjust |
| 76 | + |
| 77 | + MTL::TextureType textureType; |
| 78 | + switch (dim) |
| 79 | + { |
| 80 | + case Latte::E_DIM::DIM_1D: |
| 81 | + textureType = MTL::TextureType1D; |
| 82 | + break; |
| 83 | + case Latte::E_DIM::DIM_2D: |
| 84 | + case Latte::E_DIM::DIM_2D_MSAA: |
| 85 | + textureType = MTL::TextureType2D; |
| 86 | + break; |
| 87 | + case Latte::E_DIM::DIM_2D_ARRAY: |
| 88 | + textureType = MTL::TextureType2DArray; |
| 89 | + break; |
| 90 | + case Latte::E_DIM::DIM_3D: |
| 91 | + textureType = MTL::TextureType3D; |
| 92 | + break; |
| 93 | + case Latte::E_DIM::DIM_CUBEMAP: |
| 94 | + textureType = MTL::TextureTypeCube; // TODO: check this |
| 95 | + break; |
| 96 | + default: |
| 97 | + cemu_assert_unimplemented(); |
| 98 | + textureType = MTL::TextureType2D; |
| 99 | + break; |
| 100 | + } |
| 101 | + |
| 102 | + uint32 baseLevel = firstMip; |
| 103 | + uint32 levelCount = this->numMip; |
| 104 | + uint32 baseLayer; |
| 105 | + uint32 layerCount; |
| 106 | + // TODO: check if base texture is 3D texture as well |
| 107 | + if (textureType == MTL::TextureType3D) |
| 108 | + { |
| 109 | + cemu_assert_debug(firstMip == 0); |
| 110 | + cemu_assert_debug(this->numSlice == baseTexture->depth); |
| 111 | + baseLayer = 0; |
| 112 | + layerCount = 1; |
| 113 | + } |
| 114 | + else |
| 115 | + { |
| 116 | + baseLayer = firstSlice; |
| 117 | + layerCount = this->numSlice; |
| 118 | + } |
| 119 | + |
| 120 | + // TODO: swizzle |
| 121 | + |
| 122 | + auto formatInfo = GetMtlPixelFormatInfo(format, m_baseTexture->IsDepth()); |
| 123 | + MTL::Texture* texture = m_baseTexture->GetTexture()->newTextureView(formatInfo.pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount)); |
| 124 | + |
| 125 | + return texture; |
61 | 126 | }
|
0 commit comments