diff options
| author | 2018-09-06 19:08:45 -0400 | |
|---|---|---|
| committer | 2018-09-08 02:53:38 -0400 | |
| commit | f165a85398f48504541a7ab9aedee1b517dfd863 (patch) | |
| tree | 4020493e25fce1ea73b9702c72894336f825c649 /src | |
| parent | gl_shader_decompiler: Partially implement several non-2D texture types (Subv). (diff) | |
| download | yuzu-f165a85398f48504541a7ab9aedee1b517dfd863.tar.gz yuzu-f165a85398f48504541a7ab9aedee1b517dfd863.tar.xz yuzu-f165a85398f48504541a7ab9aedee1b517dfd863.zip | |
gl_rasterizer_cache: Partially implement several non-2D texture types.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 141 |
1 files changed, 111 insertions, 30 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 1a44de332..e9fd67d00 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -245,7 +245,8 @@ static bool IsFormatBCn(PixelFormat format) { | |||
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | template <bool morton_to_gl, PixelFormat format> | 247 | template <bool morton_to_gl, PixelFormat format> |
| 248 | void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_buffer, VAddr addr) { | 248 | void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, size_t gl_buffer_size, |
| 249 | VAddr addr) { | ||
| 249 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT; | 250 | constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT; |
| 250 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); | 251 | constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); |
| 251 | 252 | ||
| @@ -255,18 +256,18 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, std::vector<u8>& gl_bu | |||
| 255 | const u32 tile_size{IsFormatBCn(format) ? 4U : 1U}; | 256 | const u32 tile_size{IsFormatBCn(format) ? 4U : 1U}; |
| 256 | const std::vector<u8> data = Tegra::Texture::UnswizzleTexture( | 257 | const std::vector<u8> data = Tegra::Texture::UnswizzleTexture( |
| 257 | addr, tile_size, bytes_per_pixel, stride, height, block_height); | 258 | addr, tile_size, bytes_per_pixel, stride, height, block_height); |
| 258 | const size_t size_to_copy{std::min(gl_buffer.size(), data.size())}; | 259 | const size_t size_to_copy{std::min(gl_buffer_size, data.size())}; |
| 259 | gl_buffer.assign(data.begin(), data.begin() + size_to_copy); | 260 | memcpy(gl_buffer, data.data(), size_to_copy); |
| 260 | } else { | 261 | } else { |
| 261 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should | 262 | // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should |
| 262 | // check the configuration for this and perform more generic un/swizzle | 263 | // check the configuration for this and perform more generic un/swizzle |
| 263 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); | 264 | LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); |
| 264 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, | 265 | VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, |
| 265 | Memory::GetPointer(addr), gl_buffer.data(), morton_to_gl); | 266 | Memory::GetPointer(addr), gl_buffer, morton_to_gl); |
| 266 | } | 267 | } |
| 267 | } | 268 | } |
| 268 | 269 | ||
| 269 | static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr), | 270 | static constexpr std::array<void (*)(u32, u32, u32, u8*, size_t, VAddr), |
| 270 | SurfaceParams::MaxPixelFormat> | 271 | SurfaceParams::MaxPixelFormat> |
| 271 | morton_to_gl_fns = { | 272 | morton_to_gl_fns = { |
| 272 | // clang-format off | 273 | // clang-format off |
| @@ -323,7 +324,7 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr), | |||
| 323 | // clang-format on | 324 | // clang-format on |
| 324 | }; | 325 | }; |
| 325 | 326 | ||
| 326 | static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, VAddr), | 327 | static constexpr std::array<void (*)(u32, u32, u32, u8*, size_t, VAddr), |
| 327 | SurfaceParams::MaxPixelFormat> | 328 | SurfaceParams::MaxPixelFormat> |
| 328 | gl_to_morton_fns = { | 329 | gl_to_morton_fns = { |
| 329 | // clang-format off | 330 | // clang-format off |
| @@ -441,29 +442,51 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | |||
| 441 | texture.Create(); | 442 | texture.Create(); |
| 442 | const auto& rect{params.GetRect()}; | 443 | const auto& rect{params.GetRect()}; |
| 443 | 444 | ||
| 445 | // Keep track of previous texture bindings | ||
| 444 | OpenGLState cur_state = OpenGLState::GetCurState(); | 446 | OpenGLState cur_state = OpenGLState::GetCurState(); |
| 447 | const auto& old_tex = cur_state.texture_units[0]; | ||
| 448 | SCOPE_EXIT({ | ||
| 449 | cur_state.texture_units[0] = old_tex; | ||
| 450 | cur_state.Apply(); | ||
| 451 | }); | ||
| 445 | 452 | ||
| 446 | // Keep track of previous texture bindings | ||
| 447 | GLuint old_tex = cur_state.texture_units[0].texture; | ||
| 448 | cur_state.texture_units[0].texture = texture.handle; | 453 | cur_state.texture_units[0].texture = texture.handle; |
| 454 | cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); | ||
| 449 | cur_state.Apply(); | 455 | cur_state.Apply(); |
| 450 | glActiveTexture(GL_TEXTURE0); | 456 | glActiveTexture(GL_TEXTURE0); |
| 451 | 457 | ||
| 452 | const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); | 458 | const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); |
| 453 | if (!format_tuple.compressed) { | 459 | if (!format_tuple.compressed) { |
| 454 | // Only pre-create the texture for non-compressed textures. | 460 | // Only pre-create the texture for non-compressed textures. |
| 455 | glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(), | 461 | switch (params.target) { |
| 456 | rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr); | 462 | case SurfaceParams::SurfaceTarget::Texture1D: |
| 463 | glTexImage1D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, | ||
| 464 | rect.GetWidth(), 0, format_tuple.format, format_tuple.type, nullptr); | ||
| 465 | break; | ||
| 466 | case SurfaceParams::SurfaceTarget::Texture2D: | ||
| 467 | glTexImage2D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, | ||
| 468 | rect.GetWidth(), rect.GetHeight(), 0, format_tuple.format, | ||
| 469 | format_tuple.type, nullptr); | ||
| 470 | break; | ||
| 471 | case SurfaceParams::SurfaceTarget::Texture3D: | ||
| 472 | case SurfaceParams::SurfaceTarget::Texture2DArray: | ||
| 473 | glTexImage3D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, | ||
| 474 | rect.GetWidth(), rect.GetHeight(), params.depth, 0, format_tuple.format, | ||
| 475 | format_tuple.type, nullptr); | ||
| 476 | break; | ||
| 477 | default: | ||
| 478 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | ||
| 479 | static_cast<u32>(params.target)); | ||
| 480 | UNREACHABLE(); | ||
| 481 | glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(), | ||
| 482 | rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr); | ||
| 483 | } | ||
| 457 | } | 484 | } |
| 458 | 485 | ||
| 459 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0); | 486 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0); |
| 460 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 487 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 461 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 488 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 462 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 489 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 463 | |||
| 464 | // Restore previous texture bindings | ||
| 465 | cur_state.texture_units[0].texture = old_tex; | ||
| 466 | cur_state.Apply(); | ||
| 467 | } | 490 | } |
| 468 | 491 | ||
| 469 | static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { | 492 | static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) { |
| @@ -548,13 +571,24 @@ void CachedSurface::LoadGLBuffer() { | |||
| 548 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); | 571 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); |
| 549 | 572 | ||
| 550 | if (params.is_tiled) { | 573 | if (params.is_tiled) { |
| 551 | gl_buffer.resize(copy_size); | 574 | // TODO(bunnei): This only unswizzles and copies a 2D texture - we do not yet know how to do |
| 575 | // this for 3D textures, etc. | ||
| 576 | switch (params.target) { | ||
| 577 | case SurfaceParams::SurfaceTarget::Texture2D: | ||
| 578 | // Pass impl. to the fallback code below | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | LOG_CRITICAL(HW_GPU, "Unimplemented tiled load for target={}", | ||
| 582 | static_cast<u32>(params.target)); | ||
| 583 | UNREACHABLE(); | ||
| 584 | } | ||
| 552 | 585 | ||
| 586 | gl_buffer.resize(params.depth * copy_size); | ||
| 553 | morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( | 587 | morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( |
| 554 | params.width, params.block_height, params.height, gl_buffer, params.addr); | 588 | params.width, params.block_height, params.height, gl_buffer.data(), copy_size, |
| 589 | params.addr); | ||
| 555 | } else { | 590 | } else { |
| 556 | const u8* const texture_src_data_end = texture_src_data + copy_size; | 591 | const u8* const texture_src_data_end{texture_src_data + (params.depth * copy_size)}; |
| 557 | |||
| 558 | gl_buffer.assign(texture_src_data, texture_src_data_end); | 592 | gl_buffer.assign(texture_src_data, texture_src_data_end); |
| 559 | } | 593 | } |
| 560 | 594 | ||
| @@ -574,7 +608,7 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle | |||
| 574 | MICROPROFILE_SCOPE(OpenGL_TextureUL); | 608 | MICROPROFILE_SCOPE(OpenGL_TextureUL); |
| 575 | 609 | ||
| 576 | ASSERT(gl_buffer.size() == | 610 | ASSERT(gl_buffer.size() == |
| 577 | params.width * params.height * GetGLBytesPerPixel(params.pixel_format)); | 611 | params.width * params.height * GetGLBytesPerPixel(params.pixel_format) * params.depth); |
| 578 | 612 | ||
| 579 | const auto& rect{params.GetRect()}; | 613 | const auto& rect{params.GetRect()}; |
| 580 | 614 | ||
| @@ -587,8 +621,13 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle | |||
| 587 | GLuint target_tex = texture.handle; | 621 | GLuint target_tex = texture.handle; |
| 588 | OpenGLState cur_state = OpenGLState::GetCurState(); | 622 | OpenGLState cur_state = OpenGLState::GetCurState(); |
| 589 | 623 | ||
| 590 | GLuint old_tex = cur_state.texture_units[0].texture; | 624 | const auto& old_tex = cur_state.texture_units[0]; |
| 625 | SCOPE_EXIT({ | ||
| 626 | cur_state.texture_units[0] = old_tex; | ||
| 627 | cur_state.Apply(); | ||
| 628 | }); | ||
| 591 | cur_state.texture_units[0].texture = target_tex; | 629 | cur_state.texture_units[0].texture = target_tex; |
| 630 | cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); | ||
| 592 | cur_state.Apply(); | 631 | cur_state.Apply(); |
| 593 | 632 | ||
| 594 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT | 633 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT |
| @@ -597,20 +636,62 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle | |||
| 597 | 636 | ||
| 598 | glActiveTexture(GL_TEXTURE0); | 637 | glActiveTexture(GL_TEXTURE0); |
| 599 | if (tuple.compressed) { | 638 | if (tuple.compressed) { |
| 600 | glCompressedTexImage2D( | 639 | switch (params.target) { |
| 601 | GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width), | 640 | case SurfaceParams::SurfaceTarget::Texture2D: |
| 602 | static_cast<GLsizei>(params.height), 0, static_cast<GLsizei>(params.size_in_bytes), | 641 | glCompressedTexImage2D( |
| 603 | &gl_buffer[buffer_offset]); | 642 | SurfaceTargetToGL(params.target), 0, tuple.internal_format, |
| 643 | static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0, | ||
| 644 | static_cast<GLsizei>(params.size_in_bytes), &gl_buffer[buffer_offset]); | ||
| 645 | break; | ||
| 646 | case SurfaceParams::SurfaceTarget::Texture3D: | ||
| 647 | case SurfaceParams::SurfaceTarget::Texture2DArray: | ||
| 648 | glCompressedTexImage3D( | ||
| 649 | SurfaceTargetToGL(params.target), 0, tuple.internal_format, | ||
| 650 | static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), | ||
| 651 | static_cast<GLsizei>(params.depth), 0, static_cast<GLsizei>(params.size_in_bytes), | ||
| 652 | &gl_buffer[buffer_offset]); | ||
| 653 | break; | ||
| 654 | default: | ||
| 655 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | ||
| 656 | static_cast<u32>(params.target)); | ||
| 657 | UNREACHABLE(); | ||
| 658 | glCompressedTexImage2D( | ||
| 659 | GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width), | ||
| 660 | static_cast<GLsizei>(params.height), 0, static_cast<GLsizei>(params.size_in_bytes), | ||
| 661 | &gl_buffer[buffer_offset]); | ||
| 662 | } | ||
| 604 | } else { | 663 | } else { |
| 605 | glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()), | 664 | |
| 606 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | 665 | switch (params.target) { |
| 607 | &gl_buffer[buffer_offset]); | 666 | case SurfaceParams::SurfaceTarget::Texture1D: |
| 667 | glTexSubImage1D(SurfaceTargetToGL(params.target), 0, x0, | ||
| 668 | static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, | ||
| 669 | &gl_buffer[buffer_offset]); | ||
| 670 | break; | ||
| 671 | case SurfaceParams::SurfaceTarget::Texture2D: | ||
| 672 | glTexSubImage2D(SurfaceTargetToGL(params.target), 0, x0, y0, | ||
| 673 | static_cast<GLsizei>(rect.GetWidth()), | ||
| 674 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | ||
| 675 | &gl_buffer[buffer_offset]); | ||
| 676 | break; | ||
| 677 | case SurfaceParams::SurfaceTarget::Texture3D: | ||
| 678 | case SurfaceParams::SurfaceTarget::Texture2DArray: | ||
| 679 | glTexSubImage3D(SurfaceTargetToGL(params.target), 0, x0, y0, 0, | ||
| 680 | static_cast<GLsizei>(rect.GetWidth()), | ||
| 681 | static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, | ||
| 682 | tuple.type, &gl_buffer[buffer_offset]); | ||
| 683 | break; | ||
| 684 | default: | ||
| 685 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | ||
| 686 | static_cast<u32>(params.target)); | ||
| 687 | UNREACHABLE(); | ||
| 688 | glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()), | ||
| 689 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | ||
| 690 | &gl_buffer[buffer_offset]); | ||
| 691 | } | ||
| 608 | } | 692 | } |
| 609 | 693 | ||
| 610 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 694 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 611 | |||
| 612 | cur_state.texture_units[0].texture = old_tex; | ||
| 613 | cur_state.Apply(); | ||
| 614 | } | 695 | } |
| 615 | 696 | ||
| 616 | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | 697 | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { |