Files
Xenia-Canary/src/xenia/gpu/resource_cache.h
2014-07-11 18:03:35 -07:00

129 lines
4.3 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_RESOURCE_CACHE_H_
#define XENIA_GPU_RESOURCE_CACHE_H_
#include <map>
#include <unordered_map>
#include <xenia/core.h>
#include <xenia/gpu/buffer_resource.h>
#include <xenia/gpu/resource.h>
#include <xenia/gpu/sampler_state_resource.h>
#include <xenia/gpu/shader_resource.h>
#include <xenia/gpu/texture_resource.h>
#include <xenia/gpu/xenos/xenos.h>
namespace xe {
namespace gpu {
class ResourceCache {
public:
virtual ~ResourceCache();
VertexShaderResource* FetchVertexShader(
const MemoryRange& memory_range,
const VertexShaderResource::Info& info);
PixelShaderResource* FetchPixelShader(
const MemoryRange& memory_range,
const PixelShaderResource::Info& info);
TextureResource* FetchTexture(
const MemoryRange& memory_range,
const TextureResource::Info& info);
SamplerStateResource* FetchSamplerState(
const SamplerStateResource::Info& info);
IndexBufferResource* FetchIndexBuffer(
const MemoryRange& memory_range,
const IndexBufferResource::Info& info);
VertexBufferResource* FetchVertexBuffer(
const MemoryRange& memory_range,
const VertexBufferResource::Info& info);
uint64_t HashRange(const MemoryRange& memory_range);
void SyncRange(uint32_t address, int length);
protected:
ResourceCache(Memory* memory);
template <typename T, typename V>
T* FetchHashedResource(const MemoryRange& memory_range,
const typename T::Info& info,
const V& factory) {
// TODO(benvanik): if there's no way it's changed and it's been checked,
// just lookup. This way we don't rehash 100x a frame.
auto key = HashRange(memory_range);
auto it = hashed_resources_.find(key);
if (it != hashed_resources_.end()) {
return static_cast<T*>(it->second);
}
auto resource = (this->*factory)(memory_range, info);
hashed_resources_.insert({ key, resource });
resources_.push_back(resource);
return resource;
}
template <typename T, typename V>
T* FetchPagedResource(const MemoryRange& memory_range,
const typename T::Info& info,
const V& factory) {
uint32_t lo_address = memory_range.guest_base % 0x20000000;
auto key = uint64_t(lo_address);
auto range = paged_resources_.equal_range(key);
for (auto it = range.first; it != range.second; ++it) {
if (it->second->memory_range().length == memory_range.length &&
it->second->Equals(info)) {
return static_cast<T*>(it->second);
}
}
auto resource = (this->*factory)(memory_range, info);
paged_resources_.insert({ key, resource });
resources_.push_back(resource);
return resource;
}
virtual VertexShaderResource* CreateVertexShader(
const MemoryRange& memory_range,
const VertexShaderResource::Info& info) = 0;
virtual PixelShaderResource* CreatePixelShader(
const MemoryRange& memory_range,
const PixelShaderResource::Info& info) = 0;
virtual TextureResource* CreateTexture(
const MemoryRange& memory_range,
const TextureResource::Info& info) = 0;
virtual SamplerStateResource* CreateSamplerState(
const SamplerStateResource::Info& info) = 0;
virtual IndexBufferResource* CreateIndexBuffer(
const MemoryRange& memory_range,
const IndexBufferResource::Info& info) = 0;
virtual VertexBufferResource* CreateVertexBuffer(
const MemoryRange& memory_range,
const VertexBufferResource::Info& info) = 0;
private:
Memory* memory_;
std::vector<Resource*> resources_;
std::unordered_map<uint64_t, HashedResource*> hashed_resources_;
std::unordered_map<uint64_t, StaticResource*> static_resources_;
std::multimap<uint64_t, PagedResource*> paged_resources_;
};
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_RESOURCE_CACHE_H_