summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp84
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h8
-rw-r--r--src/video_core/textures/decoders.cpp2
3 files changed, 83 insertions, 11 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index f9b4a4b87..3a00d9383 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -88,6 +88,8 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
88 // DepthStencil formats 88 // DepthStencil formats
89 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, 89 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
90 false}, // Z24S8 90 false}, // Z24S8
91 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm,
92 false}, // S8Z24
91}}; 93}};
92 94
93static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { 95static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
@@ -131,13 +133,6 @@ MathUtil::Rectangle<u32> SurfaceParams::GetRect() const {
131 return {0, actual_height, width, 0}; 133 return {0, actual_height, width, 0};
132} 134}
133 135
134static void ConvertASTCToRGBA8(std::vector<u8>& data, PixelFormat format, u32 width, u32 height) {
135 u32 block_width{};
136 u32 block_height{};
137 std::tie(block_width, block_height) = GetASTCBlockSize(format);
138 data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
139}
140
141template <bool morton_to_gl, PixelFormat format> 136template <bool morton_to_gl, PixelFormat format>
142void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::GPUVAddr addr) { 137void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::GPUVAddr addr) {
143 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT; 138 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT;
@@ -177,6 +172,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
177 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, 172 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
178 MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, 173 MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>,
179 MortonCopy<true, PixelFormat::ASTC_2D_4X4>, MortonCopy<true, PixelFormat::Z24S8>, 174 MortonCopy<true, PixelFormat::ASTC_2D_4X4>, MortonCopy<true, PixelFormat::Z24S8>,
175 MortonCopy<true, PixelFormat::S8Z24>,
180}; 176};
181 177
182static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), 178static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
@@ -197,6 +193,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
197 nullptr, 193 nullptr,
198 MortonCopy<false, PixelFormat::ABGR8>, 194 MortonCopy<false, PixelFormat::ABGR8>,
199 MortonCopy<false, PixelFormat::Z24S8>, 195 MortonCopy<false, PixelFormat::Z24S8>,
196 MortonCopy<false, PixelFormat::S8Z24>,
200}; 197};
201 198
202// Allocate an uninitialized texture of appropriate size and format for the surface 199// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -234,6 +231,71 @@ CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) {
234 rect.GetWidth(), rect.GetHeight()); 231 rect.GetWidth(), rect.GetHeight());
235} 232}
236 233
234static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
235 union S8Z24 {
236 BitField<0, 24, u32> z24;
237 BitField<24, 8, u32> s8;
238 };
239 static_assert(sizeof(S8Z24) == 4, "S8Z24 is incorrect size");
240
241 union Z24S8 {
242 BitField<0, 8, u32> s8;
243 BitField<8, 24, u32> z24;
244 };
245 static_assert(sizeof(Z24S8) == 4, "Z24S8 is incorrect size");
246
247 S8Z24 input_pixel{};
248 Z24S8 output_pixel{};
249 for (size_t y = 0; y < height; ++y) {
250 for (size_t x = 0; x < width; ++x) {
251 const size_t offset{y * width + x};
252 std::memcpy(&input_pixel, &data[offset], sizeof(S8Z24));
253 output_pixel.s8.Assign(input_pixel.s8);
254 output_pixel.z24.Assign(input_pixel.z24);
255 std::memcpy(&data[offset], &output_pixel, sizeof(Z24S8));
256 }
257 }
258}
259/**
260 * Helper function to perform software conversion (as needed) when loading a buffer from Switch
261 * memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with
262 * typical desktop GPUs.
263 */
264static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format,
265 u32 width, u32 height) {
266 switch (pixel_format) {
267 case PixelFormat::ASTC_2D_4X4: {
268 // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
269 u32 block_width{};
270 u32 block_height{};
271 std::tie(block_width, block_height) = GetASTCBlockSize(pixel_format);
272 data = Tegra::Texture::ASTC::Decompress(data, width, height, block_width, block_height);
273 break;
274 }
275 case PixelFormat::S8Z24:
276 // Convert the S8Z24 depth format to Z24S8, as OpenGL does not support S8Z24.
277 ConvertS8Z24ToZ24S8(data, width, height);
278 break;
279 }
280}
281
282/**
283 * Helper function to perform software conversion (as needed) when flushing a buffer to Switch
284 * memory. This is for Maxwell pixel formats that cannot be represented as-is in OpenGL or with
285 * typical desktop GPUs.
286 */
287static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& /*data*/, PixelFormat pixel_format,
288 u32 /*width*/, u32 /*height*/) {
289 switch (pixel_format) {
290 case PixelFormat::ASTC_2D_4X4:
291 case PixelFormat::S8Z24:
292 LOG_CRITICAL(Render_OpenGL, "Unimplemented pixel_format={}",
293 static_cast<u32>(pixel_format));
294 UNREACHABLE();
295 break;
296 }
297}
298
237MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); 299MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
238void CachedSurface::LoadGLBuffer() { 300void CachedSurface::LoadGLBuffer() {
239 ASSERT(params.type != SurfaceType::Fill); 301 ASSERT(params.type != SurfaceType::Fill);
@@ -256,10 +318,7 @@ void CachedSurface::LoadGLBuffer() {
256 params.width, params.block_height, params.height, gl_buffer.data(), params.addr); 318 params.width, params.block_height, params.height, gl_buffer.data(), params.addr);
257 } 319 }
258 320
259 if (IsPixelFormatASTC(params.pixel_format)) { 321 ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer, params.pixel_format, params.width, params.height);
260 // ASTC formats are converted to RGBA8 in software, as most PC GPUs do not support this
261 ConvertASTCToRGBA8(gl_buffer, params.pixel_format, params.width, params.height);
262 }
263} 322}
264 323
265MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); 324MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
@@ -272,6 +331,9 @@ void CachedSurface::FlushGLBuffer() {
272 331
273 MICROPROFILE_SCOPE(OpenGL_SurfaceFlush); 332 MICROPROFILE_SCOPE(OpenGL_SurfaceFlush);
274 333
334 ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer, params.pixel_format, params.width,
335 params.height);
336
275 if (!params.is_tiled) { 337 if (!params.is_tiled) {
276 std::memcpy(dst_buffer, gl_buffer.data(), params.size_in_bytes); 338 std::memcpy(dst_buffer, gl_buffer.data(), params.size_in_bytes);
277 } else { 339 } else {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 459abbdc2..7aaf371bd 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -41,6 +41,7 @@ struct SurfaceParams {
41 41
42 // DepthStencil formats 42 // DepthStencil formats
43 Z24S8 = 13, 43 Z24S8 = 13,
44 S8Z24 = 14,
44 45
45 MaxDepthStencilFormat, 46 MaxDepthStencilFormat,
46 47
@@ -92,6 +93,7 @@ struct SurfaceParams {
92 4, // DXN1 93 4, // DXN1
93 4, // ASTC_2D_4X4 94 4, // ASTC_2D_4X4
94 1, // Z24S8 95 1, // Z24S8
96 1, // S8Z24
95 }}; 97 }};
96 98
97 ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); 99 ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
@@ -117,6 +119,7 @@ struct SurfaceParams {
117 64, // DXN1 119 64, // DXN1
118 32, // ASTC_2D_4X4 120 32, // ASTC_2D_4X4
119 32, // Z24S8 121 32, // Z24S8
122 32, // S8Z24
120 }}; 123 }};
121 124
122 ASSERT(static_cast<size_t>(format) < bpp_table.size()); 125 ASSERT(static_cast<size_t>(format) < bpp_table.size());
@@ -128,6 +131,8 @@ struct SurfaceParams {
128 131
129 static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { 132 static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
130 switch (format) { 133 switch (format) {
134 case Tegra::DepthFormat::S8_Z24_UNORM:
135 return PixelFormat::S8Z24;
131 case Tegra::DepthFormat::Z24_S8_UNORM: 136 case Tegra::DepthFormat::Z24_S8_UNORM:
132 return PixelFormat::Z24S8; 137 return PixelFormat::Z24S8;
133 default: 138 default:
@@ -226,6 +231,8 @@ struct SurfaceParams {
226 231
227 static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) { 232 static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) {
228 switch (format) { 233 switch (format) {
234 case PixelFormat::S8Z24:
235 return Tegra::DepthFormat::S8_Z24_UNORM;
229 case PixelFormat::Z24S8: 236 case PixelFormat::Z24S8:
230 return Tegra::DepthFormat::Z24_S8_UNORM; 237 return Tegra::DepthFormat::Z24_S8_UNORM;
231 default: 238 default:
@@ -274,6 +281,7 @@ struct SurfaceParams {
274 281
275 static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) { 282 static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) {
276 switch (format) { 283 switch (format) {
284 case Tegra::DepthFormat::S8_Z24_UNORM:
277 case Tegra::DepthFormat::Z24_S8_UNORM: 285 case Tegra::DepthFormat::Z24_S8_UNORM:
278 return ComponentType::UNorm; 286 return ComponentType::UNorm;
279 default: 287 default:
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 680f22ddb..7b06fea3e 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -76,6 +76,7 @@ u32 BytesPerPixel(TextureFormat format) {
76 76
77static u32 DepthBytesPerPixel(DepthFormat format) { 77static u32 DepthBytesPerPixel(DepthFormat format) {
78 switch (format) { 78 switch (format) {
79 case DepthFormat::S8_Z24_UNORM:
79 case DepthFormat::Z24_S8_UNORM: 80 case DepthFormat::Z24_S8_UNORM:
80 return 4; 81 return 4;
81 default: 82 default:
@@ -129,6 +130,7 @@ std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 wid
129 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); 130 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
130 131
131 switch (format) { 132 switch (format) {
133 case DepthFormat::S8_Z24_UNORM:
132 case DepthFormat::Z24_S8_UNORM: 134 case DepthFormat::Z24_S8_UNORM:
133 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 135 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
134 unswizzled_data.data(), true, block_height); 136 unswizzled_data.data(), true, block_height);