Merge pull request #61 from chrisps/canary_experimental

performance improvements, kernel fixes, cpu accuracy improvements
This commit is contained in:
Radosław Gliński
2022-08-21 09:31:09 +02:00
committed by GitHub
70 changed files with 1744 additions and 541 deletions

View File

@@ -29,10 +29,20 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#if defined(NDEBUG)
static constexpr bool should_log_unknown_reg_writes() { return false; }
#else
DEFINE_bool(log_unknown_register_writes, false,
"Log writes to unknown registers from "
"CommandProcessor::WriteRegister. Has significant performance hit.",
"GPU");
static bool should_log_unknown_reg_writes() {
return cvars::log_unknown_register_writes;
}
#endif
namespace xe {
namespace gpu {
@@ -465,7 +475,7 @@ void CommandProcessor::HandleSpecialRegisterWrite(uint32_t index,
}
}
void CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
if (XE_UNLIKELY(cvars::log_unknown_register_writes)) {
if (should_log_unknown_reg_writes()) {
// chrispy: rearrange check order, place set after checks
if (XE_UNLIKELY(!register_file_->IsValidRegister(index))) {
XELOGW("GPU: Write to unknown register ({:04X} = {:08X})", index, value);
@@ -493,15 +503,45 @@ void CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
// very unlikely. these ORS here are meant to be bitwise ors, so that we do
// not do branching evaluation of the conditions (we will almost always take
// all of the branches)
if (XE_UNLIKELY(
(index - XE_GPU_REG_SCRATCH_REG0 < 8) |
(index == XE_GPU_REG_COHER_STATUS_HOST) |
((index - XE_GPU_REG_DC_LUT_RW_INDEX) <=
(XE_GPU_REG_DC_LUT_30_COLOR - XE_GPU_REG_DC_LUT_RW_INDEX)))) {
unsigned expr = (index - XE_GPU_REG_SCRATCH_REG0 < 8) |
(index == XE_GPU_REG_COHER_STATUS_HOST) |
((index - XE_GPU_REG_DC_LUT_RW_INDEX) <=
(XE_GPU_REG_DC_LUT_30_COLOR - XE_GPU_REG_DC_LUT_RW_INDEX));
// chrispy: reordered for msvc branch probability (assumes if is taken and
// else is not)
if (XE_LIKELY(expr == 0)) {
} else {
HandleSpecialRegisterWrite(index, value);
}
}
void CommandProcessor::WriteRegistersFromMem(uint32_t start_index,
uint32_t* base,
uint32_t num_registers) {
for (uint32_t i = 0; i < num_registers; ++i) {
uint32_t data = xe::load_and_swap<uint32_t>(base + i);
this->WriteRegister(start_index + i, data);
}
}
void CommandProcessor::WriteRegisterRangeFromRing(xe::RingBuffer* ring,
uint32_t base,
uint32_t num_registers) {
for (uint32_t i = 0; i < num_registers; ++i) {
uint32_t data = ring->ReadAndSwap<uint32_t>();
WriteRegister(base + i, data);
}
}
void CommandProcessor::WriteOneRegisterFromRing(xe::RingBuffer* ring,
uint32_t base,
uint32_t num_times) {
for (uint32_t m = 0; m < num_times; m++) {
uint32_t reg_data = ring->ReadAndSwap<uint32_t>();
uint32_t target_index = base;
WriteRegister(target_index, reg_data);
}
}
void CommandProcessor::MakeCoherent() {
SCOPE_profile_cpu_f("gpu");
@@ -623,15 +663,20 @@ void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) {
}
bool CommandProcessor::ExecutePacket(RingBuffer* reader) {
// prefetch the wraparound range
// it likely is already in L3 cache, but in a zen system it may be another
// chiplets l3
reader->BeginPrefetchedRead<swcache::PrefetchTag::Level2>(
reader->read_count());
const uint32_t packet = reader->ReadAndSwap<uint32_t>();
const uint32_t packet_type = packet >> 30;
if (packet == 0 || packet == 0x0BADF00D) {
if (XE_UNLIKELY(packet == 0 || packet == 0x0BADF00D)) {
trace_writer_.WritePacketStart(uint32_t(reader->read_ptr() - 4), 1);
trace_writer_.WritePacketEnd();
return true;
}
if (packet == 0xCDCDCDCD) {
if (XE_UNLIKELY(packet == 0xCDCDCDCD)) {
XELOGW("GPU packet is CDCDCDCD - probably read uninitialized memory!");
}
@@ -667,10 +712,10 @@ bool CommandProcessor::ExecutePacketType0(RingBuffer* reader, uint32_t packet) {
uint32_t base_index = (packet & 0x7FFF);
uint32_t write_one_reg = (packet >> 15) & 0x1;
for (uint32_t m = 0; m < count; m++) {
uint32_t reg_data = reader->ReadAndSwap<uint32_t>();
uint32_t target_index = write_one_reg ? base_index : base_index + m;
WriteRegister(target_index, reg_data);
if (write_one_reg) {
WriteOneRegisterFromRing(reader, base_index, count);
} else {
WriteRegisterRangeFromRing(reader, base_index, count);
}
trace_writer_.WritePacketEnd();
@@ -934,7 +979,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader,
uint32_t count) {
SCOPE_profile_cpu_f("gpu");
XELOGI("XE_SWAP");
XELOGD("XE_SWAP");
Profiler::Flip();
@@ -1467,10 +1512,9 @@ bool CommandProcessor::ExecutePacketType3_SET_CONSTANT(RingBuffer* reader,
reader->AdvanceRead((count - 1) * sizeof(uint32_t));
return true;
}
for (uint32_t n = 0; n < count - 1; n++, index++) {
uint32_t data = reader->ReadAndSwap<uint32_t>();
WriteRegister(index, data);
}
WriteRegisterRangeFromRing(reader, index, count - 1);
return true;
}
@@ -1479,10 +1523,9 @@ bool CommandProcessor::ExecutePacketType3_SET_CONSTANT2(RingBuffer* reader,
uint32_t count) {
uint32_t offset_type = reader->ReadAndSwap<uint32_t>();
uint32_t index = offset_type & 0xFFFF;
for (uint32_t n = 0; n < count - 1; n++, index++) {
uint32_t data = reader->ReadAndSwap<uint32_t>();
WriteRegister(index, data);
}
WriteRegisterRangeFromRing(reader, index, count - 1);
return true;
}
@@ -1517,12 +1560,12 @@ bool CommandProcessor::ExecutePacketType3_LOAD_ALU_CONSTANT(RingBuffer* reader,
assert_always();
return true;
}
trace_writer_.WriteMemoryRead(CpuToGpu(address), size_dwords * 4);
for (uint32_t n = 0; n < size_dwords; n++, index++) {
uint32_t data = xe::load_and_swap<uint32_t>(
memory_->TranslatePhysical(address + n * 4));
WriteRegister(index, data);
}
WriteRegistersFromMem(index, (uint32_t*)memory_->TranslatePhysical(address),
size_dwords);
return true;
}
@@ -1530,10 +1573,9 @@ bool CommandProcessor::ExecutePacketType3_SET_SHADER_CONSTANTS(
RingBuffer* reader, uint32_t packet, uint32_t count) {
uint32_t offset_type = reader->ReadAndSwap<uint32_t>();
uint32_t index = offset_type & 0xFFFF;
for (uint32_t n = 0; n < count - 1; n++, index++) {
uint32_t data = reader->ReadAndSwap<uint32_t>();
WriteRegister(index, data);
}
WriteRegisterRangeFromRing(reader, index, count - 1);
return true;
}

View File

@@ -153,8 +153,24 @@ class CommandProcessor {
// rarely needed, most register writes have no special logic here
XE_NOINLINE
void HandleSpecialRegisterWrite(uint32_t index, uint32_t value);
XE_FORCEINLINE
virtual void WriteRegister(uint32_t index, uint32_t value);
// mem has big-endian register values
XE_FORCEINLINE
virtual void WriteRegistersFromMem(uint32_t start_index, uint32_t* base,
uint32_t num_registers);
XE_FORCEINLINE
virtual void WriteRegisterRangeFromRing(xe::RingBuffer* ring, uint32_t base,
uint32_t num_registers);
XE_FORCEINLINE
virtual void WriteOneRegisterFromRing(
xe::RingBuffer* ring, uint32_t base,
uint32_t
num_times); // repeatedly write a value to one register, presumably a
// register with special handling for writes
const reg::DC_LUT_30_COLOR* gamma_ramp_256_entry_table() const {
return gamma_ramp_256_entry_table_;
}

View File

@@ -1710,7 +1710,60 @@ void D3D12CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
}
}
}
void D3D12CommandProcessor::WriteRegistersFromMem(uint32_t start_index,
uint32_t* base,
uint32_t num_registers) {
for (uint32_t i = 0; i < num_registers; ++i) {
uint32_t data = xe::load_and_swap<uint32_t>(base + i);
D3D12CommandProcessor::WriteRegister(start_index + i, data);
}
}
void D3D12CommandProcessor::WriteRegisterRangeFromRing(xe::RingBuffer* ring,
uint32_t base,
uint32_t num_registers) {
// we already brought it into L2 earlier
RingBuffer::ReadRange range =
ring->BeginPrefetchedRead<swcache::PrefetchTag::Level1>(num_registers *
sizeof(uint32_t));
uint32_t num_regs_firstrange =
static_cast<uint32_t>(range.first_length / sizeof(uint32_t));
D3D12CommandProcessor::WriteRegistersFromMem(
base, reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(range.first)),
num_regs_firstrange);
if (range.second) {
D3D12CommandProcessor::WriteRegistersFromMem(
base + num_regs_firstrange,
reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(range.second)),
num_registers - num_regs_firstrange);
}
ring->EndRead(range);
}
void D3D12CommandProcessor::WriteOneRegisterFromRing(xe::RingBuffer* ring,
uint32_t base,
uint32_t num_times) {
auto read = ring->BeginPrefetchedRead<swcache::PrefetchTag::Level1>(
num_times * sizeof(uint32_t));
uint32_t first_length = read.first_length / sizeof(uint32_t);
for (uint32_t i = 0; i < first_length; ++i) {
D3D12CommandProcessor::WriteRegister(
base, xe::load_and_swap<uint32_t>(read.first + (sizeof(uint32_t) * i)));
}
if (read.second) {
uint32_t second_length = read.second_length / sizeof(uint32_t);
for (uint32_t i = 0; i < second_length; ++i) {
D3D12CommandProcessor::WriteRegister(
base,
xe::load_and_swap<uint32_t>(read.second + (sizeof(uint32_t) * i)));
}
}
ring->EndRead(read);
}
void D3D12CommandProcessor::OnGammaRamp256EntryTableValueWritten() {
gamma_ramp_256_entry_table_up_to_date_ = false;
}

View File

@@ -42,7 +42,7 @@ namespace xe {
namespace gpu {
namespace d3d12 {
class D3D12CommandProcessor : public CommandProcessor {
class D3D12CommandProcessor final : public CommandProcessor {
public:
explicit D3D12CommandProcessor(D3D12GraphicsSystem* graphics_system,
kernel::KernelState* kernel_state);
@@ -203,9 +203,17 @@ class D3D12CommandProcessor : public CommandProcessor {
protected:
bool SetupContext() override;
void ShutdownContext() override;
XE_FORCEINLINE
void WriteRegister(uint32_t index, uint32_t value) override;
XE_FORCEINLINE
virtual void WriteRegistersFromMem(uint32_t start_index, uint32_t* base,
uint32_t num_registers) override;
XE_FORCEINLINE
virtual void WriteRegisterRangeFromRing(xe::RingBuffer* ring, uint32_t base,
uint32_t num_registers) override;
XE_FORCEINLINE
virtual void WriteOneRegisterFromRing(xe::RingBuffer* ring, uint32_t base,
uint32_t num_times) override;
void OnGammaRamp256EntryTableValueWritten() override;
void OnGammaRampPWLValueWritten() override;

View File

@@ -406,14 +406,16 @@ bool D3D12SharedMemory::AllocateSparseHostGpuMemoryRange(
}
bool D3D12SharedMemory::UploadRanges(
const std::vector<std::pair<uint32_t, uint32_t>>& upload_page_ranges) {
if (upload_page_ranges.empty()) {
const std::pair<uint32_t, uint32_t>* upload_page_ranges, unsigned num_upload_page_ranges) {
if (!num_upload_page_ranges) {
return true;
}
CommitUAVWritesAndTransitionBuffer(D3D12_RESOURCE_STATE_COPY_DEST);
command_processor_.SubmitBarriers();
auto& command_list = command_processor_.GetDeferredCommandList();
for (auto upload_range : upload_page_ranges) {
//for (auto upload_range : upload_page_ranges) {
for (unsigned int i = 0; i < num_upload_page_ranges; ++i) {
auto& upload_range = upload_page_ranges[i];
uint32_t upload_range_start = upload_range.first;
uint32_t upload_range_length = upload_range.second;
trace_writer_.WriteMemoryRead(upload_range_start << page_size_log2(),

View File

@@ -91,8 +91,8 @@ class D3D12SharedMemory : public SharedMemory {
bool AllocateSparseHostGpuMemoryRange(uint32_t offset_allocations,
uint32_t length_allocations) override;
bool UploadRanges(const std::vector<std::pair<uint32_t, uint32_t>>&
upload_page_ranges) override;
bool UploadRanges(const std::pair<uint32_t, uint32_t>*
upload_page_ranges, unsigned num_ranges) override;
private:
D3D12CommandProcessor& command_processor_;

View File

@@ -31,8 +31,8 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
#if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES
SCOPE_profile_cpu_f("gpu");
#endif // XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES
const uintmax_t* stream = command_stream_.data();
size_t stream_remaining = command_stream_.size();
const uintmax_t* stream = (const uintmax_t*)command_stream_.data();
size_t stream_remaining = command_stream_.size() / sizeof(uintmax_t);
ID3D12PipelineState* current_pipeline_state = nullptr;
while (stream_remaining != 0) {
const CommandHeader& header =
@@ -266,8 +266,12 @@ void DeferredCommandList::Execute(ID3D12GraphicsCommandList* command_list,
void* DeferredCommandList::WriteCommand(Command command,
size_t arguments_size_bytes) {
size_t arguments_size_elements =
(arguments_size_bytes + sizeof(uintmax_t) - 1) / sizeof(uintmax_t);
round_up(arguments_size_bytes, sizeof(uintmax_t), false);
//(arguments_size_bytes + sizeof(uintmax_t) - 1) / sizeof(uintmax_t);
#if 0
size_t offset = command_stream_.size();
command_stream_.resize(offset + kCommandHeaderSizeElements +
arguments_size_elements);
@@ -276,6 +280,19 @@ void* DeferredCommandList::WriteCommand(Command command,
header.command = command;
header.arguments_size_elements = uint32_t(arguments_size_elements);
return command_stream_.data() + (offset + kCommandHeaderSizeElements);
#else
size_t offset = command_stream_.size();
constexpr size_t kCommandHeaderSizeBytes =
kCommandHeaderSizeElements * sizeof(uintmax_t);
command_stream_.resize(offset + kCommandHeaderSizeBytes +
arguments_size_elements);
CommandHeader& header =
*reinterpret_cast<CommandHeader*>(command_stream_.data() + offset);
header.command = command;
header.arguments_size_elements = uint32_t(arguments_size_elements) / sizeof(uintmax_t);
return command_stream_.data() + (offset + kCommandHeaderSizeBytes);
#endif
}
} // namespace d3d12

View File

@@ -19,7 +19,7 @@
#include "xenia/base/literals.h"
#include "xenia/base/math.h"
#include "xenia/ui/d3d12/d3d12_api.h"
#include "xenia/base/memory.h"
namespace xe {
namespace gpu {
namespace d3d12 {
@@ -30,8 +30,12 @@ class D3D12CommandProcessor;
class DeferredCommandList {
public:
static constexpr size_t MAX_SIZEOF_COMMANDLIST = 65536 * 128; //around 8 mb
/*
chrispy: upped from 1_MiB to 4_MiB, m:durandal hits frequent resizes in large open maps
*/
DeferredCommandList(const D3D12CommandProcessor& command_processor,
size_t initial_size_bytes = 1_MiB);
size_t initial_size_bytes = MAX_SIZEOF_COMMANDLIST);
void Reset();
void Execute(ID3D12GraphicsCommandList* command_list,
@@ -562,7 +566,8 @@ class DeferredCommandList {
const D3D12CommandProcessor& command_processor_;
// uintmax_t to ensure uint64_t and pointer alignment of all structures.
std::vector<uintmax_t> command_stream_;
//std::vector<uintmax_t> command_stream_;
FixedVMemVector<MAX_SIZEOF_COMMANDLIST> command_stream_;
};
} // namespace d3d12

View File

@@ -868,7 +868,7 @@ bool GetResolveInfo(const RegisterFile& regs, const Memory& memory,
xenos::kMaxResolveSize);
y1 = y0 + int32_t(xenos::kMaxResolveSize);
}
//fails in forza horizon 1
assert_true(x0 < x1 && y0 < y1);
if (x0 >= x1 || y0 >= y1) {
XELOGE("Resolve region is empty");

View File

@@ -883,7 +883,7 @@ class PrimitiveProcessor {
// Must be called in a global critical region.
void UpdateCacheBucketsNonEmptyL2(
uint32_t bucket_index_div_64,
[[maybe_unused]] const std::unique_lock<std::recursive_mutex>&
[[maybe_unused]] const global_unique_lock_type&
global_lock) {
uint64_t& cache_buckets_non_empty_l2_ref =
cache_buckets_non_empty_l2_[bucket_index_div_64 >> 6];

View File

@@ -320,8 +320,7 @@ void Shader::GatherVertexFetchInformation(
for (auto& vertex_binding : vertex_bindings_) {
if (vertex_binding.fetch_constant == op.fetch_constant_index()) {
// It may not hold that all strides are equal, but I hope it does.
assert_true(!fetch_instr.attributes.stride ||
vertex_binding.stride_words == fetch_instr.attributes.stride);
vertex_binding.attributes.push_back({});
attrib = &vertex_binding.attributes.back();
break;

View File

@@ -14,6 +14,7 @@
#include "xenia/base/assert.h"
#include "xenia/base/bit_range.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
#include "xenia/base/profiling.h"
@@ -344,7 +345,7 @@ void SharedMemory::UnlinkWatchRange(WatchRange* range) {
range->next_free = watch_range_first_free_;
watch_range_first_free_ = range;
}
// todo: optimize, an enormous amount of cpu time (1.34%) is spent here.
bool SharedMemory::RequestRange(uint32_t start, uint32_t length,
bool* any_data_resolved_out) {
if (!length) {
@@ -364,14 +365,20 @@ bool SharedMemory::RequestRange(uint32_t start, uint32_t length,
return false;
}
unsigned int current_upload_range = 0;
uint32_t page_first = start >> page_size_log2_;
uint32_t page_last = (start + length - 1) >> page_size_log2_;
upload_ranges_.clear();
std::pair<uint32_t, uint32_t>* uploads =
reinterpret_cast<std::pair<uint32_t, uint32_t>*>(upload_ranges_.data());
bool any_data_resolved = false;
uint32_t block_first = page_first >> 6;
uint32_t block_last = page_last >> 6;
uint32_t range_start = UINT32_MAX;
{
auto global_lock = global_critical_region_.Acquire();
for (uint32_t i = block_first; i <= block_last; ++i) {
@@ -412,8 +419,13 @@ bool SharedMemory::RequestRange(uint32_t start, uint32_t length,
if (!xe::bit_scan_forward(block_valid_from_start, &block_page)) {
break;
}
upload_ranges_.push_back(
std::make_pair(range_start, (i << 6) + block_page - range_start));
if (current_upload_range + 1 >= MAX_UPLOAD_RANGES) {
xe::FatalError(
"Hit max upload ranges in shared_memory.cc, tell a dev to "
"raise the limit!");
}
uploads[current_upload_range++] =
std::make_pair(range_start, (i << 6) + block_page - range_start);
// In the next iteration within this block, consider this range valid
// since it has been queued for upload.
block_valid |= (uint64_t(1) << block_page) - 1;
@@ -423,17 +435,17 @@ bool SharedMemory::RequestRange(uint32_t start, uint32_t length,
}
}
if (range_start != UINT32_MAX) {
upload_ranges_.push_back(
std::make_pair(range_start, page_last + 1 - range_start));
uploads[current_upload_range++] =
(std::make_pair(range_start, page_last + 1 - range_start));
}
if (any_data_resolved_out) {
*any_data_resolved_out = any_data_resolved;
}
if (upload_ranges_.empty()) {
if (!current_upload_range) {
return true;
}
return UploadRanges(upload_ranges_);
return UploadRanges(uploads, current_upload_range);
}
std::pair<uint32_t, uint32_t> SharedMemory::MemoryInvalidationCallbackThunk(

View File

@@ -35,7 +35,7 @@ class SharedMemory {
virtual void SetSystemPageBlocksValidWithGpuDataWritten();
typedef void (*GlobalWatchCallback)(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
const global_unique_lock_type& global_lock, void* context,
uint32_t address_first, uint32_t address_last, bool invalidated_by_gpu);
typedef void* GlobalWatchHandle;
// Registers a callback invoked when something is invalidated in the GPU
@@ -49,9 +49,9 @@ class SharedMemory {
GlobalWatchHandle RegisterGlobalWatch(GlobalWatchCallback callback,
void* callback_context);
void UnregisterGlobalWatch(GlobalWatchHandle handle);
typedef void (*WatchCallback)(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
void* data, uint64_t argument, bool invalidated_by_gpu);
typedef void (*WatchCallback)(const global_unique_lock_type& global_lock,
void* context, void* data, uint64_t argument,
bool invalidated_by_gpu);
typedef void* WatchHandle;
// Registers a callback invoked when the specified memory range is invalidated
// in the GPU memory copy by the CPU or (if triggered explicitly - such as by
@@ -140,7 +140,8 @@ class SharedMemory {
// ascending address order, so front and back can be used to determine the
// overall bounds of pages to be uploaded.
virtual bool UploadRanges(
const std::vector<std::pair<uint32_t, uint32_t>>& upload_page_ranges) = 0;
const std::pair<uint32_t, uint32_t>* upload_page_ranges,
unsigned num_upload_ranges) = 0;
const std::vector<std::pair<uint32_t, uint32_t>>& trace_download_ranges() {
return trace_download_ranges_;
@@ -174,10 +175,13 @@ class SharedMemory {
void* memory_invalidation_callback_handle_ = nullptr;
void* memory_data_provider_handle_ = nullptr;
static constexpr unsigned int MAX_UPLOAD_RANGES = 65536;
// Ranges that need to be uploaded, generated by GetRangesToUpload (a
// persistently allocated vector).
std::vector<std::pair<uint32_t, uint32_t>> upload_ranges_;
// std::vector<std::pair<uint32_t, uint32_t>> upload_ranges_;
FixedVMemVector<MAX_UPLOAD_RANGES * sizeof(std::pair<uint32_t, uint32_t>)>
upload_ranges_;
// GPU-written memory downloading for traces. <Start address, length>.
std::vector<std::pair<uint32_t, uint32_t>> trace_download_ranges_;

View File

@@ -507,7 +507,7 @@ TextureCache::Texture::~Texture() {
}
void TextureCache::Texture::MakeUpToDateAndWatch(
const std::unique_lock<std::recursive_mutex>& global_lock) {
const global_unique_lock_type& global_lock) {
SharedMemory& shared_memory = texture_cache().shared_memory();
if (base_outdated_) {
assert_not_zero(GetGuestBaseSize());
@@ -552,7 +552,7 @@ void TextureCache::Texture::MarkAsUsed() {
}
void TextureCache::Texture::WatchCallback(
[[maybe_unused]] const std::unique_lock<std::recursive_mutex>& global_lock,
[[maybe_unused]] const global_unique_lock_type& global_lock,
bool is_mip) {
if (is_mip) {
assert_not_zero(GetGuestMipsSize());
@@ -565,8 +565,8 @@ void TextureCache::Texture::WatchCallback(
}
}
void TextureCache::WatchCallback(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
void TextureCache::WatchCallback(const global_unique_lock_type& global_lock,
void* context,
void* data, uint64_t argument, bool invalidated_by_gpu) {
Texture& texture = *static_cast<Texture*>(context);
texture.WatchCallback(global_lock, argument != 0);
@@ -902,7 +902,7 @@ bool TextureCache::IsRangeScaledResolved(uint32_t start_unscaled,
}
void TextureCache::ScaledResolveGlobalWatchCallbackThunk(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
const global_unique_lock_type& global_lock, void* context,
uint32_t address_first, uint32_t address_last, bool invalidated_by_gpu) {
TextureCache* texture_cache = reinterpret_cast<TextureCache*>(context);
texture_cache->ScaledResolveGlobalWatchCallback(
@@ -910,7 +910,7 @@ void TextureCache::ScaledResolveGlobalWatchCallbackThunk(
}
void TextureCache::ScaledResolveGlobalWatchCallback(
const std::unique_lock<std::recursive_mutex>& global_lock,
const global_unique_lock_type& global_lock,
uint32_t address_first, uint32_t address_last, bool invalidated_by_gpu) {
assert_true(IsDrawResolutionScaled());
if (invalidated_by_gpu) {

View File

@@ -230,19 +230,15 @@ class TextureCache {
}
bool IsResolved() const { return base_resolved_ || mips_resolved_; }
bool base_outdated(
const std::unique_lock<std::recursive_mutex>& global_lock) const {
bool base_outdated(const global_unique_lock_type& global_lock) const {
return base_outdated_;
}
bool mips_outdated(
const std::unique_lock<std::recursive_mutex>& global_lock) const {
bool mips_outdated(const global_unique_lock_type& global_lock) const {
return mips_outdated_;
}
void MakeUpToDateAndWatch(
const std::unique_lock<std::recursive_mutex>& global_lock);
void MakeUpToDateAndWatch(const global_unique_lock_type& global_lock);
void WatchCallback(
const std::unique_lock<std::recursive_mutex>& global_lock, bool is_mip);
void WatchCallback(const global_unique_lock_type& global_lock, bool is_mip);
// For LRU caching - updates the last usage frame and moves the texture to
// the end of the usage queue. Must be called any time the texture is
@@ -579,8 +575,8 @@ class TextureCache {
void UpdateTexturesTotalHostMemoryUsage(uint64_t add, uint64_t subtract);
// Shared memory callback for texture data invalidation.
static void WatchCallback(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
static void WatchCallback(const global_unique_lock_type& global_lock,
void* context,
void* data, uint64_t argument, bool invalidated_by_gpu);
// Checks if there are any pages that contain scaled resolve data within the
@@ -589,10 +585,10 @@ class TextureCache {
// Global shared memory invalidation callback for invalidating scaled resolved
// texture data.
static void ScaledResolveGlobalWatchCallbackThunk(
const std::unique_lock<std::recursive_mutex>& global_lock, void* context,
const global_unique_lock_type& global_lock, void* context,
uint32_t address_first, uint32_t address_last, bool invalidated_by_gpu);
void ScaledResolveGlobalWatchCallback(
const std::unique_lock<std::recursive_mutex>& global_lock,
const global_unique_lock_type& global_lock,
uint32_t address_first, uint32_t address_last, bool invalidated_by_gpu);
const RegisterFile& register_file_;

View File

@@ -1157,7 +1157,14 @@ void VulkanCommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
}
}
}
void VulkanCommandProcessor::WriteRegistersFromMem(uint32_t start_index,
uint32_t* base,
uint32_t num_registers) {
for (uint32_t i = 0; i < num_registers; ++i) {
uint32_t data = xe::load_and_swap<uint32_t>(base + i);
VulkanCommandProcessor::WriteRegister(start_index + i, data);
}
}
void VulkanCommandProcessor::SparseBindBuffer(
VkBuffer buffer, uint32_t bind_count, const VkSparseMemoryBind* binds,
VkPipelineStageFlags wait_stage_mask) {

View File

@@ -45,7 +45,7 @@ namespace xe {
namespace gpu {
namespace vulkan {
class VulkanCommandProcessor : public CommandProcessor {
class VulkanCommandProcessor final : public CommandProcessor {
public:
// Single-descriptor layouts for use within a single frame.
enum class SingleTransientDescriptorLayout {
@@ -259,8 +259,11 @@ class VulkanCommandProcessor : public CommandProcessor {
protected:
bool SetupContext() override;
void ShutdownContext() override;
XE_FORCEINLINE
void WriteRegister(uint32_t index, uint32_t value) override;
XE_FORCEINLINE
virtual void WriteRegistersFromMem(uint32_t start_index, uint32_t* base,
uint32_t num_registers) override;
void OnGammaRamp256EntryTableValueWritten() override;
void OnGammaRampPWLValueWritten() override;

View File

@@ -376,18 +376,21 @@ bool VulkanSharedMemory::AllocateSparseHostGpuMemoryRange(
}
bool VulkanSharedMemory::UploadRanges(
const std::vector<std::pair<uint32_t, uint32_t>>& upload_page_ranges) {
if (upload_page_ranges.empty()) {
const std::pair<uint32_t, uint32_t>* upload_page_ranges,
unsigned num_upload_ranges) {
if (!num_upload_ranges) {
return true;
}
auto& range_front = upload_page_ranges[0];
auto& range_back = upload_page_ranges[num_upload_ranges - 1];
// upload_page_ranges are sorted, use them to determine the range for the
// ordering barrier.
Use(Usage::kTransferDestination,
std::make_pair(
upload_page_ranges.front().first << page_size_log2(),
(upload_page_ranges.back().first + upload_page_ranges.back().second -
upload_page_ranges.front().first)
<< page_size_log2()));
std::make_pair(range_front.first << page_size_log2(),
(range_back.first + range_back.second - range_front.first)
<< page_size_log2()));
command_processor_.SubmitBarriers(true);
DeferredCommandBuffer& command_buffer =
command_processor_.deferred_command_buffer();
@@ -395,9 +398,11 @@ bool VulkanSharedMemory::UploadRanges(
bool successful = true;
upload_regions_.clear();
VkBuffer upload_buffer_previous = VK_NULL_HANDLE;
for (auto upload_range : upload_page_ranges) {
uint32_t upload_range_start = upload_range.first;
uint32_t upload_range_length = upload_range.second;
// for (auto upload_range : upload_page_ranges) {
for (unsigned int i = 0; i < num_upload_ranges; ++i) {
uint32_t upload_range_start = upload_page_ranges[i].first;
uint32_t upload_range_length = upload_page_ranges[i].second;
trace_writer_.WriteMemoryRead(upload_range_start << page_size_log2(),
upload_range_length << page_size_log2());
while (upload_range_length) {

View File

@@ -62,8 +62,8 @@ class VulkanSharedMemory : public SharedMemory {
bool AllocateSparseHostGpuMemoryRange(uint32_t offset_allocations,
uint32_t length_allocations) override;
bool UploadRanges(const std::vector<std::pair<uint32_t, uint32_t>>&
upload_page_ranges) override;
bool UploadRanges(const std::pair<uint32_t, uint32_t>*
upload_page_ranges, unsigned num_ranges) override;
private:
void GetUsageMasks(Usage usage, VkPipelineStageFlags& stage_mask,