Initial refactoring of gpu/.

Runs too fast - now there are ringbuffer wrapping issues.
This commit is contained in:
Ben Vanik
2014-06-08 11:23:55 -07:00
parent 4072640a64
commit 295910c3d8
70 changed files with 5923 additions and 6095 deletions

View File

@@ -1,150 +0,0 @@
/**
******************************************************************************
* 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_buffer.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_buffer_cache.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11IndexBuffer::D3D11IndexBuffer(
D3D11BufferCache* buffer_cache,
const IndexBufferInfo& info,
const uint8_t* src_ptr, size_t length)
: IndexBuffer(info, src_ptr, length),
buffer_cache_(buffer_cache),
handle_(nullptr) {
}
D3D11IndexBuffer::~D3D11IndexBuffer() {
XESAFERELEASE(handle_);
}
bool D3D11IndexBuffer::FetchNew(uint64_t hash) {
hash_ = hash;
D3D11_BUFFER_DESC buffer_desc;
xe_zero_struct(&buffer_desc, sizeof(buffer_desc));
buffer_desc.ByteWidth = info_.index_size;
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr = buffer_cache_->device()->CreateBuffer(&buffer_desc, NULL, &handle_);
if (FAILED(hr)) {
XELOGW("D3D11: failed to create index buffer");
return false;
}
return FetchDirty(hash);
}
bool D3D11IndexBuffer::FetchDirty(uint64_t hash) {
hash_ = hash;
// All that's done so far:
XEASSERT(info_.endianness == 0x2);
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = buffer_cache_->context()->Map(
handle_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: unable to map index buffer");
return false;
}
if (info_.index_32bit) {
const uint32_t* src = reinterpret_cast<const uint32_t*>(src_);
uint32_t* dest = reinterpret_cast<uint32_t*>(res.pData);
for (uint32_t n = 0; n < info_.index_count; n++) {
uint32_t d = { XESWAP32(src[n]) };
dest[n] = d;
}
} else {
const uint16_t* src = reinterpret_cast<const uint16_t*>(src_);
uint16_t* dest = reinterpret_cast<uint16_t*>(res.pData);
for (uint32_t n = 0; n < info_.index_count; n++) {
uint16_t d = XESWAP16(src[n]);
dest[n] = d;
}
}
buffer_cache_->context()->Unmap(handle_, 0);
return true;
}
D3D11VertexBuffer::D3D11VertexBuffer(
D3D11BufferCache* buffer_cache,
const VertexBufferInfo& info,
const uint8_t* src_ptr, size_t length)
: VertexBuffer(info, src_ptr, length),
buffer_cache_(buffer_cache),
handle_(nullptr) {
}
D3D11VertexBuffer::~D3D11VertexBuffer() {
XESAFERELEASE(handle_);
}
bool D3D11VertexBuffer::FetchNew(uint64_t hash) {
hash_ = hash;
D3D11_BUFFER_DESC buffer_desc;
xe_zero_struct(&buffer_desc, sizeof(buffer_desc));
buffer_desc.ByteWidth = static_cast<UINT>(length_);
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr = buffer_cache_->device()->CreateBuffer(&buffer_desc, NULL, &handle_);
if (FAILED(hr)) {
XELOGW("D3D11: failed to create index buffer");
return false;
}
return FetchDirty(hash);
}
bool D3D11VertexBuffer::FetchDirty(uint64_t hash) {
hash_ = hash;
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = buffer_cache_->context()->Map(
handle_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: unable to map vertex buffer");
return false;
}
uint8_t* dest = reinterpret_cast<uint8_t*>(res.pData);
// TODO(benvanik): rewrite to be faster/special case common/etc
uint32_t stride = info_.layout.stride_words;
size_t count = (length_ / 4) / stride;
for (size_t n = 0; n < info_.layout.element_count; n++) {
const auto& el = info_.layout.elements[n];
const uint32_t* src_ptr = (const uint32_t*)(src_ + el.offset_words * 4);
uint32_t* dest_ptr = (uint32_t*)(dest + el.offset_words * 4);
uint32_t o = 0;
for (uint32_t i = 0; i < count; i++) {
for (uint32_t j = 0; j < el.size_words; j++) {
dest_ptr[o + j] = XESWAP32(src_ptr[o + j]);
}
o += stride;
}
}
buffer_cache_->context()->Unmap(handle_, 0);
return true;
}

View File

@@ -1,69 +0,0 @@
/**
******************************************************************************
* 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_BUFFER_H_
#define XENIA_GPU_D3D11_D3D11_BUFFER_H_
#include <xenia/core.h>
#include <xenia/gpu/buffer.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11BufferCache;
class D3D11IndexBuffer : public IndexBuffer {
public:
D3D11IndexBuffer(D3D11BufferCache* buffer_cache,
const IndexBufferInfo& info,
const uint8_t* src_ptr, size_t length);
virtual ~D3D11IndexBuffer();
ID3D11Buffer* handle() const { return handle_; }
bool FetchNew(uint64_t hash) override;
bool FetchDirty(uint64_t hash) override;
private:
D3D11BufferCache* buffer_cache_;
ID3D11Buffer* handle_;
};
class D3D11VertexBuffer : public VertexBuffer {
public:
D3D11VertexBuffer(D3D11BufferCache* buffer_cache,
const VertexBufferInfo& info,
const uint8_t* src_ptr, size_t length);
virtual ~D3D11VertexBuffer();
ID3D11Buffer* handle() const { return handle_; }
bool FetchNew(uint64_t hash) override;
bool FetchDirty(uint64_t hash) override;
private:
D3D11BufferCache* buffer_cache_;
ID3D11Buffer* handle_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_BUFFER_H_

View File

@@ -1,44 +0,0 @@
/**
******************************************************************************
* 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_buffer_cache.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_buffer.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11BufferCache::D3D11BufferCache(ID3D11DeviceContext* context,
ID3D11Device* device)
: context_(context), device_(device) {
context->AddRef();
device_->AddRef();
}
D3D11BufferCache::~D3D11BufferCache() {
XESAFERELEASE(device_);
XESAFERELEASE(context_);
}
IndexBuffer* D3D11BufferCache::CreateIndexBuffer(
const IndexBufferInfo& info,
const uint8_t* src_ptr, size_t length) {
return new D3D11IndexBuffer(this, info, src_ptr, length);
}
VertexBuffer* D3D11BufferCache::CreateVertexBuffer(
const VertexBufferInfo& info,
const uint8_t* src_ptr, size_t length) {
return new D3D11VertexBuffer(this, info, src_ptr, length);
}

View File

@@ -1,53 +0,0 @@
/**
******************************************************************************
* 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_BUFFER_CACHE_H_
#define XENIA_GPU_D3D11_D3D11_BUFFER_CACHE_H_
#include <xenia/core.h>
#include <xenia/gpu/buffer_cache.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11BufferCache : public BufferCache {
public:
D3D11BufferCache(ID3D11DeviceContext* context, ID3D11Device* device);
virtual ~D3D11BufferCache();
ID3D11DeviceContext* context() const { return context_; }
ID3D11Device* device() const { return device_; }
protected:
IndexBuffer* CreateIndexBuffer(
const IndexBufferInfo& info,
const uint8_t* src_ptr, size_t length) override;
VertexBuffer* CreateVertexBuffer(
const VertexBufferInfo& info,
const uint8_t* src_ptr, size_t length) override;
protected:
ID3D11DeviceContext* context_;
ID3D11Device* device_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_BUFFER_CACHE_H_

View File

@@ -0,0 +1,149 @@
/**
******************************************************************************
* 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_buffer_resource.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11IndexBufferResource::D3D11IndexBufferResource(
D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info)
: IndexBufferResource(memory_range, info),
resource_cache_(resource_cache),
handle_(nullptr) {
}
D3D11IndexBufferResource::~D3D11IndexBufferResource() {
XESAFERELEASE(handle_);
}
int D3D11IndexBufferResource::CreateHandle() {
D3D11_BUFFER_DESC buffer_desc;
xe_zero_struct(&buffer_desc, sizeof(buffer_desc));
buffer_desc.ByteWidth = static_cast<UINT>(memory_range_.length);
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr = resource_cache_->device()->CreateBuffer(
&buffer_desc, nullptr, &handle_);
if (FAILED(hr)) {
XELOGW("D3D11: failed to create index buffer");
return 1;
}
return 0;
}
int D3D11IndexBufferResource::InvalidateRegion(
const MemoryRange& memory_range) {
SCOPE_profile_cpu_f("gpu");
// All that's done so far:
XEASSERT(info_.endianness == 0x2);
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = resource_cache_->context()->Map(
handle_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: unable to map index buffer");
return 1;
}
if (info_.format == INDEX_FORMAT_32BIT) {
uint32_t index_count = memory_range_.length / 4;
const uint32_t* src = reinterpret_cast<const uint32_t*>(
memory_range_.host_base);
uint32_t* dest = reinterpret_cast<uint32_t*>(res.pData);
for (uint32_t n = 0; n < index_count; n++) {
dest[n] = XESWAP32(src[n]);
}
} else {
uint32_t index_count = memory_range_.length / 2;
const uint16_t* src = reinterpret_cast<const uint16_t*>(
memory_range_.host_base);
uint16_t* dest = reinterpret_cast<uint16_t*>(res.pData);
for (uint32_t n = 0; n < index_count; n++) {
dest[n] = XESWAP16(src[n]);
}
}
resource_cache_->context()->Unmap(handle_, 0);
return 0;
}
D3D11VertexBufferResource::D3D11VertexBufferResource(
D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info)
: VertexBufferResource(memory_range, info),
resource_cache_(resource_cache),
handle_(nullptr) {
}
D3D11VertexBufferResource::~D3D11VertexBufferResource() {
XESAFERELEASE(handle_);
}
int D3D11VertexBufferResource::CreateHandle() {
D3D11_BUFFER_DESC buffer_desc;
xe_zero_struct(&buffer_desc, sizeof(buffer_desc));
buffer_desc.ByteWidth = static_cast<UINT>(memory_range_.length);
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr = resource_cache_->device()->CreateBuffer(
&buffer_desc, nullptr, &handle_);
if (FAILED(hr)) {
XELOGW("D3D11: failed to create vertex buffer");
return 1;
}
return 0;
}
int D3D11VertexBufferResource::InvalidateRegion(
const MemoryRange& memory_range) {
SCOPE_profile_cpu_f("gpu");
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = resource_cache_->context()->Map(
handle_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: unable to map vertex buffer");
return 1;
}
uint8_t* dest = reinterpret_cast<uint8_t*>(res.pData);
// TODO(benvanik): rewrite to be faster/special case common/etc
uint32_t stride = info_.stride_words;
size_t count = (memory_range_.length / 4) / stride;
for (size_t n = 0; n < info_.element_count; n++) {
const auto& el = info_.elements[n];
const uint32_t* src_ptr = (const uint32_t*)(
memory_range_.host_base + el.offset_words * 4);
uint32_t* dest_ptr = (uint32_t*)(dest + el.offset_words * 4);
uint32_t o = 0;
for (uint32_t i = 0; i < count; i++) {
for (uint32_t j = 0; j < el.size_words; j++) {
dest_ptr[o + j] = XESWAP32(src_ptr[o + j]);
}
o += stride;
}
}
resource_cache_->context()->Unmap(handle_, 0);
return 0;
}

View File

@@ -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_BUFFER_RESOURCE_H_
#define XENIA_GPU_D3D11_D3D11_BUFFER_RESOURCE_H_
#include <xenia/gpu/buffer_resource.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ResourceCache;
class D3D11IndexBufferResource : public IndexBufferResource {
public:
D3D11IndexBufferResource(D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info);
~D3D11IndexBufferResource() override;
void* handle() const override { return handle_; }
protected:
int CreateHandle() override;
int InvalidateRegion(const MemoryRange& memory_range) override;
private:
D3D11ResourceCache* resource_cache_;
ID3D11Buffer* handle_;
};
class D3D11VertexBufferResource : public VertexBufferResource {
public:
D3D11VertexBufferResource(D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info);
~D3D11VertexBufferResource() override;
void* handle() const override { return handle_; }
protected:
int CreateHandle() override;
int InvalidateRegion(const MemoryRange& memory_range) override;
private:
D3D11ResourceCache* resource_cache_;
ID3D11Buffer* handle_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_BUFFER_RESOURCE_H_

View File

@@ -10,7 +10,8 @@
#include <xenia/gpu/d3d11/d3d11_geometry_shader.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_shader.h>
#include <xenia/gpu/d3d11/d3d11_shader_resource.h>
#include <xenia/gpu/d3d11/d3d11_shader_translator.h>
#include <xenia/gpu/xenos/ucode.h>
#include <d3dcompiler.h>
@@ -22,8 +23,8 @@ using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11GeometryShader::D3D11GeometryShader(ID3D11Device* device, uint64_t hash) :
hash_(hash), handle_(NULL) {
D3D11GeometryShader::D3D11GeometryShader(ID3D11Device* device)
: handle_(nullptr) {
device_ = device;
device_->AddRef();
}
@@ -33,7 +34,7 @@ D3D11GeometryShader::~D3D11GeometryShader() {
XESAFERELEASE(device_);
}
int D3D11GeometryShader::Prepare(D3D11VertexShader* vertex_shader) {
int D3D11GeometryShader::Prepare(D3D11VertexShaderResource* vertex_shader) {
SCOPE_profile_cpu_f("gpu");
if (handle_) {
@@ -94,11 +95,12 @@ ID3D10Blob* D3D11GeometryShader::Compile(const char* shader_source) {
if (FLAGS_dump_shaders.size()) {
base_path = FLAGS_dump_shaders.c_str();
}
uint64_t hash = xe_hash64(shader_source, xestrlena(shader_source)); // ?
char file_name[XE_MAX_PATH];
xesnprintfa(file_name, XECOUNT(file_name),
"%s/gen_%.16llX.gs",
base_path,
hash_);
hash);
if (FLAGS_dump_shaders.size()) {
FILE* f = fopen(file_name, "w");
@@ -128,7 +130,7 @@ ID3D10Blob* D3D11GeometryShader::Compile(const char* shader_source) {
return shader_blob;
}
int D3D11GeometryShader::Generate(D3D11VertexShader* vertex_shader,
int D3D11GeometryShader::Generate(D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) {
output->Append(
"struct VERTEX {\n"
@@ -138,7 +140,7 @@ int D3D11GeometryShader::Generate(D3D11VertexShader* vertex_shader,
// TODO(benvanik): only add used ones?
output->Append(
" float4 o[%d] : XE_O;\n",
D3D11Shader::MAX_INTERPOLATORS);
D3D11ShaderTranslator::kMaxInterpolators);
}
if (alloc_counts.point_size) {
output->Append(
@@ -156,15 +158,15 @@ int D3D11GeometryShader::Generate(D3D11VertexShader* vertex_shader,
D3D11PointSpriteGeometryShader::D3D11PointSpriteGeometryShader(
ID3D11Device* device, uint64_t hash) :
D3D11GeometryShader(device, hash) {
ID3D11Device* device) : D3D11GeometryShader(device) {
}
D3D11PointSpriteGeometryShader::~D3D11PointSpriteGeometryShader() {
}
int D3D11PointSpriteGeometryShader::Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output) {
int D3D11PointSpriteGeometryShader::Generate(
D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) {
SCOPE_profile_cpu_f("gpu");
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
return 1;
@@ -211,15 +213,15 @@ int D3D11PointSpriteGeometryShader::Generate(D3D11VertexShader* vertex_shader,
D3D11RectListGeometryShader::D3D11RectListGeometryShader(
ID3D11Device* device, uint64_t hash) :
D3D11GeometryShader(device, hash) {
ID3D11Device* device) : D3D11GeometryShader(device) {
}
D3D11RectListGeometryShader::~D3D11RectListGeometryShader() {
}
int D3D11RectListGeometryShader::Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output) {
int D3D11RectListGeometryShader::Generate(
D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) {
SCOPE_profile_cpu_f("gpu");
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
return 1;
@@ -256,15 +258,15 @@ int D3D11RectListGeometryShader::Generate(D3D11VertexShader* vertex_shader,
D3D11QuadListGeometryShader::D3D11QuadListGeometryShader(
ID3D11Device* device, uint64_t hash) :
D3D11GeometryShader(device, hash) {
ID3D11Device* device) : D3D11GeometryShader(device) {
}
D3D11QuadListGeometryShader::~D3D11QuadListGeometryShader() {
}
int D3D11QuadListGeometryShader::Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output) {
int D3D11QuadListGeometryShader::Generate(
D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) {
SCOPE_profile_cpu_f("gpu");
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
return 1;

View File

@@ -21,7 +21,7 @@ namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11VertexShader;
class D3D11VertexShaderResource;
class D3D11GeometryShader {
@@ -30,53 +30,52 @@ public:
ID3D11GeometryShader* handle() const { return handle_; }
int Prepare(D3D11VertexShader* vertex_shader);
int Prepare(D3D11VertexShaderResource* vertex_shader);
protected:
D3D11GeometryShader(ID3D11Device* device, uint64_t hash);
D3D11GeometryShader(ID3D11Device* device);
ID3D10Blob* Compile(const char* shader_source);
virtual int Generate(D3D11VertexShader* vertex_shader,
virtual int Generate(D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output);
protected:
ID3D11Device* device_;
uint64_t hash_;
ID3D11GeometryShader* handle_;
};
class D3D11PointSpriteGeometryShader : public D3D11GeometryShader {
public:
D3D11PointSpriteGeometryShader(ID3D11Device* device, uint64_t hash);
virtual ~D3D11PointSpriteGeometryShader();
D3D11PointSpriteGeometryShader(ID3D11Device* device);
~D3D11PointSpriteGeometryShader() override;
protected:
virtual int Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output);
int Generate(D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) override;
};
class D3D11RectListGeometryShader : public D3D11GeometryShader {
public:
D3D11RectListGeometryShader(ID3D11Device* device, uint64_t hash);
virtual ~D3D11RectListGeometryShader();
D3D11RectListGeometryShader(ID3D11Device* device);
~D3D11RectListGeometryShader() override;
protected:
virtual int Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output);
int Generate(D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) override;
};
class D3D11QuadListGeometryShader : public D3D11GeometryShader {
public:
D3D11QuadListGeometryShader(ID3D11Device* device, uint64_t hash);
virtual ~D3D11QuadListGeometryShader();
D3D11QuadListGeometryShader(ID3D11Device* device);
~D3D11QuadListGeometryShader() override;
protected:
virtual int Generate(D3D11VertexShader* vertex_shader,
alloy::StringBuffer* output);
int Generate(D3D11VertexShaderResource* vertex_shader,
alloy::StringBuffer* output) override;
};

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,8 @@
#include <xenia/core.h>
#include <xenia/gpu/graphics_driver.h>
#include <xenia/gpu/shader.h>
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
@@ -24,13 +24,6 @@ namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11BufferCache;
class D3D11PixelShader;
class D3D11ShaderCache;
class D3D11TextureCache;
struct D3D11TextureView;
class D3D11VertexShader;
class D3D11GraphicsDriver : public GraphicsDriver {
public:
@@ -38,48 +31,32 @@ public:
Memory* memory, IDXGISwapChain* swap_chain, ID3D11Device* device);
virtual ~D3D11GraphicsDriver();
virtual void Initialize();
ResourceCache* resource_cache() const override { return resource_cache_; }
virtual void InvalidateState(
uint32_t mask);
virtual void SetShader(
xenos::XE_GPU_SHADER_TYPE type,
uint32_t address,
uint32_t start,
uint32_t length);
virtual void DrawIndexBuffer(
xenos::XE_GPU_PRIMITIVE_TYPE prim_type,
bool index_32bit, uint32_t index_count,
uint32_t index_base, uint32_t index_size, uint32_t endianness);
virtual void DrawIndexAuto(
xenos::XE_GPU_PRIMITIVE_TYPE prim_type,
uint32_t index_count);
int Initialize() override;
int Draw(const DrawCommand& command) override;
// TODO(benvanik): figure this out.
virtual int Resolve();
int Resolve() override;
private:
int SetupDraw(xenos::XE_GPU_PRIMITIVE_TYPE prim_type);
void InitializeInvalidTexture();
int UpdateState(const DrawCommand& command);
int SetupConstantBuffers(const DrawCommand& command);
int SetupShaders(const DrawCommand& command);
int SetupInputAssembly(const DrawCommand& command);
int SetupSamplers(const DrawCommand& command);
int RebuildRenderTargets(uint32_t width, uint32_t height);
int UpdateState(uint32_t state_overrides = 0);
int UpdateConstantBuffers();
int BindShaders();
int PrepareFetchers();
int PrepareVertexBuffer(Shader::vtx_buffer_desc_t& desc);
int PrepareTextureFetchers();
int PrepareTextureSampler(xenos::XE_GPU_SHADER_TYPE shader_type,
Shader::tex_buffer_desc_t& desc);
int PrepareIndexBuffer(
bool index_32bit, uint32_t index_count,
uint32_t index_base, uint32_t index_size, uint32_t endianness);
private:
IDXGISwapChain* swap_chain_;
ID3D11Device* device_;
ID3D11DeviceContext* context_;
D3D11BufferCache* buffer_cache_;
D3D11ShaderCache* shader_cache_;
D3D11TextureCache* texture_cache_;
D3D11ResourceCache* resource_cache_;
ID3D11ShaderResourceView* invalid_texture_view_;
ID3D11SamplerState* invalid_texture_sampler_state_;
@@ -97,9 +74,6 @@ private:
} render_targets_;
struct {
D3D11VertexShader* vertex_shader;
D3D11PixelShader* pixel_shader;
struct {
ID3D11Buffer* float_constants;
ID3D11Buffer* bool_constants;
@@ -107,17 +81,7 @@ private:
ID3D11Buffer* vs_consts;
ID3D11Buffer* gs_consts;
} constant_buffers;
struct {
bool enabled;
xenos::xe_gpu_texture_fetch_t fetch;
D3D11TextureView* view;
} texture_fetchers[32];
} state_;
enum StateOverrides {
STATE_OVERRIDE_DISABLE_CULLING = (1 << 0),
};
};

View File

@@ -146,12 +146,18 @@ void D3D11GraphicsSystem::Initialize() {
XEASSERTNULL(driver_);
driver_ = new D3D11GraphicsDriver(
memory_, window_->swap_chain(), device_);
if (driver_->Initialize()) {
XELOGE("Unable to initialize D3D11 driver");
return;
}
// Initial vsync kick.
DispatchInterruptCallback(0);
}
void D3D11GraphicsSystem::Pump() {
SCOPE_profile_cpu_f("gpu");
if (swap_pending_) {
swap_pending_ = false;

View File

@@ -0,0 +1,71 @@
/**
******************************************************************************
* 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_resource_cache.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_buffer_resource.h>
#include <xenia/gpu/d3d11/d3d11_sampler_state_resource.h>
#include <xenia/gpu/d3d11/d3d11_shader_resource.h>
#include <xenia/gpu/d3d11/d3d11_texture_resource.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
D3D11ResourceCache::D3D11ResourceCache(Memory* memory,
ID3D11Device* device,
ID3D11DeviceContext* context)
: ResourceCache(memory),
device_(device), context_(context) {
device_->AddRef();
context_->AddRef();
}
D3D11ResourceCache::~D3D11ResourceCache() {
XESAFERELEASE(device_);
XESAFERELEASE(context_);
}
VertexShaderResource* D3D11ResourceCache::CreateVertexShader(
const MemoryRange& memory_range,
const VertexShaderResource::Info& info) {
return new D3D11VertexShaderResource(this, memory_range, info);
}
PixelShaderResource* D3D11ResourceCache::CreatePixelShader(
const MemoryRange& memory_range,
const PixelShaderResource::Info& info) {
return new D3D11PixelShaderResource(this, memory_range, info);
}
TextureResource* D3D11ResourceCache::CreateTexture(
const MemoryRange& memory_range,
const TextureResource::Info& info) {
return new D3D11TextureResource(this, memory_range, info);
}
SamplerStateResource* D3D11ResourceCache::CreateSamplerState(
const SamplerStateResource::Info& info) {
return new D3D11SamplerStateResource(this, info);
}
IndexBufferResource* D3D11ResourceCache::CreateIndexBuffer(
const MemoryRange& memory_range,
const IndexBufferResource::Info& info) {
return new D3D11IndexBufferResource(this, memory_range, info);
}
VertexBufferResource* D3D11ResourceCache::CreateVertexBuffer(
const MemoryRange& memory_range,
const VertexBufferResource::Info& info) {
return new D3D11VertexBufferResource(this, memory_range, info);
}

View File

@@ -0,0 +1,64 @@
/**
******************************************************************************
* 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_RESOURCE_CACHE_H_
#define XENIA_GPU_D3D11_D3D11_RESOURCE_CACHE_H_
#include <xenia/core.h>
#include <xenia/gpu/resource_cache.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ResourceCache : public ResourceCache {
public:
D3D11ResourceCache(Memory* memory,
ID3D11Device* device, ID3D11DeviceContext* context);
virtual ~D3D11ResourceCache();
ID3D11Device* device() const { return device_; }
ID3D11DeviceContext* context() const { return context_; }
protected:
VertexShaderResource* CreateVertexShader(
const MemoryRange& memory_range,
const VertexShaderResource::Info& info) override;
PixelShaderResource* CreatePixelShader(
const MemoryRange& memory_range,
const PixelShaderResource::Info& info) override;
TextureResource* CreateTexture(
const MemoryRange& memory_range,
const TextureResource::Info& info) override;
SamplerStateResource* CreateSamplerState(
const SamplerStateResource::Info& info) override;
IndexBufferResource* CreateIndexBuffer(
const MemoryRange& memory_range,
const IndexBufferResource::Info& info) override;
VertexBufferResource* CreateVertexBuffer(
const MemoryRange& memory_range,
const VertexBufferResource::Info& info) override;
private:
ID3D11Device* device_;
ID3D11DeviceContext* context_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_RESOURCE_CACHE_H_

View File

@@ -7,53 +7,36 @@
******************************************************************************
*/
#include <xenia/gpu/d3d11/d3d11_texture_cache.h>
#include <xenia/gpu/d3d11/d3d11_sampler_state_resource.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
using namespace std;
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11TextureCache::D3D11TextureCache(
Memory* memory,
ID3D11DeviceContext* context, ID3D11Device* device)
: TextureCache(memory),
context_(context), device_(device) {
context_->AddRef();
device_->AddRef();
D3D11SamplerStateResource::D3D11SamplerStateResource(
D3D11ResourceCache* resource_cache, const Info& info)
: SamplerStateResource(info),
resource_cache_(resource_cache),
handle_(nullptr) {
}
D3D11TextureCache::~D3D11TextureCache() {
for (auto it = samplers_.begin(); it != samplers_.end(); ++it) {
auto& cached_state = it->second;
XESAFERELEASE(cached_state.state);
D3D11SamplerStateResource::~D3D11SamplerStateResource() {
XESAFERELEASE(handle_);
}
int D3D11SamplerStateResource::Prepare() {
if (handle_) {
return 0;
}
samplers_.clear();
XESAFERELEASE(device_);
XESAFERELEASE(context_);
}
Texture* D3D11TextureCache::CreateTexture(
uint32_t address, const uint8_t* host_address,
const xenos::xe_gpu_texture_fetch_t& fetch) {
return new D3D11Texture(this, address, host_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] = {
{
@@ -87,7 +70,8 @@ ID3D11SamplerState* D3D11TextureCache::GetSamplerState(
},
},
};
sampler_desc.Filter = filter_matrix[min_filter][mag_filter][mip_filter];
sampler_desc.Filter =
filter_matrix[info_.min_filter][info_.mag_filter][info_.mip_filter];
static const D3D11_TEXTURE_ADDRESS_MODE mode_map[] = {
D3D11_TEXTURE_ADDRESS_WRAP,
D3D11_TEXTURE_ADDRESS_MIRROR,
@@ -98,9 +82,9 @@ ID3D11SamplerState* D3D11TextureCache::GetSamplerState(
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.AddressU = mode_map[info_.clamp_u];
sampler_desc.AddressV = mode_map[info_.clamp_v];
sampler_desc.AddressW = mode_map[info_.clamp_w];
sampler_desc.MipLODBias;
sampler_desc.MaxAnisotropy = 1;
sampler_desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
@@ -111,29 +95,12 @@ ID3D11SamplerState* D3D11TextureCache::GetSamplerState(
sampler_desc.MinLOD;
sampler_desc.MaxLOD;
// TODO(benvanik): do this earlier without having to setup the whole struct?
size_t hash = hash_combine(
sampler_desc.Filter,
sampler_desc.AddressU,
sampler_desc.AddressV,
sampler_desc.AddressW);
auto range = samplers_.equal_range(hash);
for (auto it = range.first; it != range.second; ++it) {
const auto& cached_state = it->second;
// TODO(benvanik): faster compare?
if (memcmp(&sampler_desc, &cached_state.desc, sizeof(sampler_desc)) == 0) {
return cached_state.state;
}
}
ID3D11SamplerState* sampler_state = NULL;
HRESULT hr = device_->CreateSamplerState(&sampler_desc, &sampler_state);
HRESULT hr = resource_cache_->device()->CreateSamplerState(
&sampler_desc, &handle_);
if (FAILED(hr)) {
XELOGE("D3D11: unable to create sampler state");
return nullptr;
return 1;
}
samplers_.insert({ hash, { sampler_desc, sampler_state } });
return sampler_state;
return 0;
}

View File

@@ -0,0 +1,48 @@
/**
******************************************************************************
* 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_SAMPLER_STATE_RESOURCE_H_
#define XENIA_GPU_D3D11_D3D11_SAMPLER_STATE_RESOURCE_H_
#include <xenia/gpu/sampler_state_resource.h>
#include <xenia/gpu/xenos/ucode.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ResourceCache;
class D3D11SamplerStateResource : public SamplerStateResource {
public:
D3D11SamplerStateResource(D3D11ResourceCache* resource_cache,
const Info& info);
~D3D11SamplerStateResource() override;
void* handle() const override { return handle_; }
int Prepare() override;
protected:
D3D11ResourceCache* resource_cache_;
ID3D11SamplerState* handle_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_SAMPLER_STATE_RESOURCE_H_

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_D3D11_D3D11_SHADER_H_
#define XENIA_GPU_D3D11_D3D11_SHADER_H_
#include <xenia/core.h>
#include <xenia/gpu/shader.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
struct Output;
typedef struct {
Output* output;
xenos::XE_GPU_SHADER_TYPE type;
uint32_t tex_fetch_index;
} xe_gpu_translate_ctx_t;
class D3D11GeometryShader;
class D3D11Shader : public Shader {
public:
virtual ~D3D11Shader();
const static uint32_t MAX_INTERPOLATORS = 16;
protected:
D3D11Shader(
ID3D11Device* device,
xenos::XE_GPU_SHADER_TYPE type,
const uint8_t* src_ptr, size_t length,
uint64_t hash);
const char* translated_src() const { return translated_src_; }
void set_translated_src(char* value);
void AppendTextureHeader(Output* output);
int TranslateExec(
xe_gpu_translate_ctx_t& ctx, const xenos::instr_cf_exec_t& cf);
ID3D10Blob* Compile(const char* shader_source);
protected:
ID3D11Device* device_;
char* translated_src_;
};
class D3D11VertexShader : public D3D11Shader {
public:
D3D11VertexShader(
ID3D11Device* device,
const uint8_t* src_ptr, size_t length,
uint64_t hash);
virtual ~D3D11VertexShader();
ID3D11VertexShader* handle() const { return handle_; }
ID3D11InputLayout* input_layout() const { return input_layout_; }
int Prepare(xenos::xe_gpu_program_cntl_t* program_cntl);
enum GeometryShaderType {
POINT_SPRITE_SHADER,
RECT_LIST_SHADER,
QUAD_LIST_SHADER,
MAX_GEOMETRY_SHADER_TYPE,
};
int DemandGeometryShader(GeometryShaderType type,
D3D11GeometryShader** out_shader);
private:
const char* Translate(xenos::xe_gpu_program_cntl_t* program_cntl);
private:
ID3D11VertexShader* handle_;
ID3D11InputLayout* input_layout_;
D3D11GeometryShader* geometry_shaders_[MAX_GEOMETRY_SHADER_TYPE];
};
class D3D11PixelShader : public D3D11Shader {
public:
D3D11PixelShader(
ID3D11Device* device,
const uint8_t* src_ptr, size_t length,
uint64_t hash);
virtual ~D3D11PixelShader();
ID3D11PixelShader* handle() const { return handle_; }
int Prepare(xenos::xe_gpu_program_cntl_t* program_cntl,
D3D11VertexShader* input_shader);
private:
const char* Translate(xenos::xe_gpu_program_cntl_t* program_cntl,
D3D11VertexShader* input_shader);
private:
ID3D11PixelShader* handle_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_SHADER_H_

View File

@@ -1,45 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/gpu/d3d11/d3d11_shader_cache.h>
#include <xenia/gpu/d3d11/d3d11_shader.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11ShaderCache::D3D11ShaderCache(ID3D11Device* device) {
device_ = device;
device_->AddRef();
}
D3D11ShaderCache::~D3D11ShaderCache() {
device_->Release();
}
Shader* D3D11ShaderCache::CreateCore(
xenos::XE_GPU_SHADER_TYPE type,
const uint8_t* src_ptr, size_t length,
uint64_t hash) {
switch (type) {
case XE_GPU_SHADER_TYPE_VERTEX:
return new D3D11VertexShader(
device_, src_ptr, length, hash);
case XE_GPU_SHADER_TYPE_PIXEL:
return new D3D11PixelShader(
device_, src_ptr, length, hash);
default:
XEASSERTALWAYS();
return NULL;
}
}

View File

@@ -1,46 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_
#define XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_
#include <xenia/core.h>
#include <xenia/gpu/shader_cache.h>
#include <D3D11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ShaderCache : public ShaderCache {
public:
D3D11ShaderCache(ID3D11Device* device);
virtual ~D3D11ShaderCache();
protected:
Shader* CreateCore(
xenos::XE_GPU_SHADER_TYPE type,
const uint8_t* src_ptr, size_t length,
uint64_t hash) override;
protected:
ID3D11Device* device_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_

View File

@@ -0,0 +1,381 @@
/**
******************************************************************************
* 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_shader_resource.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_geometry_shader.h>
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
#include <xenia/gpu/d3d11/d3d11_shader_translator.h>
#include <xenia/gpu/xenos/ucode.h>
#include <d3dcompiler.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
namespace {
ID3D10Blob* D3D11ShaderCompile(XE_GPU_SHADER_TYPE type,
const char* shader_source,
const char* disasm_source) {
SCOPE_profile_cpu_f("gpu");
// TODO(benvanik): pick shared runtime mode defines.
D3D10_SHADER_MACRO defines[] = {
"TEST_DEFINE", "1",
0, 0,
};
uint32_t flags1 = 0;
flags1 |= D3D10_SHADER_DEBUG;
flags1 |= D3D10_SHADER_ENABLE_STRICTNESS;
uint32_t flags2 = 0;
// Create a name.
const char* base_path = "";
if (FLAGS_dump_shaders.size()) {
base_path = FLAGS_dump_shaders.c_str();
}
size_t hash = xe_hash64(disasm_source, xestrlena(disasm_source)); // ?
char file_name[XE_MAX_PATH];
xesnprintfa(file_name, XECOUNT(file_name),
"%s/gen_%.16llX.%s",
base_path,
hash,
type == XE_GPU_SHADER_TYPE_VERTEX ? "vs" : "ps");
if (FLAGS_dump_shaders.size()) {
FILE* f = fopen(file_name, "w");
fprintf(f, shader_source);
fprintf(f, "\n\n");
fprintf(f, "/*\n");
fprintf(f, disasm_source);
fprintf(f, " */\n");
fclose(f);
}
// Compile shader to bytecode blob.
ID3D10Blob* shader_blob = 0;
ID3D10Blob* error_blob = 0;
HRESULT hr = D3DCompile(
shader_source, strlen(shader_source),
file_name,
defines, nullptr,
"main",
type == XE_GPU_SHADER_TYPE_VERTEX ? "vs_5_0" : "ps_5_0",
flags1, flags2,
&shader_blob, &error_blob);
if (error_blob) {
char* msg = (char*)error_blob->GetBufferPointer();
XELOGE("D3D11: shader compile failed with %s", msg);
}
XESAFERELEASE(error_blob);
if (FAILED(hr)) {
return nullptr;
}
return shader_blob;
}
} // namespace
D3D11VertexShaderResource::D3D11VertexShaderResource(
D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info)
: VertexShaderResource(memory_range, info),
resource_cache_(resource_cache),
handle_(nullptr),
input_layout_(nullptr),
translated_src_(nullptr) {
xe_zero_struct(geometry_shaders_, sizeof(geometry_shaders_));
}
D3D11VertexShaderResource::~D3D11VertexShaderResource() {
XESAFERELEASE(handle_);
XESAFERELEASE(input_layout_);
for (int i = 0; i < XECOUNT(geometry_shaders_); ++i) {
delete geometry_shaders_[i];
}
xe_free(translated_src_);
}
int D3D11VertexShaderResource::Prepare(
const xe_gpu_program_cntl_t& program_cntl) {
SCOPE_profile_cpu_f("gpu");
if (is_prepared_ || handle_) {
return 0;
}
// TODO(benvanik): look in file based on hash/etc.
void* byte_code = NULL;
size_t byte_code_length = 0;
// Translate and compile source.
D3D11ShaderTranslator translator;
int ret = translator.TranslateVertexShader(this, program_cntl);
if (ret) {
XELOGE("D3D11: failed to translate vertex shader");
return ret;
}
translated_src_ = xestrdupa(translator.translated_src());
ID3D10Blob* shader_blob = D3D11ShaderCompile(
XE_GPU_SHADER_TYPE_VERTEX, translated_src_, disasm_src());
if (!shader_blob) {
return 1;
}
byte_code_length = shader_blob->GetBufferSize();
byte_code = xe_malloc(byte_code_length);
xe_copy_struct(
byte_code, shader_blob->GetBufferPointer(), byte_code_length);
XESAFERELEASE(shader_blob);
// Create shader.
HRESULT hr = resource_cache_->device()->CreateVertexShader(
byte_code, byte_code_length,
nullptr,
&handle_);
if (FAILED(hr)) {
XELOGE("D3D11: failed to create vertex shader");
xe_free(byte_code);
return 1;
}
// Create input layout.
ret = CreateInputLayout(byte_code, byte_code_length);
xe_free(byte_code);
if (ret) {
return 1;
}
is_prepared_ = true;
return 0;
}
int D3D11VertexShaderResource::CreateInputLayout(const void* byte_code,
size_t byte_code_length) {
size_t element_count = 0;
const auto& inputs = buffer_inputs();
for (uint32_t n = 0; n < inputs.count; n++) {
element_count += inputs.descs[n].info.element_count;
}
if (!element_count) {
XELOGW("D3D11: vertex shader with zero inputs -- retaining previous values?");
input_layout_ = NULL;
return 0;
}
D3D11_INPUT_ELEMENT_DESC* element_descs =
(D3D11_INPUT_ELEMENT_DESC*)xe_alloca(
sizeof(D3D11_INPUT_ELEMENT_DESC) * element_count);
uint32_t el_index = 0;
for (uint32_t n = 0; n < inputs.count; n++) {
const auto& input = inputs.descs[n];
for (uint32_t m = 0; m < input.info.element_count; m++) {
const auto& el = input.info.elements[m];
uint32_t vb_slot = input.input_index;
DXGI_FORMAT vtx_format;
switch (el.format) {
case FMT_8_8_8_8:
if (el.is_normalized) {
vtx_format = el.is_signed ?
DXGI_FORMAT_R8G8B8A8_SNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
} else {
vtx_format = el.is_signed ?
DXGI_FORMAT_R8G8B8A8_SINT : DXGI_FORMAT_R8G8B8A8_UINT;
}
break;
case FMT_2_10_10_10:
if (el.is_normalized) {
vtx_format = DXGI_FORMAT_R10G10B10A2_UNORM;
} else {
vtx_format = DXGI_FORMAT_R10G10B10A2_UINT;
}
break;
// DXGI_FORMAT_R11G11B10_FLOAT?
case FMT_16_16:
if (el.is_normalized) {
vtx_format = el.is_signed ?
DXGI_FORMAT_R16G16_SNORM : DXGI_FORMAT_R16G16_UNORM;
} else {
vtx_format = el.is_signed ?
DXGI_FORMAT_R16G16_SINT : DXGI_FORMAT_R16G16_UINT;
}
break;
case FMT_16_16_16_16:
if (el.is_normalized) {
vtx_format = el.is_signed ?
DXGI_FORMAT_R16G16B16A16_SNORM : DXGI_FORMAT_R16G16B16A16_UNORM;
} else {
vtx_format = el.is_signed ?
DXGI_FORMAT_R16G16B16A16_SINT : DXGI_FORMAT_R16G16B16A16_UINT;
}
break;
case FMT_16_16_FLOAT:
vtx_format = DXGI_FORMAT_R16G16_FLOAT;
break;
case FMT_16_16_16_16_FLOAT:
vtx_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
break;
case FMT_32:
vtx_format = el.is_signed ?
DXGI_FORMAT_R32_SINT : DXGI_FORMAT_R32_UINT;
break;
case FMT_32_32:
vtx_format = el.is_signed ?
DXGI_FORMAT_R32G32_SINT : DXGI_FORMAT_R32G32_UINT;
break;
case FMT_32_32_32_32:
vtx_format = el.is_signed ?
DXGI_FORMAT_R32G32B32A32_SINT : DXGI_FORMAT_R32G32B32A32_UINT;
break;
case FMT_32_FLOAT:
vtx_format = DXGI_FORMAT_R32_FLOAT;
break;
case FMT_32_32_FLOAT:
vtx_format = DXGI_FORMAT_R32G32_FLOAT;
break;
case FMT_32_32_32_FLOAT:
vtx_format = DXGI_FORMAT_R32G32B32_FLOAT;
break;
case FMT_32_32_32_32_FLOAT:
vtx_format = DXGI_FORMAT_R32G32B32A32_FLOAT;
break;
default:
XEASSERTALWAYS();
break;
}
element_descs[el_index].SemanticName = "XE_VF";
element_descs[el_index].SemanticIndex = el_index;
element_descs[el_index].Format = vtx_format;
element_descs[el_index].InputSlot = vb_slot;
element_descs[el_index].AlignedByteOffset = el.offset_words * 4;
element_descs[el_index].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
element_descs[el_index].InstanceDataStepRate = 0;
el_index++;
}
}
HRESULT hr = resource_cache_->device()->CreateInputLayout(
element_descs,
(UINT)element_count,
byte_code, byte_code_length,
&input_layout_);
if (FAILED(hr)) {
XELOGE("D3D11: failed to create vertex shader input layout");
return 1;
}
return 0;
}
int D3D11VertexShaderResource::DemandGeometryShader(
GeometryShaderType type, D3D11GeometryShader** out_shader) {
if (geometry_shaders_[type]) {
*out_shader = geometry_shaders_[type];
return 0;
}
// Demand generate.
auto device = resource_cache_->device();
D3D11GeometryShader* shader = nullptr;
switch (type) {
case POINT_SPRITE_SHADER:
shader = new D3D11PointSpriteGeometryShader(device);
break;
case RECT_LIST_SHADER:
shader = new D3D11RectListGeometryShader(device);
break;
case QUAD_LIST_SHADER:
shader = new D3D11QuadListGeometryShader(device);
break;
default:
XEASSERTALWAYS();
return 1;
}
if (!shader) {
return 1;
}
if (shader->Prepare(this)) {
delete shader;
return 1;
}
geometry_shaders_[type] = shader;
*out_shader = geometry_shaders_[type];
return 0;
}
D3D11PixelShaderResource::D3D11PixelShaderResource(
D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info)
: PixelShaderResource(memory_range, info),
resource_cache_(resource_cache),
handle_(nullptr),
translated_src_(nullptr) {
}
D3D11PixelShaderResource::~D3D11PixelShaderResource() {
XESAFERELEASE(handle_);
xe_free(translated_src_);
}
int D3D11PixelShaderResource::Prepare(const xe_gpu_program_cntl_t& program_cntl,
VertexShaderResource* input_shader) {
SCOPE_profile_cpu_f("gpu");
if (is_prepared_ || handle_) {
return 0;
}
// TODO(benvanik): look in file based on hash/etc.
void* byte_code = NULL;
size_t byte_code_length = 0;
// Translate and compile source.
D3D11ShaderTranslator translator;
int ret = translator.TranslatePixelShader(this,
program_cntl,
input_shader->alloc_counts());
if (ret) {
XELOGE("D3D11: failed to translate pixel shader");
return ret;
}
translated_src_ = xestrdupa(translator.translated_src());
ID3D10Blob* shader_blob = D3D11ShaderCompile(
XE_GPU_SHADER_TYPE_PIXEL, translated_src_, disasm_src());
if (!shader_blob) {
return 1;
}
byte_code_length = shader_blob->GetBufferSize();
byte_code = xe_malloc(byte_code_length);
xe_copy_struct(
byte_code, shader_blob->GetBufferPointer(), byte_code_length);
XESAFERELEASE(shader_blob);
// Create shader.
HRESULT hr = resource_cache_->device()->CreatePixelShader(
byte_code, byte_code_length,
nullptr,
&handle_);
if (FAILED(hr)) {
XELOGE("D3D11: failed to create pixel shader");
xe_free(byte_code);
return 1;
}
xe_free(byte_code);
is_prepared_ = true;
return 0;
}

View File

@@ -0,0 +1,91 @@
/**
******************************************************************************
* 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_SHADER_RESOURCE_H_
#define XENIA_GPU_D3D11_D3D11_SHADER_RESOURCE_H_
#include <xenia/gpu/shader_resource.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11GeometryShader;
class D3D11ResourceCache;
struct Output;
typedef struct {
Output* output;
xenos::XE_GPU_SHADER_TYPE type;
uint32_t tex_fetch_index;
} xe_gpu_translate_ctx_t;
class D3D11VertexShaderResource : public VertexShaderResource {
public:
D3D11VertexShaderResource(D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info);
~D3D11VertexShaderResource() override;
void* handle() const override { return handle_; }
ID3D11InputLayout* input_layout() const { return input_layout_; }
const char* translated_src() const { return translated_src_; }
int Prepare(const xenos::xe_gpu_program_cntl_t& program_cntl) override;
enum GeometryShaderType {
POINT_SPRITE_SHADER,
RECT_LIST_SHADER,
QUAD_LIST_SHADER,
MAX_GEOMETRY_SHADER_TYPE, // keep at the end
};
int DemandGeometryShader(GeometryShaderType type,
D3D11GeometryShader** out_shader);
private:
int CreateInputLayout(const void* byte_code, size_t byte_code_length);
D3D11ResourceCache* resource_cache_;
ID3D11VertexShader* handle_;
ID3D11InputLayout* input_layout_;
D3D11GeometryShader* geometry_shaders_[MAX_GEOMETRY_SHADER_TYPE];
char* translated_src_;
};
class D3D11PixelShaderResource : public PixelShaderResource {
public:
D3D11PixelShaderResource(D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info);
~D3D11PixelShaderResource() override;
void* handle() const override { return handle_; }
const char* translated_src() const { return translated_src_; }
int Prepare(const xenos::xe_gpu_program_cntl_t& program_cntl,
VertexShaderResource* vertex_shader) override;
private:
D3D11ResourceCache* resource_cache_;
ID3D11PixelShader* handle_;
char* translated_src_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_SHADER_RESOURCE_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,125 @@
/**
******************************************************************************
* 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_SHADER_TRANSLATOR_H_
#define XENIA_GPU_D3D11_D3D11_SHADER_TRANSLATOR_H_
#include <xenia/gpu/shader_resource.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ShaderTranslator {
public:
const static uint32_t kMaxInterpolators = 16;
D3D11ShaderTranslator();
int TranslateVertexShader(VertexShaderResource* vertex_shader,
const xenos::xe_gpu_program_cntl_t& program_cntl);
int TranslatePixelShader(
PixelShaderResource* pixel_shader,
const xenos::xe_gpu_program_cntl_t& program_cntl,
const VertexShaderResource::AllocCounts& alloc_counts);
const char* translated_src() const { return buffer_; }
private:
xenos::XE_GPU_SHADER_TYPE type_;
uint32_t tex_fetch_index_;
const uint32_t* dwords_;
static const int kCapacity = 64 * 1024;
char buffer_[kCapacity];
size_t capacity_;
size_t offset_;
void append(const char* format, ...) {
va_list args;
va_start(args, format);
int len = xevsnprintfa(buffer_ + offset_, capacity_ - offset_,
format, args);
va_end(args);
offset_ += len;
buffer_[offset_] = 0;
}
void AppendTextureHeader(
const ShaderResource::SamplerInputs& sampler_inputs);
void AppendSrcReg(uint32_t num, uint32_t type, uint32_t swiz, uint32_t negate,
uint32_t abs);
void AppendDestRegName(uint32_t num, uint32_t dst_exp);
void AppendDestReg(uint32_t num, uint32_t mask, uint32_t dst_exp);
void AppendDestRegPost(uint32_t num, uint32_t mask, uint32_t dst_exp);
void PrintSrcReg(uint32_t num, uint32_t type, uint32_t swiz, uint32_t negate,
uint32_t abs);
void PrintDstReg(uint32_t num, uint32_t mask, uint32_t dst_exp);
void PrintExportComment(uint32_t num);
int TranslateALU(const xenos::instr_alu_t* alu, int sync);
int TranslateALU_ADDv(const xenos::instr_alu_t& alu);
int TranslateALU_MULv(const xenos::instr_alu_t& alu);
int TranslateALU_MAXv(const xenos::instr_alu_t& alu);
int TranslateALU_MINv(const xenos::instr_alu_t& alu);
int TranslateALU_SETXXv(const xenos::instr_alu_t& alu, const char* op);
int TranslateALU_SETEv(const xenos::instr_alu_t& alu);
int TranslateALU_SETGTv(const xenos::instr_alu_t& alu);
int TranslateALU_SETGTEv(const xenos::instr_alu_t& alu);
int TranslateALU_SETNEv(const xenos::instr_alu_t& alu);
int TranslateALU_FRACv(const xenos::instr_alu_t& alu);
int TranslateALU_TRUNCv(const xenos::instr_alu_t& alu);
int TranslateALU_FLOORv(const xenos::instr_alu_t& alu);
int TranslateALU_MULADDv(const xenos::instr_alu_t& alu);
int TranslateALU_CNDXXv(const xenos::instr_alu_t& alu, const char* op);
int TranslateALU_CNDEv(const xenos::instr_alu_t& alu);
int TranslateALU_CNDGTEv(const xenos::instr_alu_t& alu);
int TranslateALU_CNDGTv(const xenos::instr_alu_t& alu);
int TranslateALU_DOT4v(const xenos::instr_alu_t& alu);
int TranslateALU_DOT3v(const xenos::instr_alu_t& alu);
int TranslateALU_DOT2ADDv(const xenos::instr_alu_t& alu);
// CUBEv
int TranslateALU_MAX4v(const xenos::instr_alu_t& alu);
// ...
int TranslateALU_MAXs(const xenos::instr_alu_t& alu);
int TranslateALU_MINs(const xenos::instr_alu_t& alu);
int TranslateALU_SETXXs(const xenos::instr_alu_t& alu, const char* op);
int TranslateALU_SETEs(const xenos::instr_alu_t& alu);
int TranslateALU_SETGTs(const xenos::instr_alu_t& alu);
int TranslateALU_SETGTEs(const xenos::instr_alu_t& alu);
int TranslateALU_SETNEs(const xenos::instr_alu_t& alu);
int TranslateALU_RECIP_IEEE(const xenos::instr_alu_t& alu);
int TranslateALU_MUL_CONST_0(const xenos::instr_alu_t& alu);
int TranslateALU_MUL_CONST_1(const xenos::instr_alu_t& alu);
int TranslateALU_ADD_CONST_0(const xenos::instr_alu_t& alu);
int TranslateALU_ADD_CONST_1(const xenos::instr_alu_t& alu);
int TranslateALU_SUB_CONST_0(const xenos::instr_alu_t& alu);
int TranslateALU_SUB_CONST_1(const xenos::instr_alu_t& alu);
void PrintDestFecth(uint32_t dst_reg, uint32_t dst_swiz);
void AppendFetchDest(uint32_t dst_reg, uint32_t dst_swiz);
int GetFormatComponentCount(uint32_t format);
int TranslateExec(const xenos::instr_cf_exec_t& cf);
int TranslateVertexFetch(const xenos::instr_fetch_vtx_t* vtx, int sync);
int TranslateTextureFetch(const xenos::instr_fetch_tex_t* tex, int sync);
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_SHADER_TRANSLATOR_H_

View File

@@ -1,264 +0,0 @@
/**
******************************************************************************
* 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,
const uint8_t* host_address)
: Texture(address, host_address),
cache_(cache) {
}
D3D11Texture::~D3D11Texture() {
}
TextureView* D3D11Texture::FetchNew(
const xenos::xe_gpu_texture_fetch_t& fetch) {
D3D11TextureView* view = new D3D11TextureView();
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 (!CreateTexture1D(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 (!CreateTexture2D(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 (!CreateTexture3D(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 (!CreateTextureCube(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::FetchDirty(
TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) {
auto d3d_view = static_cast<D3D11TextureView*>(view);
switch (view->dimensions) {
case DIMENSION_1D:
return FetchTexture1D(d3d_view, fetch);
case DIMENSION_2D:
return FetchTexture2D(d3d_view, fetch);
case DIMENSION_3D:
return FetchTexture3D(d3d_view, fetch);
case DIMENSION_CUBE:
return FetchTextureCube(d3d_view, fetch);
}
return false;
}
bool D3D11Texture::CreateTexture1D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) {
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;
}
return FetchTexture1D(view, fetch);
}
bool D3D11Texture::FetchTexture1D(
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
SCOPE_profile_cpu_f("gpu");
// TODO(benvanik): upload!
XELOGE("D3D11: FetchTexture1D not yet implemented");
return false;
}
bool D3D11Texture::CreateTexture2D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) {
XEASSERTTRUE(fetch.dimension == 1);
D3D11_TEXTURE2D_DESC texture_desc;
xe_zero_struct(&texture_desc, sizeof(texture_desc));
texture_desc.Width = view->sizes_2d.output_width;
texture_desc.Height = view->sizes_2d.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;
}
return FetchTexture2D(view, fetch);
}
bool D3D11Texture::FetchTexture2D(
D3D11TextureView* view, const xe_gpu_texture_fetch_t& fetch) {
SCOPE_profile_cpu_f("gpu");
XEASSERTTRUE(fetch.dimension == 1);
auto sizes = GetTextureSizes2D(view);
// TODO(benvanik): all mip levels.
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = cache_->context()->Map(view->resource, 0,
D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: failed to map texture");
return false;
}
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
uint32_t output_pitch = res.RowPitch; // (output_width / info.block_size) * info.texel_pitch;
if (!fetch.tiled) {
dest = (uint8_t*)res.pData;
for (uint32_t y = 0; y < sizes.block_height; y++) {
for (uint32_t x = 0; x < sizes.logical_pitch; x += view->texel_pitch) {
TextureSwap(dest + x, src + x, view->texel_pitch, (XE_GPU_ENDIAN)fetch.endianness);
}
src += sizes.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 < sizes.block_height;
y++, output_base_offset += output_pitch) {
auto input_base_offset = TiledOffset2DOuter(y, (sizes.input_width / view->block_size), bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < sizes.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::CreateTexture3D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) {
XELOGE("D3D11: CreateTexture3D not yet implemented");
XEASSERTALWAYS();
return false;
}
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::CreateTextureCube(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) {
XELOGE("D3D11: CreateTextureCube not yet implemented");
XEASSERTALWAYS();
return false;
}
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;
}

View File

@@ -1,78 +0,0 @@
/**
******************************************************************************
* 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,
const uint8_t* host_address);
virtual ~D3D11Texture();
protected:
TextureView* FetchNew(
const xenos::xe_gpu_texture_fetch_t& fetch) override;
bool FetchDirty(
TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch) override;
bool CreateTexture1D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool FetchTexture1D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool CreateTexture2D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool FetchTexture2D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool CreateTexture3D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool FetchTexture3D(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool CreateTextureCube(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
bool FetchTextureCube(
D3D11TextureView* view, const xenos::xe_gpu_texture_fetch_t& fetch);
D3D11TextureCache* cache_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_TEXTURE_H_

View File

@@ -1,61 +0,0 @@
/**
******************************************************************************
* 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 uint8_t* host_address,
const xenos::xe_gpu_texture_fetch_t& fetch) override;
private:
ID3D11DeviceContext* context_;
ID3D11Device* device_;
struct CachedSamplerState {
D3D11_SAMPLER_DESC desc;
ID3D11SamplerState* state;
};
std::unordered_multimap<size_t, CachedSamplerState> samplers_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_TEXTURE_CACHE_H_

View File

@@ -0,0 +1,219 @@
/**
******************************************************************************
* 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_resource.h>
#include <xenia/gpu/gpu-private.h>
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
using namespace xe;
using namespace xe::gpu;
using namespace xe::gpu::d3d11;
using namespace xe::gpu::xenos;
D3D11TextureResource::D3D11TextureResource(
D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info)
: TextureResource(memory_range, info),
resource_cache_(resource_cache),
texture_(nullptr),
handle_(nullptr) {
}
D3D11TextureResource::~D3D11TextureResource() {
XESAFERELEASE(texture_);
XESAFERELEASE(handle_);
}
int D3D11TextureResource::CreateHandle() {
SCOPE_profile_cpu_f("gpu");
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 = info_.format;
D3D_SRV_DIMENSION dimension = D3D11_SRV_DIMENSION_UNKNOWN;
switch (info_.dimension) {
case TEXTURE_DIMENSION_1D:
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
srv_desc.Texture1D.MipLevels = 1;
srv_desc.Texture1D.MostDetailedMip = 0;
if (CreateHandle1D()) {
XELOGE("D3D11: failed to create Texture1D");
return 1;
}
break;
case TEXTURE_DIMENSION_2D:
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = 1;
srv_desc.Texture2D.MostDetailedMip = 0;
if (CreateHandle2D()) {
XELOGE("D3D11: failed to create Texture2D");
return 1;
}
break;
case TEXTURE_DIMENSION_3D:
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
srv_desc.Texture3D.MipLevels = 1;
srv_desc.Texture3D.MostDetailedMip = 0;
if (CreateHandle3D()) {
XELOGE("D3D11: failed to create Texture3D");
return 1;
}
break;
case TEXTURE_DIMENSION_CUBE:
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
srv_desc.TextureCube.MipLevels = 1;
srv_desc.TextureCube.MostDetailedMip = 0;
if (CreateHandleCube()) {
XELOGE("D3D11: failed to create TextureCube");
return 1;
}
break;
}
HRESULT hr = resource_cache_->device()->CreateShaderResourceView(
texture_, &srv_desc, &handle_);
if (FAILED(hr)) {
XELOGE("D3D11: unable to create texture resource view");
return 1;
}
return 0;
}
int D3D11TextureResource::CreateHandle1D() {
uint32_t width = 1 + info_.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 = resource_cache_->device()->CreateTexture1D(
&texture_desc, NULL, (ID3D11Texture1D**)&texture_);
if (FAILED(hr)) {
return 1;
}
return 0;
}
int D3D11TextureResource::CreateHandle2D() {
D3D11_TEXTURE2D_DESC texture_desc;
xe_zero_struct(&texture_desc, sizeof(texture_desc));
texture_desc.Width = info_.size_2d.output_width;
texture_desc.Height = info_.size_2d.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 = resource_cache_->device()->CreateTexture2D(
&texture_desc, NULL, (ID3D11Texture2D**)&texture_);
if (FAILED(hr)) {
return 1;
}
return 0;
}
int D3D11TextureResource::CreateHandle3D() {
XELOGE("D3D11: CreateTexture3D not yet implemented");
XEASSERTALWAYS();
return 1;
}
int D3D11TextureResource::CreateHandleCube() {
XELOGE("D3D11: CreateTextureCube not yet implemented");
XEASSERTALWAYS();
return 1;
}
int D3D11TextureResource::InvalidateRegion(const MemoryRange& memory_range) {
SCOPE_profile_cpu_f("gpu");
switch (info_.dimension) {
case TEXTURE_DIMENSION_1D:
return InvalidateRegion1D(memory_range);
case TEXTURE_DIMENSION_2D:
return InvalidateRegion2D(memory_range);
case TEXTURE_DIMENSION_3D:
return InvalidateRegion3D(memory_range);
case TEXTURE_DIMENSION_CUBE:
return InvalidateRegionCube(memory_range);
}
return 1;
}
int D3D11TextureResource::InvalidateRegion1D(const MemoryRange& memory_range) {
return 1;
}
int D3D11TextureResource::InvalidateRegion2D(const MemoryRange& memory_range) {
// TODO(benvanik): all mip levels.
D3D11_MAPPED_SUBRESOURCE res;
HRESULT hr = resource_cache_->context()->Map(
texture_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
if (FAILED(hr)) {
XELOGE("D3D11: failed to map texture");
return 1;
}
const uint8_t* src = memory_range_.host_base;
uint8_t* dest = (uint8_t*)res.pData;
uint32_t output_pitch = res.RowPitch; // (output_width / info.block_size) * info.texel_pitch;
if (!info_.is_tiled) {
dest = (uint8_t*)res.pData;
for (uint32_t y = 0; y < info_.size_2d.block_height; y++) {
for (uint32_t x = 0; x < info_.size_2d.logical_pitch; x += info_.texel_pitch) {
TextureSwap(dest + x, src + x, info_.texel_pitch);
}
src += info_.size_2d.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 < info_.size_2d.block_height;
y++, output_base_offset += output_pitch) {
auto input_base_offset = TiledOffset2DOuter(y, (info_.size_2d.input_width / info_.block_size), bpp);
for (uint32_t x = 0, output_offset = output_base_offset;
x < info_.size_2d.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);
}
}
}
resource_cache_->context()->Unmap(texture_, 0);
return 0;
}
int D3D11TextureResource::InvalidateRegion3D(const MemoryRange& memory_range) {
return 1;
}
int D3D11TextureResource::InvalidateRegionCube(
const MemoryRange& memory_range) {
return 1;
}

View File

@@ -0,0 +1,60 @@
/**
******************************************************************************
* 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_RESOURCE_H_
#define XENIA_GPU_D3D11_D3D11_TEXTURE_RESOURCE_H_
#include <xenia/gpu/texture_resource.h>
#include <xenia/gpu/xenos/xenos.h>
#include <d3d11.h>
namespace xe {
namespace gpu {
namespace d3d11 {
class D3D11ResourceCache;
class D3D11TextureResource : public TextureResource {
public:
D3D11TextureResource(D3D11ResourceCache* resource_cache,
const MemoryRange& memory_range,
const Info& info);
~D3D11TextureResource() override;
void* handle() const override { return handle_; }
protected:
int CreateHandle() override;
int CreateHandle1D();
int CreateHandle2D();
int CreateHandle3D();
int CreateHandleCube();
int InvalidateRegion(const MemoryRange& memory_range) override;
int InvalidateRegion1D(const MemoryRange& memory_range);
int InvalidateRegion2D(const MemoryRange& memory_range);
int InvalidateRegion3D(const MemoryRange& memory_range);
int InvalidateRegionCube(const MemoryRange& memory_range);
private:
D3D11ResourceCache* resource_cache_;
ID3D11Resource* texture_;
ID3D11ShaderResourceView* handle_;
};
} // namespace d3d11
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_D3D11_D3D11_TEXTURE_RESOURCE_H_

View File

@@ -1,10 +1,8 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'd3d11_buffer.cc',
'd3d11_buffer.h',
'd3d11_buffer_cache.cc',
'd3d11_buffer_cache.h',
'd3d11_buffer_resource.cc',
'd3d11_buffer_resource.h',
'd3d11_geometry_shader.cc',
'd3d11_geometry_shader.h',
'd3d11_gpu-private.h',
@@ -16,14 +14,16 @@
'd3d11_graphics_system.h',
'd3d11_profiler_display.cc',
'd3d11_profiler_display.h',
'd3d11_shader.cc',
'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_resource_cache.cc',
'd3d11_resource_cache.h',
'd3d11_sampler_state_resource.cc',
'd3d11_sampler_state_resource.h',
'd3d11_shader_resource.cc',
'd3d11_shader_resource.h',
'd3d11_shader_translator.cc',
'd3d11_shader_translator.h',
'd3d11_texture_resource.cc',
'd3d11_texture_resource.h',
'd3d11_window.cc',
'd3d11_window.h',
],