[D3D12] Texture object creation

This commit is contained in:
Triang3l
2018-08-05 17:43:00 +03:00
parent 620aa664e4
commit b50d6d844f
5 changed files with 557 additions and 23 deletions

View File

@@ -10,7 +10,11 @@
#ifndef XENIA_GPU_D3D12_TEXTURE_CACHE_H_
#define XENIA_GPU_D3D12_TEXTURE_CACHE_H_
#include <unordered_map>
#include "xenia/gpu/d3d12/shared_memory.h"
#include "xenia/gpu/register_file.h"
#include "xenia/gpu/texture_info.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/d3d12/d3d12_api.h"
@@ -50,11 +54,23 @@ class D3D12CommandProcessor;
class TextureCache {
public:
TextureCache(D3D12CommandProcessor* command_processor,
RegisterFile* register_file);
RegisterFile* register_file, SharedMemory* shared_memory);
~TextureCache();
bool Initialize();
void Shutdown();
void TextureFetchConstantWritten(uint32_t index);
void BeginFrame();
// Must be called within a frame - creates and untiles textures needed by
// shaders and puts them in the SRV state. This may bind compute pipelines
// (notifying the command processor about that), so this must be called before
// binding the actual drawing pipeline.
void RequestTextures(uint32_t used_vertex_texture_mask,
uint32_t used_pixel_texture_mask);
void ClearCache();
void WriteTextureSRV(uint32_t fetch_constant,
@@ -64,8 +80,122 @@ class TextureCache {
D3D12_CPU_DESCRIPTOR_HANDLE handle);
private:
struct HostFormat {
DXGI_FORMAT dxgi_format;
};
union TextureKey {
struct {
// Physical 4 KB page with the base mip level, disregarding A/C/E address
// range prefix.
uint32_t base_page : 17; // 17 total
Dimension dimension : 2; // 19
uint32_t width : 13; // 32
uint32_t height : 13; // 45
uint32_t tiled : 1; // 46
uint32_t packed_mips : 1; // 47
// Physical 4 KB page with mip 1 and smaller.
uint32_t mip_page : 17; // 64
// Layers for stacked and 3D, 6 for cube, 1 for other dimensions.
uint32_t depth : 10; // 74
uint32_t mip_max_level : 4; // 78
TextureFormat format : 6; // 84
Endian endianness : 2; // 86
};
struct {
// The key used for unordered_multimap lookup. Single uint32_t instead of
// a uint64_t so XXH hash can be calculated in a stable way due to no
// padding.
uint32_t map_key[2];
// The key used to identify one texture within unordered_multimap buckets.
uint32_t bucket_key;
};
TextureKey() { MakeInvalid(); }
TextureKey(const TextureKey& key) {
SetMapKey(key.GetMapKey());
bucket_key = key.bucket_key;
}
TextureKey& operator=(const TextureKey& key) {
SetMapKey(key.GetMapKey());
bucket_key = key.bucket_key;
return *this;
}
bool operator==(const TextureKey& key) const {
return GetMapKey() == key.GetMapKey() && bucket_key == key.bucket_key;
}
bool operator!=(const TextureKey& key) const {
return GetMapKey() != key.GetMapKey() || bucket_key != key.bucket_key;
}
inline uint64_t GetMapKey() const {
return uint64_t(map_key[0]) | (uint64_t(map_key[1]) << 32);
}
inline void SetMapKey(uint64_t key) {
map_key[0] = uint32_t(key);
map_key[1] = uint32_t(key >> 32);
}
inline bool IsInvalid() {
// Zero base and zero width is enough for a binding to be invalid.
return map_key[0] == 0;
}
inline void MakeInvalid() {
// Reset all for a stable hash.
SetMapKey(0);
bucket_key = 0;
}
};
struct Texture {
TextureKey key;
ID3D12Resource* resource;
D3D12_RESOURCE_STATES state;
// Byte size of the top guest mip level.
uint32_t base_size;
// Byte size of mips between 1 and key.mip_max_level.
uint32_t mip_size;
// Whether the recent base level data has been loaded from the memory.
bool base_in_sync;
// Whether the recent mip data has been loaded from the memory.
bool mips_in_sync;
};
struct TextureBinding {
TextureKey key;
uint32_t swizzle;
Texture* texture;
};
// Converts a texture fetch constant to a texture key, normalizing and
// validating the values, or creating an invalid key.
static void TextureKeyFromFetchConstant(
const xenos::xe_gpu_texture_fetch_t& fetch, TextureKey& key_out,
uint32_t& swizzle_out);
// Returns nullptr if the key is not supported, but also if couldn't create
// the texture - if it's nullptr, occasionally a recreation attempt should be
// made.
Texture* FindOrCreateTexture(TextureKey key);
// Makes all bindings invalid. Also requesting textures after calling this
// will cause another attempt to create a texture or to untile it if there was
// an error.
void ClearBindings();
static HostFormat host_formats_[64];
static const char* dimension_names_[];
D3D12CommandProcessor* command_processor_;
RegisterFile* register_file_;
SharedMemory* shared_memory_;
std::unordered_multimap<uint64_t, Texture*> textures_;
TextureBinding texture_bindings_[32] = {};
// Bit vector with bits reset on fetch constant writes to avoid getting
// texture keys from the fetch constants again and again.
uint32_t texture_keys_in_sync_ = 0;
};
} // namespace d3d12