diff options
Diffstat (limited to '')
19 files changed, 378 insertions, 302 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d1cbe0e44..3f009d2b7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -322,14 +322,15 @@ void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& c void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + // TODO(Subv): Find out how AM determines the display to use, for now just // create the layer in the Default display. - u64 display_id = nvflinger->OpenDisplay("Default"); - u64 layer_id = nvflinger->CreateLayer(display_id); + const auto display_id = nvflinger->OpenDisplay("Default"); + const auto layer_id = nvflinger->CreateLayer(*display_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(layer_id); + rb.Push(*layer_id); } void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 8dfc0df03..cde06916d 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -46,7 +46,7 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { nvdrv = std::move(instance); } -u64 NVFlinger::OpenDisplay(std::string_view name) { +std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { LOG_DEBUG(Service, "Opening \"{}\" display", name); // TODO(Subv): Currently we only support the Default display. @@ -54,32 +54,48 @@ u64 NVFlinger::OpenDisplay(std::string_view name) { const auto itr = std::find_if(displays.begin(), displays.end(), [&](const Display& display) { return display.name == name; }); - - ASSERT(itr != displays.end()); + if (itr == displays.end()) { + return {}; + } return itr->id; } -u64 NVFlinger::CreateLayer(u64 display_id) { - auto& display = FindDisplay(display_id); +std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { + auto* const display = FindDisplay(display_id); + + if (display == nullptr) { + return {}; + } - ASSERT_MSG(display.layers.empty(), "Only one layer is supported per display at the moment"); + ASSERT_MSG(display->layers.empty(), "Only one layer is supported per display at the moment"); const u64 layer_id = next_layer_id++; const u32 buffer_queue_id = next_buffer_queue_id++; auto buffer_queue = std::make_shared<BufferQueue>(buffer_queue_id, layer_id); - display.layers.emplace_back(layer_id, buffer_queue); + display->layers.emplace_back(layer_id, buffer_queue); buffer_queues.emplace_back(std::move(buffer_queue)); return layer_id; } -u32 NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { - const auto& layer = FindLayer(display_id, layer_id); - return layer.buffer_queue->GetId(); +std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { + const auto* const layer = FindLayer(display_id, layer_id); + + if (layer == nullptr) { + return {}; + } + + return layer->buffer_queue->GetId(); } -Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) { - return FindDisplay(display_id).vsync_event.readable; +Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const { + auto* const display = FindDisplay(display_id); + + if (display == nullptr) { + return nullptr; + } + + return display->vsync_event.readable; } std::shared_ptr<BufferQueue> NVFlinger::FindBufferQueue(u32 id) const { @@ -90,40 +106,60 @@ std::shared_ptr<BufferQueue> NVFlinger::FindBufferQueue(u32 id) const { return *itr; } -Display& NVFlinger::FindDisplay(u64 display_id) { +Display* NVFlinger::FindDisplay(u64 display_id) { const auto itr = std::find_if(displays.begin(), displays.end(), [&](const Display& display) { return display.id == display_id; }); - ASSERT(itr != displays.end()); - return *itr; + if (itr == displays.end()) { + return nullptr; + } + + return &*itr; } -const Display& NVFlinger::FindDisplay(u64 display_id) const { +const Display* NVFlinger::FindDisplay(u64 display_id) const { const auto itr = std::find_if(displays.begin(), displays.end(), [&](const Display& display) { return display.id == display_id; }); - ASSERT(itr != displays.end()); - return *itr; + if (itr == displays.end()) { + return nullptr; + } + + return &*itr; } -Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) { - auto& display = FindDisplay(display_id); +Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) { + auto* const display = FindDisplay(display_id); - const auto itr = std::find_if(display.layers.begin(), display.layers.end(), + if (display == nullptr) { + return nullptr; + } + + const auto itr = std::find_if(display->layers.begin(), display->layers.end(), [&](const Layer& layer) { return layer.id == layer_id; }); - ASSERT(itr != display.layers.end()); - return *itr; + if (itr == display->layers.end()) { + return nullptr; + } + + return &*itr; } -const Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { - const auto& display = FindDisplay(display_id); +const Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { + const auto* const display = FindDisplay(display_id); + + if (display == nullptr) { + return nullptr; + } - const auto itr = std::find_if(display.layers.begin(), display.layers.end(), + const auto itr = std::find_if(display->layers.begin(), display->layers.end(), [&](const Layer& layer) { return layer.id == layer_id; }); - ASSERT(itr != display.layers.end()); - return *itr; + if (itr == display->layers.end()) { + return nullptr; + } + + return &*itr; } void NVFlinger::Compose() { diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 83e974ed3..4c55e99f4 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -6,6 +6,7 @@ #include <array> #include <memory> +#include <optional> #include <string> #include <string_view> #include <vector> @@ -58,16 +59,24 @@ public: void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); /// Opens the specified display and returns the ID. - u64 OpenDisplay(std::string_view name); + /// + /// If an invalid display name is provided, then an empty optional is returned. + std::optional<u64> OpenDisplay(std::string_view name); /// Creates a layer on the specified display and returns the layer ID. - u64 CreateLayer(u64 display_id); + /// + /// If an invalid display ID is specified, then an empty optional is returned. + std::optional<u64> CreateLayer(u64 display_id); /// Finds the buffer queue ID of the specified layer in the specified display. - u32 FindBufferQueueId(u64 display_id, u64 layer_id) const; + /// + /// If an invalid display ID or layer ID is provided, then an empty optional is returned. + std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const; /// Gets the vsync event for the specified display. - Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id); + /// + /// If an invalid display ID is provided, then nullptr is returned. + Kernel::SharedPtr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const; /// Obtains a buffer queue identified by the ID. std::shared_ptr<BufferQueue> FindBufferQueue(u32 id) const; @@ -78,16 +87,16 @@ public: private: /// Finds the display identified by the specified ID. - Display& FindDisplay(u64 display_id); + Display* FindDisplay(u64 display_id); /// Finds the display identified by the specified ID. - const Display& FindDisplay(u64 display_id) const; + const Display* FindDisplay(u64 display_id) const; /// Finds the layer identified by the specified ID in the desired display. - Layer& FindLayer(u64 display_id, u64 layer_id); + Layer* FindLayer(u64 display_id, u64 layer_id); /// Finds the layer identified by the specified ID in the desired display. - const Layer& FindLayer(u64 display_id, u64 layer_id) const; + const Layer* FindLayer(u64 display_id, u64 layer_id) const; std::shared_ptr<Nvidia::Module> nvdrv; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index fe08c38f2..a317a2885 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -34,6 +34,7 @@ namespace Service::VI { constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::VI, 1}; constexpr ResultCode ERR_UNSUPPORTED{ErrorModule::VI, 6}; +constexpr ResultCode ERR_NOT_FOUND{ErrorModule::VI, 7}; struct DisplayInfo { /// The name of this particular display. @@ -838,11 +839,16 @@ private: "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", unknown, display, aruid); - const u64 layer_id = nv_flinger->CreateLayer(display); + const auto layer_id = nv_flinger->CreateLayer(display); + if (!layer_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(layer_id); + rb.Push(*layer_id); } void AddToLayerStack(Kernel::HLERequestContext& ctx) { @@ -950,9 +956,16 @@ private: ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); + const auto display_id = nv_flinger->OpenDisplay(name); + if (!display_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>(nv_flinger->OpenDisplay(name)); + rb.Push<u64>(*display_id); } void CloseDisplay(Kernel::HLERequestContext& ctx) { @@ -1043,10 +1056,21 @@ private: LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); - const u64 display_id = nv_flinger->OpenDisplay(display_name); - const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id); + const auto display_id = nv_flinger->OpenDisplay(display_name); + if (!display_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } + + const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id); + if (!buffer_queue_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } - NativeWindow native_window{buffer_queue_id}; + NativeWindow native_window{*buffer_queue_id}; IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); @@ -1062,13 +1086,24 @@ private: // TODO(Subv): What's the difference between a Stray and a Managed layer? - const u64 layer_id = nv_flinger->CreateLayer(display_id); - const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id); + const auto layer_id = nv_flinger->CreateLayer(display_id); + if (!layer_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } + + const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id); + if (!buffer_queue_id) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } - NativeWindow native_window{buffer_queue_id}; + NativeWindow native_window{*buffer_queue_id}; IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - rb.Push(layer_id); + rb.Push(*layer_id); rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); } @@ -1088,7 +1123,12 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); - const auto vsync_event = nv_flinger->GetVsyncEvent(display_id); + const auto vsync_event = nv_flinger->FindVsyncEvent(display_id); + if (!vsync_event) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NOT_FOUND); + return; + } IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 713b01c9f..269df9437 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -217,9 +217,9 @@ enum class StoreType : u64 { Signed8 = 1, Unsigned16 = 2, Signed16 = 3, - Bytes32 = 4, - Bytes64 = 5, - Bytes128 = 6, + Bits32 = 4, + Bits64 = 5, + Bits128 = 6, }; enum class IMinMaxExchange : u64 { @@ -981,6 +981,10 @@ union Instruction { } return false; } + + bool IsComponentEnabled(std::size_t component) const { + return ((1ULL << component) & component_mask) != 0; + } } txq; union { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 585709fe5..c806b7da7 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1015,11 +1015,8 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s if (surface != nullptr) { unit.texture = entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; - unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); - unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); - unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source); - unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source); - unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source); + surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, + texture.tic.w_source); } else { // Can occur when texture addr is null or its memory is unmapped/invalid unit.texture = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 50286432d..a79eee03e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -18,7 +18,6 @@ #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h" -#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/utils.h" #include "video_core/surface.h" #include "video_core/textures/astc.h" @@ -44,14 +43,14 @@ struct FormatTuple { bool compressed; }; -static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); +static void ApplyTextureDefaults(GLuint texture, u32 max_mip_level) { + glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); if (max_mip_level == 1) { - glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); + glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0); } } @@ -529,55 +528,41 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, CachedSurface::CachedSurface(const SurfaceParams& params) : params(params), gl_target(SurfaceTargetToGL(params.target)), cached_size_in_bytes(params.size_in_bytes) { - texture.Create(); - const auto& rect{params.GetRect()}; - - // Keep track of previous texture bindings - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - - cur_state.texture_units[0].texture = texture.handle; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); - glActiveTexture(GL_TEXTURE0); + texture.Create(gl_target); + + // TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0) + // alternatives. This signals a bug on those functions. + const auto width = static_cast<GLsizei>(params.MipWidth(0)); + const auto height = static_cast<GLsizei>(params.MipHeight(0)); const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); gl_internal_format = format_tuple.internal_format; - gl_is_compressed = format_tuple.compressed; - if (!format_tuple.compressed) { - // Only pre-create the texture for non-compressed textures. - switch (params.target) { - case SurfaceTarget::Texture1D: - glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth()); - break; - case SurfaceTarget::Texture2D: - case SurfaceTarget::TextureCubemap: - glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); - break; - case SurfaceTarget::Texture3D: - case SurfaceTarget::Texture2DArray: - case SurfaceTarget::TextureCubeArray: - glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), - params.depth); - break; - default: - LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", - static_cast<u32>(params.target)); - UNREACHABLE(); - glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format, - rect.GetWidth(), rect.GetHeight()); - } + switch (params.target) { + case SurfaceTarget::Texture1D: + glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width); + break; + case SurfaceTarget::Texture2D: + case SurfaceTarget::TextureCubemap: + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); + break; + case SurfaceTarget::Texture3D: + case SurfaceTarget::Texture2DArray: + case SurfaceTarget::TextureCubeArray: + glTextureStorage3D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height, params.depth); + break; + default: + LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", + static_cast<u32>(params.target)); + UNREACHABLE(); + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); } - ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); + ApplyTextureDefaults(texture.handle, params.max_mip_level); OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); @@ -751,63 +736,50 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, const auto& rect{params.GetRect(mip_map)}; // Load data from memory to the surface - const GLint x0 = static_cast<GLint>(rect.left); - const GLint y0 = static_cast<GLint>(rect.bottom); - std::size_t buffer_offset = + const auto x0 = static_cast<GLint>(rect.left); + const auto y0 = static_cast<GLint>(rect.bottom); + auto buffer_offset = static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + static_cast<std::size_t>(x0)) * GetBytesPerPixel(params.pixel_format); const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); - const GLuint target_tex = texture.handle; - OpenGLState cur_state = OpenGLState::GetCurState(); - - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = target_tex; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map))); - GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); - glActiveTexture(GL_TEXTURE0); + const auto image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); if (tuple.compressed) { switch (params.target) { case SurfaceTarget::Texture2D: - glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), - static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), + static_cast<GLsizei>(params.MipDepth(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), - static_cast<GLsizei>(params.depth), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.depth), + tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { - GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); + const auto layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); for (std::size_t face = 0; face < params.depth; ++face) { - glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), - mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, - layer_size, &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, static_cast<GLint>(face), + static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), 1, tuple.internal_format, + layer_size, &gl_buffer[mip_map][buffer_offset]); buffer_offset += layer_size; } break; @@ -816,46 +788,43 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast<u32>(params.target)); UNREACHABLE(); - glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, - static_cast<GLsizei>(params.MipWidth(mip_map)), - static_cast<GLsizei>(params.MipHeight(mip_map)), 0, - static_cast<GLsizei>(params.size_in_bytes_gl), - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), + static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, + static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[mip_map][buffer_offset]); } } else { - switch (params.target) { case SurfaceTarget::Texture1D: - glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, - static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage1D(texture.handle, mip_map, x0, static_cast<GLsizei>(rect.GetWidth()), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2D: - glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), - tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, - tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { std::size_t start = buffer_offset; for (std::size_t face = 0; face < params.depth; ++face) { - glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, - x0, y0, static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face), + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), 1, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); buffer_offset += params.LayerSizeGL(mip_map); } break; @@ -864,9 +833,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast<u32>(params.target)); UNREACHABLE(); - glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), - static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast<GLsizei>(rect.GetWidth()), + static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); } } @@ -876,29 +846,18 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, void CachedSurface::EnsureTextureView() { if (texture_view.handle != 0) return; - // Compressed texture are not being created with immutable storage - UNIMPLEMENTED_IF(gl_is_compressed); const GLenum target{TargetLayer()}; const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; constexpr GLuint min_layer = 0; constexpr GLuint min_level = 0; - texture_view.Create(); - glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, - params.max_mip_level, min_layer, num_layers); - - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = texture_view.handle; - cur_state.texture_units[0].target = target; - cur_state.Apply(); - - ApplyTextureDefaults(target, params.max_mip_level); + glGenTextures(1, &texture_view.handle); + glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, + params.max_mip_level, 0, 1); + ApplyTextureDefaults(texture_view.handle, params.max_mip_level); + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, + reinterpret_cast<const GLint*>(swizzle.data())); } MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); @@ -909,6 +868,25 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); } +void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w) { + const GLenum new_x = MaxwellToGL::SwizzleSource(swizzle_x); + const GLenum new_y = MaxwellToGL::SwizzleSource(swizzle_y); + const GLenum new_z = MaxwellToGL::SwizzleSource(swizzle_z); + const GLenum new_w = MaxwellToGL::SwizzleSource(swizzle_w); + if (swizzle[0] == new_x && swizzle[1] == new_y && swizzle[2] == new_z && swizzle[3] == new_w) { + return; + } + swizzle = {new_x, new_y, new_z, new_w}; + const auto swizzle_data = reinterpret_cast<const GLint*>(swizzle.data()); + glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + if (texture_view.handle != 0) { + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + } +} + RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} { read_framebuffer.Create(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 8d7d6722c..490b8252e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -382,6 +382,11 @@ public: // Upload data in gl_buffer to this surface's texture void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); + void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w); + private: void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); @@ -393,8 +398,8 @@ private: SurfaceParams params{}; GLenum gl_target{}; GLenum gl_internal_format{}; - bool gl_is_compressed{}; std::size_t cached_size_in_bytes{}; + std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; }; class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 1da744158..4170cbd3c 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -15,12 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R namespace OpenGL { -void OGLTexture::Create() { +void OGLTexture::Create(GLenum target) { if (handle != 0) return; MICROPROFILE_SCOPE(OpenGL_ResourceCreation); - glGenTextures(1, &handle); + glCreateTextures(target, 1, &handle); } void OGLTexture::Release() { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index e33f1e973..df76cbc4b 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -28,7 +28,7 @@ public: } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create(GLenum target); /// Deletes the internal OpenGL resource void Release(); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index b7ba59350..81af803bc 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -462,29 +462,35 @@ void OpenGLState::ApplyPolygonOffset() const { } void OpenGLState::ApplyTextures() const { + bool has_delta{}; + std::size_t first{}; + std::size_t last{}; + std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures; + for (std::size_t i = 0; i < std::size(texture_units); ++i) { const auto& texture_unit = texture_units[i]; const auto& cur_state_texture_unit = cur_state.texture_units[i]; + textures[i] = texture_unit.texture; - if (texture_unit.texture != cur_state_texture_unit.texture) { - glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); - glBindTexture(texture_unit.target, texture_unit.texture); - } - // Update the texture swizzle - if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || - texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || - texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b || - texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) { - std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g, - texture_unit.swizzle.b, texture_unit.swizzle.a}; - glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); + if (textures[i] != cur_state_texture_unit.texture) { + if (!has_delta) { + first = i; + has_delta = true; + } + last = i; } } + + if (has_delta) { + glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), + textures.data()); + } } void OpenGLState::ApplySamplers() const { bool has_delta{}; - std::size_t first{}, last{}; + std::size_t first{}; + std::size_t last{}; std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; for (std::size_t i = 0; i < std::size(samplers); ++i) { samplers[i] = texture_units[i].sampler; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index a5a7c0920..9e1eda5b1 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -126,26 +126,14 @@ public: struct TextureUnit { GLuint texture; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING - GLenum target; - struct { - GLint r; // GL_TEXTURE_SWIZZLE_R - GLint g; // GL_TEXTURE_SWIZZLE_G - GLint b; // GL_TEXTURE_SWIZZLE_B - GLint a; // GL_TEXTURE_SWIZZLE_A - } swizzle; void Unbind() { texture = 0; - swizzle.r = GL_RED; - swizzle.g = GL_GREEN; - swizzle.b = GL_BLUE; - swizzle.a = GL_ALPHA; } void Reset() { Unbind(); sampler = 0; - target = GL_TEXTURE_2D; } }; std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e37b65b38..5b09c38ea 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -171,10 +171,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf Memory::GetPointer(framebuffer_addr), gl_framebuffer_data.data(), true); - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); // Update existing texture @@ -182,14 +178,11 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf // they differ from the LCD resolution. // TODO: Applications could theoretically crash yuzu here by specifying too large // framebuffer sizes. We should make sure that this cannot happen. - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, - screen_info.texture.gl_format, screen_info.texture.gl_type, - gl_framebuffer_data.data()); + glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, + framebuffer.height, screen_info.texture.gl_format, + screen_info.texture.gl_type, gl_framebuffer_data.data()); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - state.texture_units[0].texture = 0; - state.Apply(); } } @@ -199,17 +192,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf */ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture) { - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; - - // Update existing texture - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - - state.texture_units[0].texture = 0; - state.Apply(); + const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; + glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); } /** @@ -249,26 +233,13 @@ void RendererOpenGL::InitOpenGLObjects() { sizeof(ScreenRectVertex)); // Allocate textures for the screen - screen_info.texture.resource.Create(); + screen_info.texture.resource.Create(GL_TEXTURE_2D); - // Allocation of storage is deferred until the first frame, when we - // know the framebuffer size. - - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + const GLuint texture = screen_info.texture.resource.handle; + glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); screen_info.display_texture = screen_info.texture.resource.handle; - state.texture_units[0].texture = 0; - state.Apply(); - // Clear screen to black LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); } @@ -284,20 +255,19 @@ void RendererOpenGL::CreateRasterizer() { void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, const Tegra::FramebufferConfig& framebuffer) { - texture.width = framebuffer.width; texture.height = framebuffer.height; GLint internal_format; switch (framebuffer.pixel_format) { case Tegra::FramebufferConfig::PixelFormat::ABGR8: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); break; default: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); @@ -306,15 +276,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, UNREACHABLE(); } - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, - texture.gl_format, texture.gl_type, nullptr); - - state.texture_units[0].texture = 0; - state.Apply(); + texture.resource.Release(); + texture.resource.Create(GL_TEXTURE_2D); + glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); } void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, @@ -356,7 +320,6 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, }}; state.texture_units[0].texture = screen_info.display_texture; - state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; // Workaround brigthness problems in SMO by enabling sRGB in the final output // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 4d075f088..3dd26da20 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -104,19 +104,42 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) { } case OpCode::Id::LD_L: { UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}", - static_cast<unsigned>(instr.ld_l.unknown.Value())); - - const Node index = Operation(OperationCode::IAdd, GetRegister(instr.gpr8), - Immediate(static_cast<s32>(instr.smem_imm))); - const Node lmem = GetLocalMemory(index); + static_cast<u32>(instr.ld_l.unknown.Value())); + + const auto GetLmem = [&](s32 offset) { + ASSERT(offset % 4 == 0); + const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset); + const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), + immediate_offset); + return GetLocalMemory(address); + }; switch (instr.ldst_sl.type.Value()) { - case Tegra::Shader::StoreType::Bytes32: - SetRegister(bb, instr.gpr0, lmem); + case Tegra::Shader::StoreType::Bits32: + case Tegra::Shader::StoreType::Bits64: + case Tegra::Shader::StoreType::Bits128: { + const u32 count = [&]() { + switch (instr.ldst_sl.type.Value()) { + case Tegra::Shader::StoreType::Bits32: + return 1; + case Tegra::Shader::StoreType::Bits64: + return 2; + case Tegra::Shader::StoreType::Bits128: + return 4; + default: + UNREACHABLE(); + return 0; + } + }(); + for (u32 i = 0; i < count; ++i) + SetTemporal(bb, i, GetLmem(i * 4)); + for (u32 i = 0; i < count; ++i) + SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i)); break; + } default: UNIMPLEMENTED_MSG("LD_L Unhandled type: {}", - static_cast<unsigned>(instr.ldst_sl.type.Value())); + static_cast<u32>(instr.ldst_sl.type.Value())); } break; } @@ -202,12 +225,20 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) { UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}", static_cast<u32>(instr.st_l.unknown.Value())); - const Node index = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), - Immediate(static_cast<s32>(instr.smem_imm))); + const auto GetLmemAddr = [&](s32 offset) { + ASSERT(offset % 4 == 0); + const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset); + return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate); + }; switch (instr.ldst_sl.type.Value()) { - case Tegra::Shader::StoreType::Bytes32: - SetLocalMemory(bb, index, GetRegister(instr.gpr0)); + case Tegra::Shader::StoreType::Bits128: + SetLocalMemory(bb, GetLmemAddr(12), GetRegister(instr.gpr0.Value() + 3)); + SetLocalMemory(bb, GetLmemAddr(8), GetRegister(instr.gpr0.Value() + 2)); + case Tegra::Shader::StoreType::Bits64: + SetLocalMemory(bb, GetLmemAddr(4), GetRegister(instr.gpr0.Value() + 1)); + case Tegra::Shader::StoreType::Bits32: + SetLocalMemory(bb, GetLmemAddr(0), GetRegister(instr.gpr0)); break; default: UNIMPLEMENTED_MSG("ST_L Unhandled type: {}", @@ -324,15 +355,18 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) { const auto& sampler = GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false); + u32 indexer = 0; switch (instr.txq.query_type) { case Tegra::Shader::TextureQueryType::Dimension: { for (u32 element = 0; element < 4; ++element) { - MetaTexture meta{sampler, element}; - const Node value = Operation(OperationCode::F4TextureQueryDimensions, - std::move(meta), GetRegister(instr.gpr8)); - SetTemporal(bb, element, value); + if (instr.txq.IsComponentEnabled(element)) { + MetaTexture meta{sampler, element}; + const Node value = Operation(OperationCode::F4TextureQueryDimensions, + std::move(meta), GetRegister(instr.gpr8)); + SetTemporal(bb, indexer++, value); + } } - for (u32 i = 0; i < 4; ++i) { + for (u32 i = 0; i < indexer; ++i) { SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i)); } break; @@ -734,4 +768,4 @@ std::tuple<std::size_t, std::size_t> ShaderIR::ValidateAndGetCoordinateElement( return {coord_count, total_coord_count}; } -} // namespace VideoCommon::Shader
\ No newline at end of file +} // namespace VideoCommon::Shader diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 3f3cff652..0fc5530f2 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -182,7 +182,7 @@ struct TICEntry { }; union { BitField<0, 16, u32> height_minus_1; - BitField<16, 15, u32> depth_minus_1; + BitField<16, 14, u32> depth_minus_1; }; union { BitField<6, 13, u32> mip_lod_bias; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 8290b4384..d21f95469 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -62,9 +62,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) const QColor new_bg_color = QColorDialog::getColor(bg_color); if (!new_bg_color.isValid()) return; - bg_color = new_bg_color; - ui->bg_button->setStyleSheet( - QString("QPushButton { background-color: %1 }").arg(bg_color.name())); + UpdateBackgroundColorButton(new_bg_color); }); } @@ -76,10 +74,8 @@ void ConfigureGraphics::setConfiguration() { ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); ui->frame_limit->setValue(Settings::values.frame_limit); ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation); - bg_color = QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, - Settings::values.bg_blue); - ui->bg_button->setStyleSheet( - QString("QPushButton { background-color: %1 }").arg(bg_color.name())); + UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, + Settings::values.bg_blue)); } void ConfigureGraphics::applyConfiguration() { @@ -92,3 +88,13 @@ void ConfigureGraphics::applyConfiguration() { Settings::values.bg_green = static_cast<float>(bg_color.greenF()); Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); } + +void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) { + bg_color = color; + + QPixmap pixmap(ui->bg_button->size()); + pixmap.fill(bg_color); + + const QIcon color_icon(pixmap); + ui->bg_button->setIcon(color_icon); +} diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index d6ffc6fde..f2799822d 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -23,6 +23,8 @@ public: private: void setConfiguration(); + void UpdateBackgroundColorButton(QColor color); + std::unique_ptr<Ui::ConfigureGraphics> ui; QColor bg_color; }; diff --git a/src/yuzu/loading_screen.ui b/src/yuzu/loading_screen.ui index a67d273fd..820b47536 100644 --- a/src/yuzu/loading_screen.ui +++ b/src/yuzu/loading_screen.ui @@ -132,7 +132,7 @@ border-radius: 15px; font: 75 15pt "Arial";</string> </property> <property name="text"> - <string>Stage 1 of 2. Estimate Time 5m 4s</string> + <string>Estimated Time 5m 4s</string> </property> </widget> </item> @@ -146,6 +146,9 @@ font: 75 15pt "Arial";</string> <property name="text"> <string/> </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> <property name="margin"> <number>30</number> </property> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ab403b3ac..485e29de2 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1682,12 +1682,16 @@ void GMainWindow::OnToggleFilterBar() { void GMainWindow::OnCaptureScreenshot() { OnPauseGame(); - const QString path = - QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), - UISettings::values.screenshot_path, tr("PNG Image (*.png)")); - if (!path.isEmpty()) { - UISettings::values.screenshot_path = QFileInfo(path).path(); - render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path); + QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path, + tr("PNG Image (*.png)")); + png_dialog.setAcceptMode(QFileDialog::AcceptSave); + png_dialog.setDefaultSuffix("png"); + if (png_dialog.exec()) { + const QString path = png_dialog.selectedFiles().first(); + if (!path.isEmpty()) { + UISettings::values.screenshot_path = QFileInfo(path).path(); + render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, path); + } } OnStartGame(); } |