diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 98e6296f1..f045008eb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -19,26 +19,29 @@ | |||
| 19 | namespace Service::Nvidia::Devices { | 19 | namespace Service::Nvidia::Devices { |
| 20 | 20 | ||
| 21 | namespace { | 21 | namespace { |
| 22 | // Splice vectors will copy count amount of type T from the input vector into the dst vector. | 22 | // Copies count amount of type T from the input vector into the dst vector. |
| 23 | // Returns the number of bytes written into dst. | ||
| 23 | template <typename T> | 24 | template <typename T> |
| 24 | std::size_t SpliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, | 25 | std::size_t SliceVectors(const std::vector<u8>& input, std::vector<T>& dst, std::size_t count, |
| 25 | std::size_t offset) { | 26 | std::size_t offset) { |
| 26 | if (!dst.empty()) { | 27 | if (dst.empty()) { |
| 27 | std::memcpy(dst.data(), input.data() + offset, count * sizeof(T)); | 28 | return 0; |
| 28 | } | 29 | } |
| 29 | return 0; | 30 | const size_t bytes_copied = count * sizeof(T); |
| 31 | std::memcpy(dst.data(), input.data() + offset, bytes_copied); | ||
| 32 | return bytes_copied; | ||
| 30 | } | 33 | } |
| 31 | 34 | ||
| 32 | // Write vectors will write data to the output buffer | 35 | // Writes the data in src to an offset into the dst vector. The offset is specified in bytes |
| 36 | // Returns the number of bytes written into dst. | ||
| 33 | template <typename T> | 37 | template <typename T> |
| 34 | std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { | 38 | std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) { |
| 35 | if (src.empty()) { | 39 | if (src.empty()) { |
| 36 | return 0; | 40 | return 0; |
| 37 | } else { | ||
| 38 | std::memcpy(dst.data() + offset, src.data(), src.size() * sizeof(T)); | ||
| 39 | offset += src.size() * sizeof(T); | ||
| 40 | return offset; | ||
| 41 | } | 41 | } |
| 42 | const size_t bytes_copied = src.size() * sizeof(T); | ||
| 43 | std::memcpy(dst.data() + offset, src.data(), bytes_copied); | ||
| 44 | return bytes_copied; | ||
| 42 | } | 45 | } |
| 43 | } // Anonymous namespace | 46 | } // Anonymous namespace |
| 44 | 47 | ||
| @@ -62,7 +65,6 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u | |||
| 62 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); | 65 | LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); |
| 63 | 66 | ||
| 64 | // Instantiate param buffers | 67 | // Instantiate param buffers |
| 65 | std::size_t offset = sizeof(IoctlSubmit); | ||
| 66 | std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count); | 68 | std::vector<CommandBuffer> command_buffers(params.cmd_buffer_count); |
| 67 | std::vector<Reloc> relocs(params.relocation_count); | 69 | std::vector<Reloc> relocs(params.relocation_count); |
| 68 | std::vector<u32> reloc_shifts(params.relocation_count); | 70 | std::vector<u32> reloc_shifts(params.relocation_count); |
| @@ -70,13 +72,14 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u | |||
| 70 | std::vector<SyncptIncr> wait_checks(params.syncpoint_count); | 72 | std::vector<SyncptIncr> wait_checks(params.syncpoint_count); |
| 71 | std::vector<Fence> fences(params.fence_count); | 73 | std::vector<Fence> fences(params.fence_count); |
| 72 | 74 | ||
| 73 | // Splice input into their respective buffers | 75 | // Slice input into their respective buffers |
| 74 | offset = SpliceVectors(input, command_buffers, params.cmd_buffer_count, offset); | 76 | std::size_t offset = sizeof(IoctlSubmit); |
| 75 | offset = SpliceVectors(input, relocs, params.relocation_count, offset); | 77 | offset += SliceVectors(input, command_buffers, params.cmd_buffer_count, offset); |
| 76 | offset = SpliceVectors(input, reloc_shifts, params.relocation_count, offset); | 78 | offset += SliceVectors(input, relocs, params.relocation_count, offset); |
| 77 | offset = SpliceVectors(input, syncpt_increments, params.syncpoint_count, offset); | 79 | offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); |
| 78 | offset = SpliceVectors(input, wait_checks, params.syncpoint_count, offset); | 80 | offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); |
| 79 | offset = SpliceVectors(input, fences, params.fence_count, offset); | 81 | offset += SliceVectors(input, wait_checks, params.syncpoint_count, offset); |
| 82 | offset += SliceVectors(input, fences, params.fence_count, offset); | ||
| 80 | 83 | ||
| 81 | auto& gpu = system.GPU(); | 84 | auto& gpu = system.GPU(); |
| 82 | if (gpu.UseNvdec()) { | 85 | if (gpu.UseNvdec()) { |
| @@ -88,7 +91,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u | |||
| 88 | } | 91 | } |
| 89 | } | 92 | } |
| 90 | for (const auto& cmd_buffer : command_buffers) { | 93 | for (const auto& cmd_buffer : command_buffers) { |
| 91 | auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); | 94 | const auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); |
| 92 | ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); | 95 | ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); |
| 93 | const auto map = FindBufferMap(object->dma_map_addr); | 96 | const auto map = FindBufferMap(object->dma_map_addr); |
| 94 | if (!map) { | 97 | if (!map) { |
| @@ -102,21 +105,19 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u | |||
| 102 | gpu.PushCommandBuffer(cmdlist); | 105 | gpu.PushCommandBuffer(cmdlist); |
| 103 | } | 106 | } |
| 104 | if (gpu.UseNvdec()) { | 107 | if (gpu.UseNvdec()) { |
| 105 | |||
| 106 | fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1); | 108 | fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1); |
| 107 | |||
| 108 | Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}}; | 109 | Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}}; |
| 109 | gpu.PushCommandBuffer(cmdlist); | 110 | gpu.PushCommandBuffer(cmdlist); |
| 110 | } | 111 | } |
| 111 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); | 112 | std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); |
| 112 | // Some games expect command_buffers to be written back | 113 | // Some games expect command_buffers to be written back |
| 113 | offset = sizeof(IoctlSubmit); | 114 | offset = sizeof(IoctlSubmit); |
| 114 | offset = WriteVectors(output, command_buffers, offset); | 115 | offset += WriteVectors(output, command_buffers, offset); |
| 115 | offset = WriteVectors(output, relocs, offset); | 116 | offset += WriteVectors(output, relocs, offset); |
| 116 | offset = WriteVectors(output, reloc_shifts, offset); | 117 | offset += WriteVectors(output, reloc_shifts, offset); |
| 117 | offset = WriteVectors(output, syncpt_increments, offset); | 118 | offset += WriteVectors(output, syncpt_increments, offset); |
| 118 | offset = WriteVectors(output, wait_checks, offset); | 119 | offset += WriteVectors(output, wait_checks, offset); |
| 119 | offset = WriteVectors(output, fences, offset); | 120 | offset += WriteVectors(output, fences, offset); |
| 120 | 121 | ||
| 121 | return NvResult::Success; | 122 | return NvResult::Success; |
| 122 | } | 123 | } |
| @@ -148,14 +149,14 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto | |||
| 148 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 149 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); |
| 149 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 150 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); |
| 150 | 151 | ||
| 151 | SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | 152 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); |
| 152 | 153 | ||
| 153 | auto& gpu = system.GPU(); | 154 | auto& gpu = system.GPU(); |
| 154 | 155 | ||
| 155 | for (auto& cmf_buff : cmd_buffer_handles) { | 156 | for (auto& cmd_buffer : cmd_buffer_handles) { |
| 156 | auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; | 157 | auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)}; |
| 157 | if (!object) { | 158 | if (!object) { |
| 158 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | 159 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle); |
| 159 | std::memcpy(output.data(), ¶ms, output.size()); | 160 | std::memcpy(output.data(), ¶ms, output.size()); |
| 160 | return NvResult::InvalidState; | 161 | return NvResult::InvalidState; |
| 161 | } | 162 | } |
| @@ -170,7 +171,7 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto | |||
| 170 | if (!object->dma_map_addr) { | 171 | if (!object->dma_map_addr) { |
| 171 | LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); | 172 | LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); |
| 172 | } else { | 173 | } else { |
| 173 | cmf_buff.map_address = object->dma_map_addr; | 174 | cmd_buffer.map_address = object->dma_map_addr; |
| 174 | AddBufferMap(object->dma_map_addr, object->size, object->addr, | 175 | AddBufferMap(object->dma_map_addr, object->size, object->addr, |
| 175 | object->status == nvmap::Object::Status::Allocated); | 176 | object->status == nvmap::Object::Status::Allocated); |
| 176 | } | 177 | } |
| @@ -186,14 +187,14 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vec | |||
| 186 | IoctlMapBuffer params{}; | 187 | IoctlMapBuffer params{}; |
| 187 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 188 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); |
| 188 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 189 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); |
| 189 | SpliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | 190 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); |
| 190 | 191 | ||
| 191 | auto& gpu = system.GPU(); | 192 | auto& gpu = system.GPU(); |
| 192 | 193 | ||
| 193 | for (auto& cmf_buff : cmd_buffer_handles) { | 194 | for (auto& cmd_buffer : cmd_buffer_handles) { |
| 194 | const auto object{nvmap_dev->GetObject(cmf_buff.map_handle)}; | 195 | const auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)}; |
| 195 | if (!object) { | 196 | if (!object) { |
| 196 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); | 197 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle); |
| 197 | std::memcpy(output.data(), ¶ms, output.size()); | 198 | std::memcpy(output.data(), ¶ms, output.size()); |
| 198 | return NvResult::InvalidState; | 199 | return NvResult::InvalidState; |
| 199 | } | 200 | } |