Files
Xenia-Canary/src/xenia/gpu/resource_cache.cc
2014-12-19 17:29:27 -08:00

121 lines
3.6 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. *
******************************************************************************
*/
#include <xenia/gpu/resource_cache.h>
#include <algorithm>
#include <xenia/core/hash.h>
using namespace std;
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::xenos;
ResourceCache::ResourceCache(Memory* memory)
: memory_(memory) {
}
ResourceCache::~ResourceCache() {
for (auto it = resources_.begin(); it != resources_.end(); ++it) {
Resource* resource = *it;
delete resource;
}
resources_.clear();
}
VertexShaderResource* ResourceCache::FetchVertexShader(
const MemoryRange& memory_range,
const VertexShaderResource::Info& info) {
return FetchHashedResource<VertexShaderResource>(
memory_range, info, &ResourceCache::CreateVertexShader);
}
PixelShaderResource* ResourceCache::FetchPixelShader(
const MemoryRange& memory_range,
const PixelShaderResource::Info& info) {
return FetchHashedResource<PixelShaderResource>(
memory_range, info, &ResourceCache::CreatePixelShader);
}
TextureResource* ResourceCache::FetchTexture(
const MemoryRange& memory_range,
const TextureResource::Info& info) {
auto resource = FetchPagedResource<TextureResource>(
memory_range, info, &ResourceCache::CreateTexture);
if (!resource) {
return nullptr;
}
if (resource->Prepare()) {
XELOGE("Unable to prepare texture");
return nullptr;
}
return resource;
}
SamplerStateResource* ResourceCache::FetchSamplerState(
const SamplerStateResource::Info& info) {
auto key = info.hash();
auto it = static_resources_.find(key);
if (it != static_resources_.end()) {
return static_cast<SamplerStateResource*>(it->second);
}
auto resource = CreateSamplerState(info);
if (resource->Prepare()) {
XELOGE("Unable to prepare sampler state");
return nullptr;
}
static_resources_.insert({ key, resource });
resources_.push_back(resource);
return resource;
}
IndexBufferResource* ResourceCache::FetchIndexBuffer(
const MemoryRange& memory_range,
const IndexBufferResource::Info& info) {
auto resource = FetchPagedResource<IndexBufferResource>(
memory_range, info, &ResourceCache::CreateIndexBuffer);
if (!resource) {
return nullptr;
}
if (resource->Prepare()) {
XELOGE("Unable to prepare index buffer");
return nullptr;
}
return resource;
}
VertexBufferResource* ResourceCache::FetchVertexBuffer(
const MemoryRange& memory_range,
const VertexBufferResource::Info& info) {
auto resource = FetchPagedResource<VertexBufferResource>(
memory_range, info, &ResourceCache::CreateVertexBuffer);
if (!resource) {
return nullptr;
}
if (resource->Prepare()) {
XELOGE("Unable to prepare vertex buffer");
return nullptr;
}
return resource;
}
uint64_t ResourceCache::HashRange(const MemoryRange& memory_range) {
// We could do something smarter here to potentially early exit.
return hash64(memory_range.host_base, memory_range.length);
}
void ResourceCache::SyncRange(uint32_t address, int length) {
SCOPE_profile_cpu_f("gpu");
// TODO(benvanik): something interesting?
//uint32_t lo_address = address % 0x20000000;
//uint32_t hi_address = lo_address + length;
}