Moving texture code into shared/separate files. Leaking a lot.
This commit is contained in:
parent
e42460039f
commit
6607606b15
|
@ -13,6 +13,8 @@
|
|||
#include <xenia/gpu/d3d11/d3d11_geometry_shader.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_shader.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_shader_cache.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_texture.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_texture_cache.h>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
|
@ -32,6 +34,7 @@ D3D11GraphicsDriver::D3D11GraphicsDriver(
|
|||
device_->AddRef();
|
||||
device_->GetImmediateContext(&context_);
|
||||
shader_cache_ = new D3D11ShaderCache(device_);
|
||||
texture_cache_ = new D3D11TextureCache(memory_, context_, device_);
|
||||
|
||||
xe_zero_struct(&state_, sizeof(state_));
|
||||
|
||||
|
@ -126,9 +129,6 @@ D3D11GraphicsDriver::D3D11GraphicsDriver(
|
|||
|
||||
D3D11GraphicsDriver::~D3D11GraphicsDriver() {
|
||||
RebuildRenderTargets(0, 0);
|
||||
for (size_t n = 0; n < XECOUNT(state_.texture_fetchers); n++) {
|
||||
XESAFERELEASE(state_.texture_fetchers[n].view);
|
||||
}
|
||||
XESAFERELEASE(state_.constant_buffers.float_constants);
|
||||
XESAFERELEASE(state_.constant_buffers.bool_constants);
|
||||
XESAFERELEASE(state_.constant_buffers.loop_constants);
|
||||
|
@ -136,6 +136,7 @@ D3D11GraphicsDriver::~D3D11GraphicsDriver() {
|
|||
XESAFERELEASE(state_.constant_buffers.gs_consts);
|
||||
XESAFERELEASE(invalid_texture_view_);
|
||||
XESAFERELEASE(invalid_texture_sampler_state_);
|
||||
delete texture_cache_;
|
||||
delete shader_cache_;
|
||||
XESAFERELEASE(context_);
|
||||
XESAFERELEASE(device_);
|
||||
|
@ -1034,9 +1035,8 @@ int D3D11GraphicsDriver::PrepareTextureFetchers() {
|
|||
for (int n = 0; n < XECOUNT(state_.texture_fetchers); n++) {
|
||||
auto& fetcher = state_.texture_fetchers[n];
|
||||
|
||||
// TODO(benvanik): caching.
|
||||
// TODO(benvanik): quick validate without refetching.
|
||||
fetcher.enabled = false;
|
||||
XESAFERELEASE(fetcher.view);
|
||||
fetcher.view = NULL;
|
||||
|
||||
int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + n * 6;
|
||||
|
@ -1049,468 +1049,34 @@ int D3D11GraphicsDriver::PrepareTextureFetchers() {
|
|||
// Stash a copy of the fetch register.
|
||||
fetcher.fetch = fetch;
|
||||
|
||||
fetcher.info = GetTextureInfo(fetch);
|
||||
if (fetcher.info.format == DXGI_FORMAT_UNKNOWN) {
|
||||
// Fetch texture from the cache.
|
||||
uint32_t address = (fetch.address << 12) + address_translation_;
|
||||
auto texture_view = texture_cache_->FetchTexture(address, fetch);
|
||||
if (!texture_view) {
|
||||
XELOGW("D3D11: unable to fetch texture at %.8X", address);
|
||||
continue;
|
||||
}
|
||||
if (texture_view->format == DXGI_FORMAT_UNKNOWN) {
|
||||
XELOGW("D3D11: unknown texture format %d", fetch.format);
|
||||
continue;
|
||||
}
|
||||
fetcher.view = static_cast<D3D11TextureView*>(texture_view);
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC texture_view_desc;
|
||||
xe_zero_struct(&texture_view_desc, sizeof(texture_view_desc));
|
||||
// TODO(benvanik): this may need to be typed on the fetch instruction (float/int/etc?)
|
||||
texture_view_desc.Format = fetcher.info.format;
|
||||
|
||||
ID3D11Resource* texture = NULL;
|
||||
D3D_SRV_DIMENSION dimension = D3D11_SRV_DIMENSION_UNKNOWN;
|
||||
switch (fetch.dimension) {
|
||||
case DIMENSION_1D:
|
||||
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
|
||||
texture_view_desc.Texture1D.MipLevels = 1;
|
||||
texture_view_desc.Texture1D.MostDetailedMip = 0;
|
||||
if (FetchTexture1D(fetch, fetcher.info, &texture)) {
|
||||
XELOGE("D3D11: failed to fetch Texture1D");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_2D:
|
||||
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
texture_view_desc.Texture2D.MipLevels = 1;
|
||||
texture_view_desc.Texture2D.MostDetailedMip = 0;
|
||||
if (FetchTexture2D(fetch, fetcher.info, &texture)) {
|
||||
XELOGE("D3D11: failed to fetch Texture2D");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_3D:
|
||||
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||
texture_view_desc.Texture3D.MipLevels = 1;
|
||||
texture_view_desc.Texture3D.MostDetailedMip = 0;
|
||||
if (FetchTexture3D(fetch, fetcher.info, &texture)) {
|
||||
XELOGE("D3D11: failed to fetch Texture3D");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_CUBE:
|
||||
texture_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
texture_view_desc.TextureCube.MipLevels = 1;
|
||||
texture_view_desc.TextureCube.MostDetailedMip = 0;
|
||||
if (FetchTextureCube(fetch, fetcher.info, &texture)) {
|
||||
XELOGE("D3D11: failed to fetch TextureCube");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
XEASSERTNOTNULL(texture);
|
||||
|
||||
ID3D11ShaderResourceView* texture_view = NULL;
|
||||
HRESULT hr = device_->CreateShaderResourceView(
|
||||
texture, &texture_view_desc, &texture_view);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: unable to create texture resource view");
|
||||
texture->Release();
|
||||
return 1;
|
||||
}
|
||||
texture->Release();
|
||||
|
||||
// Only enable if we get all the way down here successfully.
|
||||
fetcher.enabled = true;
|
||||
fetcher.view = texture_view;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/cc308051(v=vs.85).aspx
|
||||
D3D11GraphicsDriver::TextureInfo D3D11GraphicsDriver::GetTextureInfo(
|
||||
xe_gpu_texture_fetch_t& fetch) {
|
||||
// a2xx_sq_surfaceformat
|
||||
TextureInfo info;
|
||||
info.format = DXGI_FORMAT_UNKNOWN;
|
||||
info.block_size = 0;
|
||||
info.texel_pitch = 0;
|
||||
info.is_compressed = false;
|
||||
switch (fetch.format) {
|
||||
case FMT_8:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RRR1:
|
||||
info.format = DXGI_FORMAT_R8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_000R:
|
||||
info.format = DXGI_FORMAT_A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_8");
|
||||
info.format = DXGI_FORMAT_A8_UNORM;
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 1;
|
||||
break;
|
||||
case FMT_1_5_5_5:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
info.format = DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_1_5_5_5");
|
||||
info.format = DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 2;
|
||||
break;
|
||||
case FMT_8_8_8_8:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RGBA:
|
||||
info.format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
info.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_RGB1:
|
||||
info.format = DXGI_FORMAT_R8G8B8A8_UNORM; // ?
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_BGR1:
|
||||
info.format = DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_8_8_8_8");
|
||||
info.format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 4;
|
||||
break;
|
||||
case FMT_4_4_4_4:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
info.format = DXGI_FORMAT_B4G4R4A4_UNORM; // only supported on Windows 8+
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_4_4_4_4");
|
||||
info.format = DXGI_FORMAT_B4G4R4A4_UNORM; // only supported on Windows 8+
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 2;
|
||||
break;
|
||||
case FMT_16_16_16_16_FLOAT:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RGBA:
|
||||
info.format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_16_16_16_16_FLOAT");
|
||||
info.format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 8;
|
||||
break;
|
||||
case FMT_32_FLOAT:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_R111:
|
||||
info.format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_32_FLOAT");
|
||||
info.format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
}
|
||||
info.block_size = 1;
|
||||
info.texel_pitch = 4;
|
||||
break;
|
||||
case FMT_DXT1:
|
||||
info.format = DXGI_FORMAT_BC1_UNORM;
|
||||
info.block_size = 4;
|
||||
info.texel_pitch = 8;
|
||||
info.is_compressed = true;
|
||||
break;
|
||||
case FMT_DXT2_3:
|
||||
case FMT_DXT4_5:
|
||||
info.format = (fetch.format == FMT_DXT4_5 ? DXGI_FORMAT_BC3_UNORM : DXGI_FORMAT_BC2_UNORM);
|
||||
info.block_size = 4;
|
||||
info.texel_pitch = 16;
|
||||
info.is_compressed = true;
|
||||
break;
|
||||
case FMT_1_REVERSE:
|
||||
case FMT_1:
|
||||
case FMT_5_6_5:
|
||||
case FMT_6_5_5:
|
||||
case FMT_2_10_10_10:
|
||||
case FMT_8_A:
|
||||
case FMT_8_B:
|
||||
case FMT_8_8:
|
||||
case FMT_Cr_Y1_Cb_Y0:
|
||||
case FMT_Y1_Cr_Y0_Cb:
|
||||
case FMT_5_5_5_1:
|
||||
case FMT_8_8_8_8_A:
|
||||
case FMT_10_11_11:
|
||||
case FMT_11_11_10:
|
||||
case FMT_24_8:
|
||||
case FMT_24_8_FLOAT:
|
||||
case FMT_16:
|
||||
case FMT_16_16:
|
||||
case FMT_16_16_16_16:
|
||||
case FMT_16_EXPAND:
|
||||
case FMT_16_16_EXPAND:
|
||||
case FMT_16_16_16_16_EXPAND:
|
||||
case FMT_16_FLOAT:
|
||||
case FMT_16_16_FLOAT:
|
||||
case FMT_32:
|
||||
case FMT_32_32:
|
||||
case FMT_32_32_32_32:
|
||||
case FMT_32_32_FLOAT:
|
||||
case FMT_32_32_32_32_FLOAT:
|
||||
case FMT_32_AS_8:
|
||||
case FMT_32_AS_8_8:
|
||||
case FMT_16_MPEG:
|
||||
case FMT_16_16_MPEG:
|
||||
case FMT_8_INTERLACED:
|
||||
case FMT_32_AS_8_INTERLACED:
|
||||
case FMT_32_AS_8_8_INTERLACED:
|
||||
case FMT_16_INTERLACED:
|
||||
case FMT_16_MPEG_INTERLACED:
|
||||
case FMT_16_16_MPEG_INTERLACED:
|
||||
case FMT_DXN:
|
||||
case FMT_8_8_8_8_AS_16_16_16_16:
|
||||
case FMT_DXT1_AS_16_16_16_16:
|
||||
case FMT_DXT2_3_AS_16_16_16_16:
|
||||
case FMT_DXT4_5_AS_16_16_16_16:
|
||||
case FMT_2_10_10_10_AS_16_16_16_16:
|
||||
case FMT_10_11_11_AS_16_16_16_16:
|
||||
case FMT_11_11_10_AS_16_16_16_16:
|
||||
case FMT_32_32_32_FLOAT:
|
||||
case FMT_DXT3A:
|
||||
case FMT_DXT5A:
|
||||
case FMT_CTX1:
|
||||
case FMT_DXT3A_AS_1_1_1_1:
|
||||
info.format = DXGI_FORMAT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::FetchTexture1D(
|
||||
xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
uint32_t address = (fetch.address << 12) + address_translation_;
|
||||
|
||||
uint32_t width = 1 + fetch.size_1d.width;
|
||||
|
||||
D3D11_TEXTURE1D_DESC texture_desc;
|
||||
xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
texture_desc.Width = width;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = info.format;
|
||||
texture_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS?
|
||||
HRESULT hr = device_->CreateTexture1D(
|
||||
&texture_desc, NULL, (ID3D11Texture1D**)out_texture);
|
||||
if (FAILED(hr)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEFORCEINLINE void TextureSwap(uint8_t* dest, const uint8_t* src, uint32_t pitch, XE_GPU_ENDIAN endianness) {
|
||||
switch (endianness) {
|
||||
case XE_GPU_ENDIAN_8IN16:
|
||||
for (uint32_t i = 0; i < pitch; i += 2, src += 2, dest += 2) {
|
||||
*(uint16_t*)dest = XESWAP16(*(uint16_t*)src);
|
||||
}
|
||||
break;
|
||||
case XE_GPU_ENDIAN_8IN32: // Swap bytes.
|
||||
for (uint32_t i = 0; i < pitch; i += 4, src += 4, dest += 4) {
|
||||
*(uint32_t*)dest = XESWAP32(*(uint32_t*)src);
|
||||
}
|
||||
break;
|
||||
case XE_GPU_ENDIAN_16IN32: // Swap half words.
|
||||
for (uint32_t i = 0; i < pitch; i += 4, src += 4, dest += 4) {
|
||||
uint32_t value = *(uint32_t*)src;
|
||||
*(uint32_t*)dest = ((value >> 16) & 0xFFFF) | (value << 16);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case XE_GPU_ENDIAN_NONE:
|
||||
memcpy(dest, src, pitch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// https://code.google.com/p/crunch/source/browse/trunk/inc/crn_decomp.h#4104
|
||||
XEFORCEINLINE uint32_t TiledOffset2DOuter(uint32_t y, uint32_t width, uint32_t log_bpp)
|
||||
{
|
||||
uint32_t macro = ((y >> 5) * (width >> 5)) << (log_bpp + 7);
|
||||
uint32_t micro = ((y & 6) << 2) << log_bpp;
|
||||
return macro + ((micro & ~15) << 1) + (micro & 15) + ((y & 8) << (3 + log_bpp)) + ((y & 1) << 4);
|
||||
}
|
||||
|
||||
XEFORCEINLINE uint32_t TiledOffset2DInner(uint32_t x, uint32_t y, uint32_t bpp, uint32_t base_offset)
|
||||
{
|
||||
uint32_t macro = (x >> 5) << (bpp + 7);
|
||||
uint32_t micro = (x & 7) << bpp;
|
||||
uint32_t offset = base_offset + (macro + ((micro & ~15) << 1) + (micro & 15));
|
||||
return ((offset & ~511) << 3) + ((offset & 448) << 2) + (offset & 63) +
|
||||
((y & 16) << 7) + (((((y & 8) >> 2) + (x >> 3)) & 3) << 6);
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::FetchTexture2D(
|
||||
xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XEASSERTTRUE(fetch.dimension == 1);
|
||||
|
||||
uint32_t address = (fetch.address << 12) + address_translation_;
|
||||
|
||||
uint32_t logical_width = 1 + fetch.size_2d.width;
|
||||
uint32_t logical_height = 1 + fetch.size_2d.height;
|
||||
|
||||
uint32_t block_width = logical_width / info.block_size;
|
||||
uint32_t block_height = logical_height / info.block_size;
|
||||
|
||||
uint32_t input_width, input_height;
|
||||
uint32_t output_width, output_height;
|
||||
|
||||
if (!info.is_compressed) {
|
||||
// must be 32x32, but also must have a pitch that is a multiple of 256 bytes
|
||||
uint32_t bytes_per_block = info.block_size * info.block_size * info.texel_pitch;
|
||||
uint32_t width_multiple = 32;
|
||||
if (bytes_per_block) {
|
||||
uint32_t minimum_multiple = 256 / bytes_per_block;
|
||||
if (width_multiple < minimum_multiple) {
|
||||
width_multiple = minimum_multiple;
|
||||
}
|
||||
}
|
||||
|
||||
input_width = XEROUNDUP(logical_width, width_multiple);
|
||||
input_height = XEROUNDUP(logical_height, 32);
|
||||
output_width = logical_width;
|
||||
output_height = logical_height;
|
||||
}
|
||||
else {
|
||||
// must be 128x128
|
||||
input_width = XEROUNDUP(logical_width, 128);
|
||||
input_height = XEROUNDUP(logical_height, 128);
|
||||
output_width = XENEXTPOW2(logical_width);
|
||||
output_height = XENEXTPOW2(logical_height);
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC texture_desc;
|
||||
xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
texture_desc.Width = output_width;
|
||||
texture_desc.Height = output_height;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = info.format;
|
||||
texture_desc.SampleDesc.Count = 1;
|
||||
texture_desc.SampleDesc.Quality = 0;
|
||||
texture_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS?
|
||||
HRESULT hr = device_->CreateTexture2D(
|
||||
&texture_desc, NULL, (ID3D11Texture2D**)out_texture);
|
||||
if (FAILED(hr)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO(benvanik): all mip levels.
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
hr = context_->Map(*out_texture, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: failed to map texture");
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto logical_pitch = (logical_width / info.block_size) * info.texel_pitch;
|
||||
auto input_pitch = (input_width / info.block_size) * info.texel_pitch;
|
||||
auto output_pitch = res.RowPitch; // (output_width / info.block_size) * info.texel_pitch;
|
||||
|
||||
const uint8_t* src = memory_->Translate(address);
|
||||
uint8_t* dest = (uint8_t*)res.pData;
|
||||
|
||||
memset(dest, 0, output_pitch * (output_height / info.block_size)); // TODO(gibbed): remove me later
|
||||
|
||||
if (!fetch.tiled) {
|
||||
dest = (uint8_t*)res.pData;
|
||||
for (uint32_t y = 0; y < block_height; y++) {
|
||||
for (uint32_t x = 0; x < logical_pitch; x += info.texel_pitch) {
|
||||
TextureSwap(dest + x, src + x, info.texel_pitch, (XE_GPU_ENDIAN)fetch.endianness);
|
||||
}
|
||||
src += input_pitch;
|
||||
dest += output_pitch;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto bpp = (info.texel_pitch >> 2) + ((info.texel_pitch >> 1) >> (info.texel_pitch >> 2));
|
||||
for (uint32_t y = 0, output_base_offset = 0; y < block_height; y++, output_base_offset += output_pitch) {
|
||||
auto input_base_offset = TiledOffset2DOuter(y, (input_width / info.block_size), bpp);
|
||||
for (uint32_t x = 0, output_offset = output_base_offset; x < block_width; x++, output_offset += info.texel_pitch) {
|
||||
auto input_offset = TiledOffset2DInner(x, y, bpp, input_base_offset) >> bpp;
|
||||
TextureSwap(dest + output_offset,
|
||||
src + input_offset * info.texel_pitch,
|
||||
info.texel_pitch, (XE_GPU_ENDIAN)fetch.endianness);
|
||||
}
|
||||
}
|
||||
}
|
||||
context_->Unmap(*out_texture, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::FetchTexture3D(
|
||||
xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XELOGE("D3D11: FetchTexture2D not yet implemented");
|
||||
XEASSERTALWAYS();
|
||||
return 1;
|
||||
//D3D11_TEXTURE3D_DESC texture_desc;
|
||||
//xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
//texture_desc.Width;
|
||||
//texture_desc.Height;
|
||||
//texture_desc.Depth;
|
||||
//texture_desc.MipLevels;
|
||||
//texture_desc.Format;
|
||||
//texture_desc.Usage;
|
||||
//texture_desc.BindFlags;
|
||||
//texture_desc.CPUAccessFlags;
|
||||
//texture_desc.MiscFlags;
|
||||
//hr = device_->CreateTexture3D(
|
||||
// &texture_desc, &initial_data, (ID3D11Texture3D**)&texture);
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::FetchTextureCube(
|
||||
xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XELOGE("D3D11: FetchTextureCube not yet implemented");
|
||||
XEASSERTALWAYS();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::PrepareTextureSampler(
|
||||
xenos::XE_GPU_SHADER_TYPE shader_type, Shader::tex_buffer_desc_t& desc) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// If the fetcher is disabled or invalid, set some default textures.
|
||||
auto& fetcher = state_.texture_fetchers[desc.fetch_slot];
|
||||
auto& info = fetcher.info;
|
||||
if (!fetcher.enabled ||
|
||||
info.format == DXGI_FORMAT_UNKNOWN) {
|
||||
fetcher.view->format == DXGI_FORMAT_UNKNOWN) {
|
||||
XELOGW("D3D11: ignoring texture fetch: disabled or an unknown format");
|
||||
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {
|
||||
context_->VSSetShaderResources(desc.input_index,
|
||||
|
@ -1526,82 +1092,16 @@ int D3D11GraphicsDriver::PrepareTextureSampler(
|
|||
return 0;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// Get and set the real shader resource views/samplers.
|
||||
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {
|
||||
context_->VSSetShaderResources(desc.input_index, 1, &fetcher.view);
|
||||
context_->VSSetShaderResources(desc.input_index, 1, &fetcher.view->srv);
|
||||
} else {
|
||||
context_->PSSetShaderResources(desc.input_index, 1, &fetcher.view);
|
||||
context_->PSSetShaderResources(desc.input_index, 1, &fetcher.view->srv);
|
||||
}
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc;
|
||||
xe_zero_struct(&sampler_desc, sizeof(sampler_desc));
|
||||
uint32_t min_filter = desc.tex_fetch.min_filter == 3 ?
|
||||
fetcher.fetch.min_filter : desc.tex_fetch.min_filter;
|
||||
uint32_t mag_filter = desc.tex_fetch.mag_filter == 3 ?
|
||||
fetcher.fetch.mag_filter : desc.tex_fetch.mag_filter;
|
||||
uint32_t mip_filter = desc.tex_fetch.mip_filter == 3 ?
|
||||
fetcher.fetch.mip_filter : desc.tex_fetch.mip_filter;
|
||||
// MIN, MAG, MIP
|
||||
static const D3D11_FILTER filter_matrix[2][2][3] = {
|
||||
{
|
||||
// min = POINT
|
||||
{
|
||||
// mag = POINT
|
||||
D3D11_FILTER_MIN_MAG_MIP_POINT,
|
||||
D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, // basemap?
|
||||
},
|
||||
{
|
||||
// mag = LINEAR
|
||||
D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
|
||||
D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR, // basemap?
|
||||
},
|
||||
},
|
||||
{
|
||||
// min = LINEAR
|
||||
{
|
||||
// mag = POINT
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT,
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, // basemap?
|
||||
},
|
||||
{
|
||||
// mag = LINEAR
|
||||
D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
||||
D3D11_FILTER_MIN_MAG_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_MAG_MIP_LINEAR, // basemap?
|
||||
},
|
||||
},
|
||||
};
|
||||
sampler_desc.Filter = filter_matrix[min_filter][mag_filter][mip_filter];
|
||||
static const D3D11_TEXTURE_ADDRESS_MODE mode_map[] = {
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR_ONCE, // ?
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR_ONCE, // ?
|
||||
D3D11_TEXTURE_ADDRESS_BORDER, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR, // ?
|
||||
};
|
||||
sampler_desc.AddressU = mode_map[fetcher.fetch.clamp_x];
|
||||
sampler_desc.AddressV = mode_map[fetcher.fetch.clamp_y];
|
||||
sampler_desc.AddressW = mode_map[fetcher.fetch.clamp_z];
|
||||
sampler_desc.MipLODBias;
|
||||
sampler_desc.MaxAnisotropy = 1;
|
||||
sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
sampler_desc.BorderColor[0];
|
||||
sampler_desc.BorderColor[1];
|
||||
sampler_desc.BorderColor[2];
|
||||
sampler_desc.BorderColor[3];
|
||||
sampler_desc.MinLOD;
|
||||
sampler_desc.MaxLOD;
|
||||
ID3D11SamplerState* sampler_state = NULL;
|
||||
hr = device_->CreateSamplerState(&sampler_desc, &sampler_state);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: unable to create sampler state");
|
||||
ID3D11SamplerState* sampler_state = texture_cache_->GetSamplerState(
|
||||
fetcher.fetch, desc);
|
||||
if (!sampler_state) {
|
||||
XELOGW("D3D11: failed to set sampler state; ignoring texture");
|
||||
return 1;
|
||||
}
|
||||
if (shader_type == XE_GPU_SHADER_TYPE_VERTEX) {
|
||||
|
@ -1609,7 +1109,7 @@ int D3D11GraphicsDriver::PrepareTextureSampler(
|
|||
} else {
|
||||
context_->PSSetSamplers(desc.input_index, 1, &sampler_state);
|
||||
}
|
||||
sampler_state->Release();
|
||||
XESAFERELEASE(sampler_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace d3d11 {
|
|||
|
||||
class D3D11PixelShader;
|
||||
class D3D11ShaderCache;
|
||||
class D3D11TextureCache;
|
||||
struct D3D11TextureView;
|
||||
class D3D11VertexShader;
|
||||
|
||||
|
||||
|
@ -66,25 +68,6 @@ private:
|
|||
int PrepareTextureFetchers();
|
||||
int PrepareTextureSampler(xenos::XE_GPU_SHADER_TYPE shader_type,
|
||||
Shader::tex_buffer_desc_t& desc);
|
||||
typedef struct {
|
||||
DXGI_FORMAT format;
|
||||
uint32_t block_size;
|
||||
uint32_t texel_pitch;
|
||||
bool is_compressed;
|
||||
} TextureInfo;
|
||||
TextureInfo GetTextureInfo(xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
int FetchTexture1D(xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture);
|
||||
int FetchTexture2D(xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture);
|
||||
int FetchTexture3D(xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture);
|
||||
int FetchTextureCube(xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
TextureInfo& info,
|
||||
ID3D11Resource** out_texture);
|
||||
int PrepareIndexBuffer(
|
||||
bool index_32bit, uint32_t index_count,
|
||||
uint32_t index_base, uint32_t index_size, uint32_t endianness);
|
||||
|
@ -94,6 +77,7 @@ private:
|
|||
ID3D11Device* device_;
|
||||
ID3D11DeviceContext* context_;
|
||||
D3D11ShaderCache* shader_cache_;
|
||||
D3D11TextureCache* texture_cache_;
|
||||
|
||||
ID3D11ShaderResourceView* invalid_texture_view_;
|
||||
ID3D11SamplerState* invalid_texture_sampler_state_;
|
||||
|
@ -125,8 +109,7 @@ private:
|
|||
struct {
|
||||
bool enabled;
|
||||
xenos::xe_gpu_texture_fetch_t fetch;
|
||||
TextureInfo info;
|
||||
ID3D11ShaderResourceView* view;
|
||||
D3D11TextureView* view;
|
||||
} texture_fetchers[32];
|
||||
} state_;
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/d3d11/d3d11_texture.h>
|
||||
|
||||
#include <xenia/gpu/gpu-private.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_texture_cache.h>
|
||||
#include <xenia/gpu/xenos/ucode.h>
|
||||
#include <xenia/gpu/xenos/xenos.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
|
||||
D3D11Texture::D3D11Texture(D3D11TextureCache* cache, uint32_t address)
|
||||
: Texture(address),
|
||||
cache_(cache) {
|
||||
}
|
||||
|
||||
D3D11Texture::~D3D11Texture() {
|
||||
// views
|
||||
}
|
||||
|
||||
TextureView* D3D11Texture::Fetch(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch) {
|
||||
D3D11TextureView* view = new D3D11TextureView();
|
||||
view->texture = this;
|
||||
if (!FillViewInfo(view, fetch)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
xe_zero_struct(&srv_desc, sizeof(srv_desc));
|
||||
// TODO(benvanik): this may need to be typed on the fetch instruction (float/int/etc?)
|
||||
srv_desc.Format = view->format;
|
||||
|
||||
D3D_SRV_DIMENSION dimension = D3D11_SRV_DIMENSION_UNKNOWN;
|
||||
switch (view->dimensions) {
|
||||
case DIMENSION_1D:
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
|
||||
srv_desc.Texture1D.MipLevels = 1;
|
||||
srv_desc.Texture1D.MostDetailedMip = 0;
|
||||
if (!FetchTexture1D(view, fetch)) {
|
||||
XELOGE("D3D11: failed to fetch Texture1D");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_2D:
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MipLevels = 1;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
if (!FetchTexture2D(view, fetch)) {
|
||||
XELOGE("D3D11: failed to fetch Texture2D");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_3D:
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||
srv_desc.Texture3D.MipLevels = 1;
|
||||
srv_desc.Texture3D.MostDetailedMip = 0;
|
||||
if (!FetchTexture3D(view, fetch)) {
|
||||
XELOGE("D3D11: failed to fetch Texture3D");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case DIMENSION_CUBE:
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srv_desc.TextureCube.MipLevels = 1;
|
||||
srv_desc.TextureCube.MostDetailedMip = 0;
|
||||
if (!FetchTextureCube(view, fetch)) {
|
||||
XELOGE("D3D11: failed to fetch TextureCube");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
HRESULT hr = cache_->device()->CreateShaderResourceView(
|
||||
view->resource, &srv_desc, &view->srv);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: unable to create texture resource view");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
bool D3D11Texture::FetchTexture1D(
|
||||
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
uint32_t width = 1 + fetch.size_1d.width;
|
||||
|
||||
D3D11_TEXTURE1D_DESC texture_desc;
|
||||
xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
texture_desc.Width = width;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = view->format;
|
||||
texture_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS?
|
||||
HRESULT hr = cache_->device()->CreateTexture1D(
|
||||
&texture_desc, NULL, (ID3D11Texture1D**)&view->resource);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(benvanik): upload!
|
||||
XELOGE("D3D11: FetchTexture1D not yet implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool D3D11Texture::FetchTexture2D(
|
||||
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XEASSERTTRUE(fetch.dimension == 1);
|
||||
|
||||
uint32_t logical_width = 1 + fetch.size_2d.width;
|
||||
uint32_t logical_height = 1 + fetch.size_2d.height;
|
||||
|
||||
uint32_t block_width = logical_width / view->block_size;
|
||||
uint32_t block_height = logical_height / view->block_size;
|
||||
|
||||
uint32_t input_width, input_height;
|
||||
uint32_t output_width, output_height;
|
||||
|
||||
if (!view->is_compressed) {
|
||||
// must be 32x32, but also must have a pitch that is a multiple of 256 bytes
|
||||
uint32_t bytes_per_block = view->block_size * view->block_size *
|
||||
view->texel_pitch;
|
||||
uint32_t width_multiple = 32;
|
||||
if (bytes_per_block) {
|
||||
uint32_t minimum_multiple = 256 / bytes_per_block;
|
||||
if (width_multiple < minimum_multiple) {
|
||||
width_multiple = minimum_multiple;
|
||||
}
|
||||
}
|
||||
|
||||
input_width = XEROUNDUP(logical_width, width_multiple);
|
||||
input_height = XEROUNDUP(logical_height, 32);
|
||||
output_width = logical_width;
|
||||
output_height = logical_height;
|
||||
}
|
||||
else {
|
||||
// must be 128x128
|
||||
input_width = XEROUNDUP(logical_width, 128);
|
||||
input_height = XEROUNDUP(logical_height, 128);
|
||||
output_width = XENEXTPOW2(logical_width);
|
||||
output_height = XENEXTPOW2(logical_height);
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC texture_desc;
|
||||
xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
texture_desc.Width = output_width;
|
||||
texture_desc.Height = output_height;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = view->format;
|
||||
texture_desc.SampleDesc.Count = 1;
|
||||
texture_desc.SampleDesc.Quality = 0;
|
||||
texture_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS?
|
||||
HRESULT hr = cache_->device()->CreateTexture2D(
|
||||
&texture_desc, NULL, (ID3D11Texture2D**)&view->resource);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(benvanik): all mip levels.
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
hr = cache_->context()->Map(view->resource, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: failed to map texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto logical_pitch = (logical_width / view->block_size) * view->texel_pitch;
|
||||
auto input_pitch = (input_width / view->block_size) * view->texel_pitch;
|
||||
auto output_pitch = res.RowPitch; // (output_width / info.block_size) * info.texel_pitch;
|
||||
|
||||
const uint8_t* src = cache_->memory()->Translate(address_);
|
||||
uint8_t* dest = (uint8_t*)res.pData;
|
||||
|
||||
//memset(dest, 0, output_pitch * (output_height / view->block_size)); // TODO(gibbed): remove me later
|
||||
|
||||
if (!fetch.tiled) {
|
||||
dest = (uint8_t*)res.pData;
|
||||
for (uint32_t y = 0; y < block_height; y++) {
|
||||
for (uint32_t x = 0; x < logical_pitch; x += view->texel_pitch) {
|
||||
TextureSwap(dest + x, src + x, view->texel_pitch, (XE_GPU_ENDIAN)fetch.endianness);
|
||||
}
|
||||
src += input_pitch;
|
||||
dest += output_pitch;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto bpp = (view->texel_pitch >> 2) + ((view->texel_pitch >> 1) >> (view->texel_pitch >> 2));
|
||||
for (uint32_t y = 0, output_base_offset = 0; y < block_height; y++, output_base_offset += output_pitch) {
|
||||
auto input_base_offset = TiledOffset2DOuter(y, (input_width / view->block_size), bpp);
|
||||
for (uint32_t x = 0, output_offset = output_base_offset; x < block_width; x++, output_offset += view->texel_pitch) {
|
||||
auto input_offset = TiledOffset2DInner(x, y, bpp, input_base_offset) >> bpp;
|
||||
TextureSwap(dest + output_offset,
|
||||
src + input_offset * view->texel_pitch,
|
||||
view->texel_pitch, (XE_GPU_ENDIAN)fetch.endianness);
|
||||
}
|
||||
}
|
||||
}
|
||||
cache_->context()->Unmap(view->resource, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11Texture::FetchTexture3D(
|
||||
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XELOGE("D3D11: FetchTexture3D not yet implemented");
|
||||
XEASSERTALWAYS();
|
||||
return false;
|
||||
//D3D11_TEXTURE3D_DESC texture_desc;
|
||||
//xe_zero_struct(&texture_desc, sizeof(texture_desc));
|
||||
//texture_desc.Width;
|
||||
//texture_desc.Height;
|
||||
//texture_desc.Depth;
|
||||
//texture_desc.MipLevels;
|
||||
//texture_desc.Format;
|
||||
//texture_desc.Usage;
|
||||
//texture_desc.BindFlags;
|
||||
//texture_desc.CPUAccessFlags;
|
||||
//texture_desc.MiscFlags;
|
||||
//hr = device_->CreateTexture3D(
|
||||
// &texture_desc, &initial_data, (ID3D11Texture3D**)&view->resource);
|
||||
}
|
||||
|
||||
bool D3D11Texture::FetchTextureCube(
|
||||
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
XELOGE("D3D11: FetchTextureCube not yet implemented");
|
||||
XEASSERTALWAYS();
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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_D3D11_D3D11_TEXTURE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_TEXTURE_H_
|
||||
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/gpu/texture.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11TextureCache;
|
||||
|
||||
|
||||
struct D3D11TextureView : TextureView {
|
||||
ID3D11Resource* resource;
|
||||
ID3D11ShaderResourceView* srv;
|
||||
|
||||
D3D11TextureView()
|
||||
: resource(nullptr), srv(nullptr) {}
|
||||
virtual ~D3D11TextureView() {
|
||||
XESAFERELEASE(srv);
|
||||
XESAFERELEASE(resource);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class D3D11Texture : public Texture {
|
||||
public:
|
||||
D3D11Texture(D3D11TextureCache* cache, uint32_t address);
|
||||
virtual ~D3D11Texture();
|
||||
|
||||
TextureView* Fetch(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch) override;
|
||||
|
||||
protected:
|
||||
bool FetchTexture1D(
|
||||
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
bool FetchTexture2D(
|
||||
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
bool FetchTexture3D(
|
||||
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
bool FetchTextureCube(
|
||||
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
|
||||
D3D11TextureCache* cache_;
|
||||
|
||||
// views
|
||||
};
|
||||
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_TEXTURE_H_
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/d3d11/d3d11_texture_cache.h>
|
||||
|
||||
#include <xenia/gpu/gpu-private.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
|
||||
|
||||
D3D11TextureCache::D3D11TextureCache(
|
||||
Memory* memory,
|
||||
ID3D11DeviceContext* context, ID3D11Device* device)
|
||||
: TextureCache(memory),
|
||||
context_(context), device_(device) {
|
||||
context_->AddRef();
|
||||
device_->AddRef();
|
||||
}
|
||||
|
||||
D3D11TextureCache::~D3D11TextureCache() {
|
||||
XESAFERELEASE(device_);
|
||||
XESAFERELEASE(context_);
|
||||
}
|
||||
|
||||
Texture* D3D11TextureCache::CreateTexture(
|
||||
uint32_t address, const xenos::xe_gpu_texture_fetch_t& fetch) {
|
||||
return new D3D11Texture(this, address);
|
||||
}
|
||||
|
||||
ID3D11SamplerState* D3D11TextureCache::GetSamplerState(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
const Shader::tex_buffer_desc_t& desc) {
|
||||
D3D11_SAMPLER_DESC sampler_desc;
|
||||
xe_zero_struct(&sampler_desc, sizeof(sampler_desc));
|
||||
uint32_t min_filter = desc.tex_fetch.min_filter == 3 ?
|
||||
fetch.min_filter : desc.tex_fetch.min_filter;
|
||||
uint32_t mag_filter = desc.tex_fetch.mag_filter == 3 ?
|
||||
fetch.mag_filter : desc.tex_fetch.mag_filter;
|
||||
uint32_t mip_filter = desc.tex_fetch.mip_filter == 3 ?
|
||||
fetch.mip_filter : desc.tex_fetch.mip_filter;
|
||||
// MIN, MAG, MIP
|
||||
static const D3D11_FILTER filter_matrix[2][2][3] = {
|
||||
{
|
||||
// min = POINT
|
||||
{
|
||||
// mag = POINT
|
||||
D3D11_FILTER_MIN_MAG_MIP_POINT,
|
||||
D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, // basemap?
|
||||
},
|
||||
{
|
||||
// mag = LINEAR
|
||||
D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
|
||||
D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR, // basemap?
|
||||
},
|
||||
},
|
||||
{
|
||||
// min = LINEAR
|
||||
{
|
||||
// mag = POINT
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT,
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, // basemap?
|
||||
},
|
||||
{
|
||||
// mag = LINEAR
|
||||
D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
||||
D3D11_FILTER_MIN_MAG_MIP_LINEAR,
|
||||
D3D11_FILTER_MIN_MAG_MIP_LINEAR, // basemap?
|
||||
},
|
||||
},
|
||||
};
|
||||
sampler_desc.Filter = filter_matrix[min_filter][mag_filter][mip_filter];
|
||||
static const D3D11_TEXTURE_ADDRESS_MODE mode_map[] = {
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR_ONCE, // ?
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR_ONCE, // ?
|
||||
D3D11_TEXTURE_ADDRESS_BORDER, // ?
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR, // ?
|
||||
};
|
||||
sampler_desc.AddressU = mode_map[fetch.clamp_x];
|
||||
sampler_desc.AddressV = mode_map[fetch.clamp_y];
|
||||
sampler_desc.AddressW = mode_map[fetch.clamp_z];
|
||||
sampler_desc.MipLODBias;
|
||||
sampler_desc.MaxAnisotropy = 1;
|
||||
sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
sampler_desc.BorderColor[0];
|
||||
sampler_desc.BorderColor[1];
|
||||
sampler_desc.BorderColor[2];
|
||||
sampler_desc.BorderColor[3];
|
||||
sampler_desc.MinLOD;
|
||||
sampler_desc.MaxLOD;
|
||||
ID3D11SamplerState* sampler_state = NULL;
|
||||
HRESULT hr = device_->CreateSamplerState(&sampler_desc, &sampler_state);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: unable to create sampler state");
|
||||
return nullptr;
|
||||
}
|
||||
return sampler_state;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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_D3D11_D3D11_TEXTURE_CACHE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_TEXTURE_CACHE_H_
|
||||
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/gpu/texture_cache.h>
|
||||
#include <xenia/gpu/shader.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_texture.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
|
||||
class D3D11TextureCache : public TextureCache {
|
||||
public:
|
||||
D3D11TextureCache(Memory* memory,
|
||||
ID3D11DeviceContext* context, ID3D11Device* device);
|
||||
virtual ~D3D11TextureCache();
|
||||
|
||||
ID3D11DeviceContext* context() const { return context_; }
|
||||
ID3D11Device* device() const { return device_; }
|
||||
|
||||
ID3D11SamplerState* GetSamplerState(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch,
|
||||
const Shader::tex_buffer_desc_t& desc);
|
||||
|
||||
protected:
|
||||
Texture* CreateTexture(uint32_t address,
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch) override;
|
||||
|
||||
private:
|
||||
ID3D11DeviceContext* context_;
|
||||
ID3D11Device* device_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_TEXTURE_CACHE_H_
|
|
@ -16,6 +16,10 @@
|
|||
'd3d11_shader.h',
|
||||
'd3d11_shader_cache.cc',
|
||||
'd3d11_shader_cache.h',
|
||||
'd3d11_texture.cc',
|
||||
'd3d11_texture.h',
|
||||
'd3d11_texture_cache.cc',
|
||||
'd3d11_texture_cache.h',
|
||||
'd3d11_window.cc',
|
||||
'd3d11_window.h',
|
||||
],
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
'shader.h',
|
||||
'shader_cache.cc',
|
||||
'shader_cache.h',
|
||||
'texture.cc',
|
||||
'texture.h',
|
||||
'texture_cache.cc',
|
||||
'texture_cache.h',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/texture.h>
|
||||
|
||||
#include <xenia/gpu/xenos/ucode.h>
|
||||
#include <xenia/gpu/xenos/xenos.h>
|
||||
|
||||
// TODO(benvanik): replace DXGI constants with xenia constants.
|
||||
#include <d3d11.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
|
||||
Texture::Texture(uint32_t address)
|
||||
: address_(address) {
|
||||
}
|
||||
|
||||
bool Texture::FillViewInfo(TextureView* view,
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch) {
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/cc308051(v=vs.85).aspx
|
||||
// a2xx_sq_surfaceformat
|
||||
|
||||
view->dimensions = fetch.dimension;
|
||||
switch (fetch.dimension) {
|
||||
case DIMENSION_1D:
|
||||
view->width = fetch.size_1d.width;
|
||||
break;
|
||||
case DIMENSION_2D:
|
||||
view->width = fetch.size_2d.width;
|
||||
view->height = fetch.size_2d.height;
|
||||
break;
|
||||
case DIMENSION_3D:
|
||||
view->width = fetch.size_3d.width;
|
||||
view->height = fetch.size_3d.height;
|
||||
view->depth = fetch.size_3d.depth;
|
||||
break;
|
||||
case DIMENSION_CUBE:
|
||||
view->width = fetch.size_stack.width;
|
||||
view->height = fetch.size_stack.height;
|
||||
view->depth = fetch.size_stack.depth;
|
||||
break;
|
||||
}
|
||||
view->format = DXGI_FORMAT_UNKNOWN;
|
||||
view->block_size = 0;
|
||||
view->texel_pitch = 0;
|
||||
view->is_compressed = false;
|
||||
switch (fetch.format) {
|
||||
case FMT_8:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RRR1:
|
||||
view->format = DXGI_FORMAT_R8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_000R:
|
||||
view->format = DXGI_FORMAT_A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_8");
|
||||
view->format = DXGI_FORMAT_A8_UNORM;
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 1;
|
||||
break;
|
||||
case FMT_1_5_5_5:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
view->format = DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_1_5_5_5");
|
||||
view->format = DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 2;
|
||||
break;
|
||||
case FMT_8_8_8_8:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RGBA:
|
||||
view->format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
view->format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_RGB1:
|
||||
view->format = DXGI_FORMAT_R8G8B8A8_UNORM; // ?
|
||||
break;
|
||||
case XE_GPU_SWIZZLE_BGR1:
|
||||
view->format = DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_8_8_8_8");
|
||||
view->format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 4;
|
||||
break;
|
||||
case FMT_4_4_4_4:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_BGRA:
|
||||
view->format = DXGI_FORMAT_B4G4R4A4_UNORM; // only supported on Windows 8+
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_4_4_4_4");
|
||||
view->format = DXGI_FORMAT_B4G4R4A4_UNORM; // only supported on Windows 8+
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 2;
|
||||
break;
|
||||
case FMT_16_16_16_16_FLOAT:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_RGBA:
|
||||
view->format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_16_16_16_16_FLOAT");
|
||||
view->format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 8;
|
||||
break;
|
||||
case FMT_32_FLOAT:
|
||||
switch (fetch.swizzle) {
|
||||
case XE_GPU_SWIZZLE_R111:
|
||||
view->format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
default:
|
||||
XELOGW("D3D11: unhandled swizzle for FMT_32_FLOAT");
|
||||
view->format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
}
|
||||
view->block_size = 1;
|
||||
view->texel_pitch = 4;
|
||||
break;
|
||||
case FMT_DXT1:
|
||||
view->format = DXGI_FORMAT_BC1_UNORM;
|
||||
view->block_size = 4;
|
||||
view->texel_pitch = 8;
|
||||
view->is_compressed = true;
|
||||
break;
|
||||
case FMT_DXT2_3:
|
||||
case FMT_DXT4_5:
|
||||
view->format = (fetch.format == FMT_DXT4_5 ? DXGI_FORMAT_BC3_UNORM : DXGI_FORMAT_BC2_UNORM);
|
||||
view->block_size = 4;
|
||||
view->texel_pitch = 16;
|
||||
view->is_compressed = true;
|
||||
break;
|
||||
case FMT_1_REVERSE:
|
||||
case FMT_1:
|
||||
case FMT_5_6_5:
|
||||
case FMT_6_5_5:
|
||||
case FMT_2_10_10_10:
|
||||
case FMT_8_A:
|
||||
case FMT_8_B:
|
||||
case FMT_8_8:
|
||||
case FMT_Cr_Y1_Cb_Y0:
|
||||
case FMT_Y1_Cr_Y0_Cb:
|
||||
case FMT_5_5_5_1:
|
||||
case FMT_8_8_8_8_A:
|
||||
case FMT_10_11_11:
|
||||
case FMT_11_11_10:
|
||||
case FMT_24_8:
|
||||
case FMT_24_8_FLOAT:
|
||||
case FMT_16:
|
||||
case FMT_16_16:
|
||||
case FMT_16_16_16_16:
|
||||
case FMT_16_EXPAND:
|
||||
case FMT_16_16_EXPAND:
|
||||
case FMT_16_16_16_16_EXPAND:
|
||||
case FMT_16_FLOAT:
|
||||
case FMT_16_16_FLOAT:
|
||||
case FMT_32:
|
||||
case FMT_32_32:
|
||||
case FMT_32_32_32_32:
|
||||
case FMT_32_32_FLOAT:
|
||||
case FMT_32_32_32_32_FLOAT:
|
||||
case FMT_32_AS_8:
|
||||
case FMT_32_AS_8_8:
|
||||
case FMT_16_MPEG:
|
||||
case FMT_16_16_MPEG:
|
||||
case FMT_8_INTERLACED:
|
||||
case FMT_32_AS_8_INTERLACED:
|
||||
case FMT_32_AS_8_8_INTERLACED:
|
||||
case FMT_16_INTERLACED:
|
||||
case FMT_16_MPEG_INTERLACED:
|
||||
case FMT_16_16_MPEG_INTERLACED:
|
||||
case FMT_DXN:
|
||||
case FMT_8_8_8_8_AS_16_16_16_16:
|
||||
case FMT_DXT1_AS_16_16_16_16:
|
||||
case FMT_DXT2_3_AS_16_16_16_16:
|
||||
case FMT_DXT4_5_AS_16_16_16_16:
|
||||
case FMT_2_10_10_10_AS_16_16_16_16:
|
||||
case FMT_10_11_11_AS_16_16_16_16:
|
||||
case FMT_11_11_10_AS_16_16_16_16:
|
||||
case FMT_32_32_32_FLOAT:
|
||||
case FMT_DXT3A:
|
||||
case FMT_DXT5A:
|
||||
case FMT_CTX1:
|
||||
case FMT_DXT3A_AS_1_1_1_1:
|
||||
view->format = DXGI_FORMAT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::TextureSwap(uint8_t* dest, const uint8_t* src, uint32_t pitch,
|
||||
XE_GPU_ENDIAN endianness) {
|
||||
switch (endianness) {
|
||||
case XE_GPU_ENDIAN_8IN16:
|
||||
for (uint32_t i = 0; i < pitch; i += 2, src += 2, dest += 2) {
|
||||
*(uint16_t*)dest = XESWAP16(*(uint16_t*)src);
|
||||
}
|
||||
break;
|
||||
case XE_GPU_ENDIAN_8IN32: // Swap bytes.
|
||||
for (uint32_t i = 0; i < pitch; i += 4, src += 4, dest += 4) {
|
||||
*(uint32_t*)dest = XESWAP32(*(uint32_t*)src);
|
||||
}
|
||||
break;
|
||||
case XE_GPU_ENDIAN_16IN32: // Swap half words.
|
||||
for (uint32_t i = 0; i < pitch; i += 4, src += 4, dest += 4) {
|
||||
uint32_t value = *(uint32_t*)src;
|
||||
*(uint32_t*)dest = ((value >> 16) & 0xFFFF) | (value << 16);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case XE_GPU_ENDIAN_NONE:
|
||||
memcpy(dest, src, pitch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// https://code.google.com/p/crunch/source/browse/trunk/inc/crn_decomp.h#4104
|
||||
uint32_t Texture::TiledOffset2DOuter(uint32_t y, uint32_t width,
|
||||
uint32_t log_bpp) {
|
||||
uint32_t macro = ((y >> 5) * (width >> 5)) << (log_bpp + 7);
|
||||
uint32_t micro = ((y & 6) << 2) << log_bpp;
|
||||
return macro +
|
||||
((micro & ~15) << 1) +
|
||||
(micro & 15) +
|
||||
((y & 8) << (3 + log_bpp)) +
|
||||
((y & 1) << 4);
|
||||
}
|
||||
|
||||
uint32_t Texture::TiledOffset2DInner(uint32_t x, uint32_t y, uint32_t bpp,
|
||||
uint32_t base_offset) {
|
||||
uint32_t macro = (x >> 5) << (bpp + 7);
|
||||
uint32_t micro = (x & 7) << bpp;
|
||||
uint32_t offset = base_offset + (macro + ((micro & ~15) << 1) + (micro & 15));
|
||||
return ((offset & ~511) << 3) + ((offset & 448) << 2) + (offset & 63) +
|
||||
((y & 16) << 7) + (((((y & 8) >> 2) + (x >> 3)) & 3) << 6);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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_TEXTURE_H_
|
||||
#define XENIA_GPU_TEXTURE_H_
|
||||
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/gpu/xenos/xenos.h>
|
||||
|
||||
// TODO(benvanik): replace DXGI constants with xenia constants.
|
||||
#include <d3d11.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
|
||||
class Texture;
|
||||
|
||||
|
||||
struct TextureView {
|
||||
Texture* texture;
|
||||
int dimensions;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
uint32_t block_size;
|
||||
uint32_t texel_pitch;
|
||||
bool is_compressed;
|
||||
DXGI_FORMAT format;
|
||||
|
||||
TextureView()
|
||||
: texture(nullptr),
|
||||
dimensions(0),
|
||||
width(0), height(0), depth(0),
|
||||
block_size(0), texel_pitch(0),
|
||||
is_compressed(false), format(DXGI_FORMAT_UNKNOWN) {}
|
||||
};
|
||||
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
Texture(uint32_t address);
|
||||
virtual ~Texture() = default;
|
||||
|
||||
virtual TextureView* Fetch(
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch) = 0;
|
||||
|
||||
protected:
|
||||
bool FillViewInfo(TextureView* view,
|
||||
const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
|
||||
static void TextureSwap(uint8_t* dest, const uint8_t* src, uint32_t pitch,
|
||||
xenos::XE_GPU_ENDIAN endianness);
|
||||
static uint32_t TiledOffset2DOuter(uint32_t y, uint32_t width,
|
||||
uint32_t log_bpp);
|
||||
static uint32_t TiledOffset2DInner(uint32_t x, uint32_t y, uint32_t bpp,
|
||||
uint32_t base_offset);
|
||||
|
||||
uint32_t address_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_GPU_TEXTURE_H_
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/texture_cache.h>
|
||||
|
||||
#include <xenia/gpu/xenos/ucode.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
|
||||
// https://github.com/ivmai/bdwgc/blob/master/os_dep.c
|
||||
|
||||
TextureCache::TextureCache(Memory* memory)
|
||||
: memory_(memory) {
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() {
|
||||
// textures
|
||||
}
|
||||
|
||||
TextureView* TextureCache::FetchTexture(
|
||||
uint32_t address, const xenos::xe_gpu_texture_fetch_t& fetch) {
|
||||
auto it = textures_.find(address);
|
||||
if (it == textures_.end()) {
|
||||
// Texture not found.
|
||||
auto texture = CreateTexture(address, fetch);
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
textures_.insert({ address, texture });
|
||||
return texture->Fetch(fetch);
|
||||
} else {
|
||||
// Texture found.
|
||||
return it->second->Fetch(fetch);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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_TEXTURE_CACHE_H_
|
||||
#define XENIA_GPU_TEXTURE_CACHE_H_
|
||||
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/gpu/texture.h>
|
||||
#include <xenia/gpu/xenos/xenos.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
|
||||
// TODO(benvanik): overlapping textures.
|
||||
// TODO(benvanik): multiple textures (differing formats/etc) per address.
|
||||
class TextureCache {
|
||||
public:
|
||||
TextureCache(Memory* memory);
|
||||
virtual ~TextureCache();
|
||||
|
||||
Memory* memory() const { return memory_; }
|
||||
|
||||
TextureView* FetchTexture(
|
||||
uint32_t address, const xenos::xe_gpu_texture_fetch_t& fetch);
|
||||
|
||||
protected:
|
||||
virtual Texture* CreateTexture(
|
||||
uint32_t address, const xenos::xe_gpu_texture_fetch_t& fetch) = 0;
|
||||
|
||||
Memory* memory_;
|
||||
|
||||
// Mapped by guest address.
|
||||
std::unordered_map<uint32_t, Texture*> textures_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_GPU_TEXTURE_CACHE_H_
|
Loading…
Reference in New Issue