diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 7850ae103f..2c04daba34 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -90,9 +90,9 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) } void GPU::ProcessCommandList(GPUVAddr address, u32 size) { - const VAddr head_address = memory_manager->GpuToCpuAddress(address); - VAddr current_addr = head_address; - while (current_addr < head_address + size * sizeof(CommandHeader)) { + const boost::optional head_address = memory_manager->GpuToCpuAddress(address); + VAddr current_addr = *head_address; + while (current_addr < *head_address + size * sizeof(CommandHeader)) { const CommandHeader header = {Memory::Read32(current_addr)}; current_addr += sizeof(u32); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 8d7d627b8b..4e9aed380f 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -145,7 +145,7 @@ void Maxwell3D::ProcessQueryGet() { GPUVAddr sequence_address = regs.query.QueryAddress(); // Since the sequence address is given as a GPU VAddr, we have to convert it to an application // VAddr before writing. - VAddr address = memory_manager.GpuToCpuAddress(sequence_address); + boost::optional address = memory_manager.GpuToCpuAddress(sequence_address); // TODO(Subv): Support the other query units. ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, @@ -153,7 +153,7 @@ void Maxwell3D::ProcessQueryGet() { ASSERT_MSG(regs.query.query_get.short_query, "Writing the entire query result structure is unimplemented"); - u32 value = Memory::Read32(address); + u32 value = Memory::Read32(*address); u32 result = 0; // TODO(Subv): Support the other query variables @@ -173,7 +173,7 @@ void Maxwell3D::ProcessQueryGet() { case Regs::QueryMode::Write2: { // Write the current query sequence to the sequence address. u32 sequence = regs.query.query_sequence; - Memory::Write32(address, sequence); + Memory::Write32(*address, sequence); // TODO(Subv): Write the proper query response structure to the address when not using short // mode. @@ -225,9 +225,10 @@ void Maxwell3D::ProcessCBData(u32 value) { // Don't allow writing past the end of the buffer. ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size); - VAddr address = memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos); + boost::optional address = + memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos); - Memory::Write32(address, value); + Memory::Write32(*address, value); // Increment the current buffer position. regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; @@ -237,10 +238,10 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const { GPUVAddr tic_base_address = regs.tic.TICAddress(); GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry); - VAddr tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu); + boost::optional tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu); Texture::TICEntry tic_entry; - Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); + Memory::ReadBlock(*tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear || tic_entry.header_version == Texture::TICHeaderVersion::Pitch, @@ -267,10 +268,10 @@ Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const { GPUVAddr tsc_base_address = regs.tsc.TSCAddress(); GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry); - VAddr tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu); + boost::optional tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu); Texture::TSCEntry tsc_entry; - Memory::ReadBlock(tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry)); + Memory::ReadBlock(*tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry)); return tsc_entry; } @@ -292,7 +293,7 @@ std::vector Maxwell3D::GetStageTextures(Regs::ShaderSt current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) { Texture::TextureHandle tex_handle{ - Memory::Read32(memory_manager.GpuToCpuAddress(current_texture))}; + Memory::Read32(*memory_manager.GpuToCpuAddress(current_texture))}; Texture::FullTextureInfo tex_info{}; // TODO(Subv): Use the shader to determine which textures are actually accessed. diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 3f21071c00..9bbbb7e650 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -73,9 +73,14 @@ boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { return {}; } -VAddr MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { +boost::optional MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { VAddr base_addr = PageSlot(gpu_addr); ASSERT(base_addr != static_cast(PageStatus::Unmapped)); + + if (base_addr == static_cast(PageStatus::Allocated)) { + return {}; + } + return base_addr + (gpu_addr & PAGE_MASK); } diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 4710cb21f6..246c8fb7e8 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -6,6 +6,9 @@ #include #include + +#include + #include "common/common_types.h" #include "core/memory.h" @@ -22,7 +25,7 @@ public: GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align); GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size); GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size); - VAddr GpuToCpuAddress(GPUVAddr gpu_addr); + boost::optional GpuToCpuAddress(GPUVAddr gpu_addr); static constexpr u64 PAGE_BITS = 16; static constexpr u64 PAGE_SIZE = 1 << PAGE_BITS; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 8568d67627..71612790be 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -150,7 +150,7 @@ std::pair RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, u64 size = end - start + 1; // Copy vertex array data - const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(start)}; + const VAddr data_addr{*memory_manager->GpuToCpuAddress(start)}; res_cache.FlushRegion(data_addr, size, nullptr); Memory::ReadBlock(data_addr, array_ptr, size); @@ -233,8 +233,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) { // Fetch program code from memory GLShader::ProgramCode program_code; const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset}; - const VAddr cpu_address{gpu.memory_manager.GpuToCpuAddress(gpu_address)}; - Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64)); + const boost::optional cpu_address{gpu.memory_manager.GpuToCpuAddress(gpu_address)}; + Memory::ReadBlock(*cpu_address, program_code.data(), program_code.size() * sizeof(u64)); GLShader::ShaderSetup setup{std::move(program_code)}; GLShader::ShaderEntries shader_resources; @@ -394,9 +394,9 @@ void RasterizerOpenGL::DrawArrays() { GLintptr index_buffer_offset = 0; if (is_indexed) { const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; - const VAddr index_data_addr{ + const boost::optional index_data_addr{ memory_manager->GpuToCpuAddress(regs.index_array.StartAddress())}; - Memory::ReadBlock(index_data_addr, offseted_buffer, index_buffer_size); + Memory::ReadBlock(*index_data_addr, offseted_buffer, index_buffer_size); index_buffer_offset = buffer_offset; offseted_buffer += index_buffer_size; @@ -659,9 +659,9 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr buffer_draw_state.enabled = true; buffer_draw_state.bindpoint = current_bindpoint + bindpoint; - VAddr addr = gpu.memory_manager->GpuToCpuAddress(buffer.address); + boost::optional addr = gpu.memory_manager->GpuToCpuAddress(buffer.address); std::vector data(used_buffer.GetSize() * sizeof(float)); - Memory::ReadBlock(addr, data.data(), data.size()); + Memory::ReadBlock(*addr, data.data(), data.size()); glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 46f0f25aaf..ced648c123 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -1028,7 +1028,7 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu auto& gpu = Core::System::GetInstance().GPU(); SurfaceParams params; - params.addr = gpu.memory_manager->GpuToCpuAddress(config.tic.Address()); + params.addr = *gpu.memory_manager->GpuToCpuAddress(config.tic.Address()); params.width = config.tic.Width(); params.height = config.tic.Height(); params.is_tiled = config.tic.IsTiled(); @@ -1106,7 +1106,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; SurfaceParams depth_params = color_params; - color_params.addr = memory_manager->GpuToCpuAddress(config.Address()); + color_params.addr = *memory_manager->GpuToCpuAddress(config.Address()); color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); color_params.UpdateParams(); diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp index 5cadb807ec..1fbca8ad09 100644 --- a/src/yuzu/debugger/graphics/graphics_surface.cpp +++ b/src/yuzu/debugger/graphics/graphics_surface.cpp @@ -378,10 +378,10 @@ void GraphicsSurfaceWidget::OnUpdate() { // TODO: Implement a good way to visualize alpha components! QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); - VAddr address = gpu.memory_manager->GpuToCpuAddress(surface_address); + boost::optional address = gpu.memory_manager->GpuToCpuAddress(surface_address); auto unswizzled_data = - Tegra::Texture::UnswizzleTexture(address, surface_format, surface_width, surface_height); + Tegra::Texture::UnswizzleTexture(*address, surface_format, surface_width, surface_height); auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, surface_width, surface_height); @@ -437,9 +437,9 @@ void GraphicsSurfaceWidget::SaveSurface() { pixmap->save(&file, "PNG"); } else if (selectedFilter == bin_filter) { auto& gpu = Core::System::GetInstance().GPU(); - VAddr address = gpu.memory_manager->GpuToCpuAddress(surface_address); + boost::optional address = gpu.memory_manager->GpuToCpuAddress(surface_address); - const u8* buffer = Memory::GetPointer(address); + const u8* buffer = Memory::GetPointer(*address); ASSERT_MSG(buffer != nullptr, "Memory not accessible"); QFile file(filename);