diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 27 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 49 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 47 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 50 |
5 files changed, 148 insertions, 28 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 324c28d1b..ca3814cfc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -304,10 +304,15 @@ void RasterizerOpenGL::DrawArrays() { MICROPROFILE_SCOPE(OpenGL_Drawing); const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; - // TODO(bunnei): Implement these + // Sync the depth test state before configuring the framebuffer surfaces. + SyncDepthTestState(); + + // TODO(bunnei): Implement this const bool has_stencil = false; + const bool using_color_fb = true; - const bool using_depth_fb = false; + const bool using_depth_fb = regs.zeta.Address() != 0; + const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; const bool write_color_fb = @@ -338,11 +343,9 @@ void RasterizerOpenGL::DrawArrays() { // Bind the framebuffer surfaces BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); - // Sync the viewport SyncViewport(surfaces_rect); - - // Sync the blend state registers SyncBlendState(); + SyncCullMode(); // TODO(bunnei): Sync framebuffer_scale uniform here // TODO(bunnei): Sync scissorbox uniform(s) here @@ -712,7 +715,11 @@ void RasterizerOpenGL::SyncClipCoef() { } void RasterizerOpenGL::SyncCullMode() { - UNREACHABLE(); + const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; + + state.cull.enabled = regs.cull.enabled != 0; + state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); + state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); } void RasterizerOpenGL::SyncDepthScale() { @@ -723,6 +730,14 @@ void RasterizerOpenGL::SyncDepthOffset() { UNREACHABLE(); } +void RasterizerOpenGL::SyncDepthTestState() { + const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; + + state.depth.test_enabled = regs.depth_test_enable != 0; + state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE; + state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func); +} + void RasterizerOpenGL::SyncBlendState() { const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 621200f03..493aa39e5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -126,6 +126,9 @@ private: /// Syncs the depth offset to match the guest state void SyncDepthOffset(); + /// Syncs the depth test state to match the guest state + void SyncDepthTestState(); + /// Syncs the blend state to match the guest state void SyncBlendState(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 9410ddb4e..851ebc263 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -84,22 +84,18 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form true}, // DXT45 {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, true}, // DXN1 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4 + + // DepthStencil formats + {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, ComponentType::UNorm, + false}, // Z24S8 }}; static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { - const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); - if (type == SurfaceType::ColorTexture) { - ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); - auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)]; - ASSERT(component_type == format.component_type); - return format; - } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { - // TODO(Subv): Implement depth formats - ASSERT_MSG(false, "Unimplemented"); - } + ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); + auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)]; + ASSERT(component_type == format.component_type); - UNREACHABLE(); - return {}; + return format; } VAddr SurfaceParams::GetCpuAddr() const { @@ -149,11 +145,17 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra:: const auto& gpu = Core::System::GetInstance().GPU(); if (morton_to_gl) { - auto data = Tegra::Texture::UnswizzleTexture( - *gpu.memory_manager->GpuToCpuAddress(addr), - SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height); - - std::memcpy(gl_buffer, data.data(), data.size()); + if (SurfaceParams::GetFormatType(format) == SurfaceType::ColorTexture) { + auto data = Tegra::Texture::UnswizzleTexture( + *gpu.memory_manager->GpuToCpuAddress(addr), + SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height); + std::memcpy(gl_buffer, data.data(), data.size()); + } else { + auto data = Tegra::Texture::UnswizzleDepthTexture( + *gpu.memory_manager->GpuToCpuAddress(addr), + SurfaceParams::DepthFormatFromPixelFormat(format), stride, height, block_height); + std::memcpy(gl_buffer, data.data(), data.size()); + } } else { // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should // check the configuration for this and perform more generic un/swizzle @@ -174,7 +176,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), MortonCopy<true, PixelFormat::R11FG11FB10F>, MortonCopy<true, PixelFormat::RGBA32UI>, MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, - MortonCopy<true, PixelFormat::ASTC_2D_4X4>, + MortonCopy<true, PixelFormat::ASTC_2D_4X4>, MortonCopy<true, PixelFormat::Z24S8>, }; static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), @@ -194,6 +196,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr), nullptr, nullptr, MortonCopy<false, PixelFormat::ABGR8>, + MortonCopy<false, PixelFormat::Z24S8>, }; // Allocate an uninitialized texture of appropriate size and format for the surface @@ -397,9 +400,15 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( // get color and depth surfaces const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])}; - const SurfaceParams depth_params{color_params}; + SurfaceParams depth_params{color_params}; - ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); + if (using_depth_fb) { + depth_params.addr = regs.zeta.Address(); + depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(regs.zeta.format); + depth_params.component_type = SurfaceParams::ComponentTypeFromDepthFormat(regs.zeta.format); + depth_params.type = SurfaceParams::GetFormatType(depth_params.pixel_format); + depth_params.size_in_bytes = depth_params.SizeInBytes(); + } MathUtil::Rectangle<u32> color_rect{}; Surface color_surface; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 99be250b4..eea432b0b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -37,7 +37,14 @@ struct SurfaceParams { DXN1 = 11, // This is also known as BC4 ASTC_2D_4X4 = 12, - Max, + MaxColorFormat, + + // DepthStencil formats + Z24S8 = 13, + + MaxDepthStencilFormat, + + Max = MaxDepthStencilFormat, Invalid = 255, }; @@ -84,6 +91,7 @@ struct SurfaceParams { 4, // DXT45 4, // DXN1 4, // ASTC_2D_4X4 + 1, // Z24S8 }}; ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); @@ -108,6 +116,7 @@ struct SurfaceParams { 128, // DXT45 64, // DXN1 32, // ASTC_2D_4X4 + 32, // Z24S8 }}; ASSERT(static_cast<size_t>(format) < bpp_table.size()); @@ -117,6 +126,16 @@ struct SurfaceParams { return GetFormatBpp(pixel_format); } + static PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { + switch (format) { + case Tegra::DepthFormat::Z24_S8_UNORM: + return PixelFormat::Z24S8; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); + UNREACHABLE(); + } + } + static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { switch (format) { case Tegra::RenderTargetFormat::RGBA8_UNORM: @@ -205,6 +224,15 @@ struct SurfaceParams { } } + static Tegra::DepthFormat DepthFormatFromPixelFormat(PixelFormat format) { + switch (format) { + case PixelFormat::Z24S8: + return Tegra::DepthFormat::Z24_S8_UNORM; + default: + UNREACHABLE(); + } + } + static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { // TODO(Subv): Implement more component types switch (type) { @@ -244,11 +272,26 @@ struct SurfaceParams { } } + static ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) { + switch (format) { + case Tegra::DepthFormat::Z24_S8_UNORM: + return ComponentType::UNorm; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); + UNREACHABLE(); + } + } + static SurfaceType GetFormatType(PixelFormat pixel_format) { - if (static_cast<size_t>(pixel_format) < MaxPixelFormat) { + if (static_cast<size_t>(pixel_format) < static_cast<size_t>(PixelFormat::MaxColorFormat)) { return SurfaceType::ColorTexture; } + if (static_cast<size_t>(pixel_format) < + static_cast<size_t>(PixelFormat::MaxDepthStencilFormat)) { + return SurfaceType::DepthStencil; + } + // TODO(Subv): Implement the other formats ASSERT(false); diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 2155fb019..392041a1c 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -201,4 +201,54 @@ inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { return {}; } +inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) { + switch (comparison) { + case Maxwell::ComparisonOp::Never: + return GL_NEVER; + case Maxwell::ComparisonOp::Less: + return GL_LESS; + case Maxwell::ComparisonOp::Equal: + return GL_EQUAL; + case Maxwell::ComparisonOp::LessEqual: + return GL_LEQUAL; + case Maxwell::ComparisonOp::Greater: + return GL_GREATER; + case Maxwell::ComparisonOp::NotEqual: + return GL_NOTEQUAL; + case Maxwell::ComparisonOp::GreaterEqual: + return GL_GEQUAL; + case Maxwell::ComparisonOp::Always: + return GL_ALWAYS; + } + NGLOG_CRITICAL(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison)); + UNREACHABLE(); + return {}; +} + +inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) { + switch (front_face) { + case Maxwell::Cull::FrontFace::ClockWise: + return GL_CW; + case Maxwell::Cull::FrontFace::CounterClockWise: + return GL_CCW; + } + NGLOG_CRITICAL(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face)); + UNREACHABLE(); + return {}; +} + +inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) { + switch (cull_face) { + case Maxwell::Cull::CullFace::Front: + return GL_FRONT; + case Maxwell::Cull::CullFace::Back: + return GL_BACK; + case Maxwell::Cull::CullFace::FrontAndBack: + return GL_FRONT_AND_BACK; + } + NGLOG_CRITICAL(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face)); + UNREACHABLE(); + return {}; +} + } // namespace MaxwellToGL |