Removing D3D.
This commit is contained in:
parent
bbb7de6bff
commit
42e6a44624
|
@ -1,155 +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_resource.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#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() {
|
||||
SafeRelease(handle_);
|
||||
}
|
||||
|
||||
int D3D11IndexBufferResource::CreateHandle() {
|
||||
D3D11_BUFFER_DESC buffer_desc;
|
||||
memset(&buffer_desc, 0, 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:
|
||||
assert_true(info_.endianness == XE_GPU_ENDIAN_8IN16 ||
|
||||
info_.endianness == XE_GPU_ENDIAN_8IN32);
|
||||
|
||||
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] = poly::byte_swap(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] = poly::byte_swap(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() {
|
||||
SafeRelease(handle_);
|
||||
}
|
||||
|
||||
int D3D11VertexBufferResource::CreateHandle() {
|
||||
D3D11_BUFFER_DESC buffer_desc;
|
||||
memset(&buffer_desc, 0, 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;
|
||||
if (FLAGS_max_draw_elements) {
|
||||
count = std::min(FLAGS_max_draw_elements, count);
|
||||
}
|
||||
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] = poly::byte_swap(src_ptr[o + j]);
|
||||
}
|
||||
o += stride;
|
||||
}
|
||||
}
|
||||
|
||||
resource_cache_->context()->Unmap(handle_, 0);
|
||||
return 0;
|
||||
}
|
|
@ -1,67 +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_RESOURCE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_BUFFER_RESOURCE_H_
|
||||
|
||||
#include <xenia/gpu/buffer_resource.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/xenos/xenos.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_
|
|
@ -1,286 +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_geometry_shader.h>
|
||||
|
||||
#include <poly/math.h>
|
||||
#include <xenia/core/hash.h>
|
||||
#include <xenia/gpu/gpu-private.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>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
|
||||
D3D11GeometryShader::D3D11GeometryShader(ID3D11Device* device)
|
||||
: handle_(nullptr) {
|
||||
device_ = device;
|
||||
device_->AddRef();
|
||||
}
|
||||
|
||||
D3D11GeometryShader::~D3D11GeometryShader() {
|
||||
SafeRelease(handle_);
|
||||
SafeRelease(device_);
|
||||
}
|
||||
|
||||
int D3D11GeometryShader::Prepare(D3D11VertexShaderResource* vertex_shader) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
if (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.
|
||||
auto output = new alloy::StringBuffer();
|
||||
if (Generate(vertex_shader, output)) {
|
||||
delete output;
|
||||
return 1;
|
||||
}
|
||||
ID3D10Blob* shader_blob = Compile(output->GetString());
|
||||
delete output;
|
||||
if (!shader_blob) {
|
||||
return 1;
|
||||
}
|
||||
byte_code_length = shader_blob->GetBufferSize();
|
||||
byte_code = malloc(byte_code_length);
|
||||
memcpy(byte_code, shader_blob->GetBufferPointer(), byte_code_length);
|
||||
SafeRelease(shader_blob);
|
||||
|
||||
// Create shader.
|
||||
HRESULT hr = device_->CreateGeometryShader(
|
||||
byte_code, byte_code_length,
|
||||
NULL,
|
||||
&handle_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: failed to create geometry shader");
|
||||
free(byte_code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ID3D10Blob* D3D11GeometryShader::Compile(const char* shader_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();
|
||||
}
|
||||
uint64_t hash = hash64(shader_source, strlen(shader_source)); // ?
|
||||
char file_name[poly::max_path];
|
||||
snprintf(file_name, poly::countof(file_name), "%s/gen_%.16llX.gs", base_path,
|
||||
hash);
|
||||
|
||||
if (FLAGS_dump_shaders.size()) {
|
||||
FILE* f = fopen(file_name, "w");
|
||||
fprintf(f, shader_source);
|
||||
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, NULL,
|
||||
"main",
|
||||
"gs_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);
|
||||
}
|
||||
SafeRelease(error_blob);
|
||||
if (FAILED(hr)) {
|
||||
return NULL;
|
||||
}
|
||||
return shader_blob;
|
||||
}
|
||||
|
||||
int D3D11GeometryShader::Generate(D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) {
|
||||
output->Append(
|
||||
"struct VERTEX {\n"
|
||||
" float4 oPos : SV_POSITION;\n");
|
||||
auto alloc_counts = vertex_shader->alloc_counts();
|
||||
if (alloc_counts.params) {
|
||||
// TODO(benvanik): only add used ones?
|
||||
output->Append(
|
||||
" float4 o[%d] : XE_O;\n",
|
||||
D3D11ShaderTranslator::kMaxInterpolators);
|
||||
}
|
||||
if (alloc_counts.point_size) {
|
||||
output->Append(
|
||||
" float4 oPointSize : PSIZE;\n");
|
||||
}
|
||||
output->Append(
|
||||
"};\n");
|
||||
|
||||
output->Append(
|
||||
"cbuffer geo_consts {\n"
|
||||
"};\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
D3D11PointSpriteGeometryShader::D3D11PointSpriteGeometryShader(
|
||||
ID3D11Device* device) : D3D11GeometryShader(device) {
|
||||
}
|
||||
|
||||
D3D11PointSpriteGeometryShader::~D3D11PointSpriteGeometryShader() {
|
||||
}
|
||||
|
||||
int D3D11PointSpriteGeometryShader::Generate(
|
||||
D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto alloc_counts = vertex_shader->alloc_counts();
|
||||
|
||||
// TODO(benvanik): fetch default point size from register and use that if
|
||||
// the VS doesn't write oPointSize.
|
||||
// TODO(benvanik): clamp to min/max.
|
||||
// TODO(benvanik): figure out how to see which interpolator gets adjusted.
|
||||
|
||||
output->Append(
|
||||
"[maxvertexcount(4)]\n"
|
||||
"void main(point VERTEX input[1], inout TriangleStream<VERTEX> output) {\n"
|
||||
" const float2 offsets[4] = {\n"
|
||||
" float2(-1.0, 1.0),\n"
|
||||
" float2( 1.0, 1.0),\n"
|
||||
" float2(-1.0, -1.0),\n"
|
||||
" float2( 1.0, -1.0),\n"
|
||||
" };\n");
|
||||
if (alloc_counts.point_size) {
|
||||
// Point size specified in input.
|
||||
// TODO(benvanik): pull in psize min/max.
|
||||
output->Append(
|
||||
" float psize = max(input[0].oPointSize.x, 1.0);\n");
|
||||
} else {
|
||||
// Point size from register.
|
||||
// TODO(benvanik): pull in psize.
|
||||
output->Append(
|
||||
" float psize = 1.0;\n");
|
||||
}
|
||||
output->Append(
|
||||
" for (uint n = 0; n < 4; n++) {\n"
|
||||
" VERTEX v = input[0];\n"
|
||||
" v.oPos.xy += offsets[n] * psize;\n"
|
||||
" output.Append(v);\n"
|
||||
" }\n"
|
||||
" output.RestartStrip();\n"
|
||||
"}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
D3D11RectListGeometryShader::D3D11RectListGeometryShader(
|
||||
ID3D11Device* device) : D3D11GeometryShader(device) {
|
||||
}
|
||||
|
||||
D3D11RectListGeometryShader::~D3D11RectListGeometryShader() {
|
||||
}
|
||||
|
||||
int D3D11RectListGeometryShader::Generate(
|
||||
D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto alloc_counts = vertex_shader->alloc_counts();
|
||||
|
||||
output->Append(
|
||||
"[maxvertexcount(4)]\n"
|
||||
"void main(triangle VERTEX input[3], inout TriangleStream<VERTEX> output) {\n"
|
||||
" for (uint n = 0; n < 3; n++) {\n"
|
||||
" VERTEX v = input[n];\n"
|
||||
" output.Append(v);\n"
|
||||
" }\n"
|
||||
" VERTEX v = input[2];\n"
|
||||
" v.oPos += input[1].oPos - input[0].oPos;\n");
|
||||
if (alloc_counts.point_size) {
|
||||
output->Append(
|
||||
" v.oPointSize += input[1].oPointSize - input[0].oPointSize;\n");
|
||||
}
|
||||
for (uint32_t n = 0; n < alloc_counts.params; n++) {
|
||||
// TODO(benvanik): this may be wrong - the count is a bad metric.
|
||||
output->Append(
|
||||
" v.o[%d] += input[1].o[%d] - input[0].o[%d];\n",
|
||||
n, n, n, n);
|
||||
}
|
||||
output->Append(
|
||||
" output.Append(v);\n"
|
||||
" output.RestartStrip();\n"
|
||||
"}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
D3D11QuadListGeometryShader::D3D11QuadListGeometryShader(
|
||||
ID3D11Device* device) : D3D11GeometryShader(device) {
|
||||
}
|
||||
|
||||
D3D11QuadListGeometryShader::~D3D11QuadListGeometryShader() {
|
||||
}
|
||||
|
||||
int D3D11QuadListGeometryShader::Generate(
|
||||
D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
if (D3D11GeometryShader::Generate(vertex_shader, output)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
output->Append(
|
||||
"[maxvertexcount(4)]\n"
|
||||
"void main(lineadj VERTEX input[4], inout TriangleStream<VERTEX> output) {\n"
|
||||
" const uint order[4] = { 0, 1, 3, 2 };\n"
|
||||
" for (uint n = 0; n < 4; n++) {\n"
|
||||
" VERTEX v = input[order[n]];\n"
|
||||
" output.Append(v);\n"
|
||||
" }\n"
|
||||
" output.RestartStrip();\n"
|
||||
"}\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,81 +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_GEOMETRY_SHADER_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_GEOMETRY_SHADER_H_
|
||||
|
||||
#include <alloy/string_buffer.h>
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11VertexShaderResource;
|
||||
|
||||
class D3D11GeometryShader {
|
||||
public:
|
||||
virtual ~D3D11GeometryShader();
|
||||
|
||||
ID3D11GeometryShader* handle() const { return handle_; }
|
||||
|
||||
int Prepare(D3D11VertexShaderResource* vertex_shader);
|
||||
|
||||
protected:
|
||||
D3D11GeometryShader(ID3D11Device* device);
|
||||
|
||||
ID3D10Blob* Compile(const char* shader_source);
|
||||
|
||||
virtual int Generate(D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output);
|
||||
|
||||
protected:
|
||||
ID3D11Device* device_;
|
||||
ID3D11GeometryShader* handle_;
|
||||
};
|
||||
|
||||
|
||||
class D3D11PointSpriteGeometryShader : public D3D11GeometryShader {
|
||||
public:
|
||||
D3D11PointSpriteGeometryShader(ID3D11Device* device);
|
||||
~D3D11PointSpriteGeometryShader() override;
|
||||
|
||||
protected:
|
||||
int Generate(D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) override;
|
||||
};
|
||||
|
||||
|
||||
class D3D11RectListGeometryShader : public D3D11GeometryShader {
|
||||
public:
|
||||
D3D11RectListGeometryShader(ID3D11Device* device);
|
||||
~D3D11RectListGeometryShader() override;
|
||||
|
||||
protected:
|
||||
int Generate(D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) override;
|
||||
};
|
||||
|
||||
|
||||
class D3D11QuadListGeometryShader : public D3D11GeometryShader {
|
||||
public:
|
||||
D3D11QuadListGeometryShader(ID3D11Device* device);
|
||||
~D3D11QuadListGeometryShader() override;
|
||||
|
||||
protected:
|
||||
int Generate(D3D11VertexShaderResource* vertex_shader,
|
||||
alloy::StringBuffer* output) override;
|
||||
};
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_SHADER_H_
|
|
@ -1,33 +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_GPU_PRIVATE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_GPU_PRIVATE_H_
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
template <typename T>
|
||||
void SafeRelease(T* ptr) {
|
||||
if (ptr) {
|
||||
ptr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_GPU_PRIVATE_H_
|
|
@ -1,40 +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_gpu.h>
|
||||
|
||||
#include <xenia/gpu/d3d11/d3d11_graphics_system.h>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
|
||||
namespace {
|
||||
void InitializeIfNeeded();
|
||||
void CleanupOnShutdown();
|
||||
|
||||
void InitializeIfNeeded() {
|
||||
static bool has_initialized = false;
|
||||
if (has_initialized) {
|
||||
return;
|
||||
}
|
||||
has_initialized = true;
|
||||
|
||||
//
|
||||
|
||||
atexit(CleanupOnShutdown);
|
||||
}
|
||||
|
||||
void CleanupOnShutdown() {}
|
||||
}
|
||||
|
||||
std::unique_ptr<GraphicsSystem> xe::gpu::d3d11::Create(Emulator* emulator) {
|
||||
InitializeIfNeeded();
|
||||
return std::make_unique<D3D11GraphicsSystem>(emulator);
|
||||
}
|
|
@ -1,32 +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_GPU_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_GPU_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <xenia/common.h>
|
||||
|
||||
namespace xe {
|
||||
class Emulator;
|
||||
} // namespace xe
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
class GraphicsSystem;
|
||||
namespace d3d11 {
|
||||
|
||||
std::unique_ptr<GraphicsSystem> Create(Emulator* emulator);
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_GPU_H_
|
|
@ -1,924 +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_graphics_driver.h>
|
||||
|
||||
#include <poly/math.h>
|
||||
#include <xenia/core/hash.h>
|
||||
#include <xenia/gpu/gpu-private.h>
|
||||
#include <xenia/gpu/buffer_resource.h>
|
||||
#include <xenia/gpu/shader_resource.h>
|
||||
#include <xenia/gpu/texture_resource.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_geometry_shader.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_shader_resource.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
|
||||
#define XETRACED3D(fmt, ...) if (FLAGS_trace_ring_buffer) XELOGGPU(fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
D3D11GraphicsDriver::D3D11GraphicsDriver(
|
||||
Memory* memory, IDXGISwapChain* swap_chain, ID3D11Device* device) :
|
||||
GraphicsDriver(memory) {
|
||||
swap_chain_ = swap_chain;
|
||||
swap_chain_->AddRef();
|
||||
device_ = device;
|
||||
device_->AddRef();
|
||||
device_->GetImmediateContext(&context_);
|
||||
|
||||
resource_cache_ = new D3D11ResourceCache(memory, device_, context_);
|
||||
|
||||
memset(&state_, 0, sizeof(state_));
|
||||
|
||||
memset(&render_targets_, 0, sizeof(render_targets_));
|
||||
|
||||
HRESULT hr;
|
||||
D3D11_BUFFER_DESC buffer_desc = {0};
|
||||
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
buffer_desc.ByteWidth = (512 * 4) * sizeof(float);
|
||||
hr = device_->CreateBuffer(
|
||||
&buffer_desc, NULL, &state_.constant_buffers.float_constants);
|
||||
buffer_desc.ByteWidth = (8) * sizeof(int);
|
||||
hr = device_->CreateBuffer(
|
||||
&buffer_desc, NULL, &state_.constant_buffers.bool_constants);
|
||||
buffer_desc.ByteWidth = (32) * sizeof(int);
|
||||
hr = device_->CreateBuffer(
|
||||
&buffer_desc, NULL, &state_.constant_buffers.loop_constants);
|
||||
buffer_desc.ByteWidth = (32) * sizeof(int);
|
||||
hr = device_->CreateBuffer(
|
||||
&buffer_desc, NULL, &state_.constant_buffers.vs_consts);
|
||||
buffer_desc.ByteWidth = (32) * sizeof(int);
|
||||
hr = device_->CreateBuffer(
|
||||
&buffer_desc, NULL, &state_.constant_buffers.gs_consts);
|
||||
}
|
||||
|
||||
D3D11GraphicsDriver::~D3D11GraphicsDriver() {
|
||||
RebuildRenderTargets(0, 0);
|
||||
SafeRelease(state_.constant_buffers.float_constants);
|
||||
SafeRelease(state_.constant_buffers.bool_constants);
|
||||
SafeRelease(state_.constant_buffers.loop_constants);
|
||||
SafeRelease(state_.constant_buffers.vs_consts);
|
||||
SafeRelease(state_.constant_buffers.gs_consts);
|
||||
for (auto it = rasterizer_state_cache_.begin();
|
||||
it != rasterizer_state_cache_.end(); ++it) {
|
||||
SafeRelease(it->second);
|
||||
}
|
||||
for (auto it = blend_state_cache_.begin();
|
||||
it != blend_state_cache_.end(); ++it) {
|
||||
SafeRelease(it->second);
|
||||
}
|
||||
for (auto it = depth_stencil_state_cache_.begin();
|
||||
it != depth_stencil_state_cache_.end(); ++it) {
|
||||
SafeRelease(it->second);
|
||||
}
|
||||
SafeRelease(invalid_texture_view_);
|
||||
SafeRelease(invalid_texture_sampler_state_);
|
||||
delete resource_cache_;
|
||||
SafeRelease(context_);
|
||||
SafeRelease(device_);
|
||||
SafeRelease(swap_chain_);
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::Initialize() {
|
||||
InitializeInvalidTexture();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void D3D11GraphicsDriver::InitializeInvalidTexture() {
|
||||
// TODO(benvanik): pattern?
|
||||
D3D11_TEXTURE2D_DESC texture_desc = {0};
|
||||
texture_desc.Width = 4;
|
||||
texture_desc.Height = 4;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
texture_desc.SampleDesc.Count = 1;
|
||||
texture_desc.SampleDesc.Quality = 0;
|
||||
texture_desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = 0;
|
||||
texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS?
|
||||
uint32_t texture_data[] = {
|
||||
0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00,
|
||||
0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00,
|
||||
0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00,
|
||||
0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00,
|
||||
};
|
||||
D3D11_SUBRESOURCE_DATA initial_data;
|
||||
initial_data.SysMemPitch = 4 * texture_desc.Width;
|
||||
initial_data.SysMemSlicePitch = 0;
|
||||
initial_data.pSysMem = texture_data;
|
||||
ID3D11Texture2D* texture = NULL;
|
||||
HRESULT hr = device_->CreateTexture2D(
|
||||
&texture_desc, &initial_data, (ID3D11Texture2D**)&texture);
|
||||
if (FAILED(hr)) {
|
||||
PFATAL("D3D11: unable to create invalid texture");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC texture_view_desc = {};
|
||||
texture_view_desc.Format = texture_desc.Format;
|
||||
texture_view_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
texture_view_desc.Texture2D.MipLevels = 1;
|
||||
texture_view_desc.Texture2D.MostDetailedMip = 0;
|
||||
hr = device_->CreateShaderResourceView(
|
||||
texture, &texture_view_desc, &invalid_texture_view_);
|
||||
SafeRelease(texture);
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc = {};
|
||||
sampler_desc.Filter;
|
||||
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
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;
|
||||
hr = device_->CreateSamplerState(
|
||||
&sampler_desc, &invalid_texture_sampler_state_);
|
||||
if (FAILED(hr)) {
|
||||
PFATAL("D3D11: unable to create invalid sampler state");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::Draw(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// Misc state.
|
||||
if (UpdateState(command)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Build constant buffers.
|
||||
if (SetupConstantBuffers(command)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Bind shaders.
|
||||
if (SetupShaders(command)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Bind vertex buffers/index buffer.
|
||||
if (SetupInputAssembly(command)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Bind texture fetchers.
|
||||
if (SetupSamplers(command)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (command.index_buffer) {
|
||||
// Have an actual index buffer.
|
||||
XETRACED3D("D3D11: draw indexed %d (indicies [%d,%d] (%d))",
|
||||
command.prim_type, command.start_index,
|
||||
command.start_index + command.index_count, command.index_count);
|
||||
context_->DrawIndexed(command.index_count, command.start_index,
|
||||
command.base_vertex);
|
||||
} else {
|
||||
// Auto draw.
|
||||
XETRACED3D("D3D11: draw indexed auto %d (indicies [%d,%d] (%d))",
|
||||
command.prim_type, command.start_index,
|
||||
command.start_index + command.index_count, command.index_count);
|
||||
context_->Draw(command.index_count, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::UpdateState(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// Most information comes from here:
|
||||
// https://chromium.googlesource.com/chromiumos/third_party/mesa/+/6173cc19c45d92ef0b7bc6aa008aa89bb29abbda/src/gallium/drivers/freedreno/freedreno_zsa.c
|
||||
// http://cgit.freedesktop.org/mesa/mesa/diff/?id=aac7f06ad843eaa696363e8e9c7781ca30cb4914
|
||||
// The only differences so far are extra packets for multiple render targets
|
||||
// and a few modes being switched around.
|
||||
|
||||
RegisterFile& rf = register_file_;
|
||||
|
||||
uint32_t window_scissor_tl = register_file_[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32;
|
||||
uint32_t window_scissor_br = register_file_[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32;
|
||||
//uint32_t window_width =
|
||||
// (window_scissor_br & 0x7FFF) - (window_scissor_tl & 0x7FFF);
|
||||
//uint32_t window_height =
|
||||
// ((window_scissor_br >> 16) & 0x7FFF) - ((window_scissor_tl >> 16) & 0x7FFF);
|
||||
uint32_t window_width = 1280;
|
||||
uint32_t window_height = 720;
|
||||
if (RebuildRenderTargets(window_width, window_height)) {
|
||||
XELOGE("Unable to rebuild render targets to %d x %d",
|
||||
window_width, window_height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// RB_SURFACE_INFO ?
|
||||
|
||||
// Enable buffers.
|
||||
uint32_t enable_mode = register_file_[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7;
|
||||
// 4 = color + depth
|
||||
// 6 = copy ?
|
||||
|
||||
// color_info[0-3] has format 8888
|
||||
uint32_t color_info[4] = {
|
||||
register_file_[XE_GPU_REG_RB_COLOR_INFO].u32,
|
||||
register_file_[XE_GPU_REG_RB_COLOR1_INFO].u32,
|
||||
register_file_[XE_GPU_REG_RB_COLOR2_INFO].u32,
|
||||
register_file_[XE_GPU_REG_RB_COLOR3_INFO].u32,
|
||||
};
|
||||
ID3D11RenderTargetView* render_target_views[4] = { 0 };
|
||||
for (int n = 0; n < poly::countof(color_info); n++) {
|
||||
auto cb = render_targets_.color_buffers[n];
|
||||
uint32_t color_format = (color_info[n] >> 16) & 0xF;
|
||||
switch (color_format) {
|
||||
case 0: // D3DFMT_A8R8G8B8 (or ABGR?)
|
||||
case 1:
|
||||
render_target_views[n] = cb.color_view_8888;
|
||||
break;
|
||||
default:
|
||||
// Unknown.
|
||||
XELOGGPU("Unsupported render target format %d", color_format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// depth_info has format 24_8
|
||||
uint32_t depth_info = register_file_[XE_GPU_REG_RB_DEPTH_INFO].u32;
|
||||
uint32_t depth_format = (depth_info >> 16) & 0x1;
|
||||
ID3D11DepthStencilView* depth_stencil_view = 0;
|
||||
switch (depth_format) {
|
||||
case 0: // D3DFMT_D24S8
|
||||
depth_stencil_view = render_targets_.depth_view_d28s8;
|
||||
break;
|
||||
default:
|
||||
case 1: // D3DFMT_D24FS8
|
||||
//depth_stencil_view = render_targets_.depth_view_d28fs8;
|
||||
XELOGGPU("Unsupported depth/stencil format %d", depth_format);
|
||||
break;
|
||||
}
|
||||
// TODO(benvanik): when a game switches does it expect to keep the same
|
||||
// depth buffer contents?
|
||||
|
||||
// TODO(benvanik): only enable the number of valid render targets.
|
||||
context_->OMSetRenderTargets(4, render_target_views, depth_stencil_view);
|
||||
|
||||
// Viewport.
|
||||
// If we have resized the window we will want to change this.
|
||||
uint32_t window_offset = register_file_[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32;
|
||||
// signed?
|
||||
uint32_t window_offset_x = window_offset & 0x7FFF;
|
||||
uint32_t window_offset_y = (window_offset >> 16) & 0x7FFF;
|
||||
|
||||
// ?
|
||||
// TODO(benvanik): figure out how to emulate viewports in D3D11. Could use
|
||||
// viewport above to scale, though that doesn't support negatives/etc.
|
||||
uint32_t vte_control = register_file_[XE_GPU_REG_PA_CL_VTE_CNTL].u32;
|
||||
bool vport_xscale_enable = (vte_control & (1 << 0)) > 0;
|
||||
float vport_xscale = register_file_[XE_GPU_REG_PA_CL_VPORT_XSCALE].f32; // 640
|
||||
bool vport_xoffset_enable = (vte_control & (1 << 1)) > 0;
|
||||
float vport_xoffset = register_file_[XE_GPU_REG_PA_CL_VPORT_XOFFSET].f32; // 640
|
||||
bool vport_yscale_enable = (vte_control & (1 << 2)) > 0;
|
||||
float vport_yscale = register_file_[XE_GPU_REG_PA_CL_VPORT_YSCALE].f32; // -360
|
||||
bool vport_yoffset_enable = (vte_control & (1 << 3)) > 0;
|
||||
float vport_yoffset = register_file_[XE_GPU_REG_PA_CL_VPORT_YOFFSET].f32; // 360
|
||||
bool vport_zscale_enable = (vte_control & (1 << 4)) > 0;
|
||||
float vport_zscale = register_file_[XE_GPU_REG_PA_CL_VPORT_ZSCALE].f32; // 1
|
||||
bool vport_zoffset_enable = (vte_control & (1 << 5)) > 0;
|
||||
float vport_zoffset = register_file_[XE_GPU_REG_PA_CL_VPORT_ZOFFSET].f32; // 0
|
||||
|
||||
// TODO(benvanik): compute viewport values.
|
||||
D3D11_VIEWPORT viewport;
|
||||
if (vport_xscale_enable) {
|
||||
// Viewport enabled.
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = 1280;
|
||||
viewport.Height = 720;
|
||||
} else {
|
||||
// Viewport disabled. Geometry shaders will compensate for this.
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = 1280;
|
||||
viewport.Height = 720;
|
||||
}
|
||||
context_->RSSetViewports(1, &viewport);
|
||||
|
||||
// Viewport constants from D3D11VertexShader.
|
||||
//"cbuffer vs_consts {\n"
|
||||
//" float4 window;\n" // x,y,w,h
|
||||
//" float4 viewport_z_enable;\n" // min,(max - min),?,enabled
|
||||
//" float4 viewport_size;\n" // x,y,w,h
|
||||
//"};"
|
||||
// TODO(benvanik): only when viewport changes.
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
context_->Map(
|
||||
state_.constant_buffers.vs_consts, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
float* vsc_buffer = (float*)res.pData;
|
||||
vsc_buffer[0] = (float)window_offset_x;
|
||||
vsc_buffer[1] = (float)window_offset_y;
|
||||
vsc_buffer[2] = (float)window_width;
|
||||
vsc_buffer[3] = (float)window_height;
|
||||
vsc_buffer[4] = viewport.MinDepth;
|
||||
vsc_buffer[5] = viewport.MaxDepth - viewport.MinDepth;
|
||||
vsc_buffer[6] = 0; // unused
|
||||
vsc_buffer[7] = vport_xscale_enable ? 1.0f : 0.0f;
|
||||
vsc_buffer[8] = viewport.TopLeftX;
|
||||
vsc_buffer[9] = viewport.TopLeftY;
|
||||
vsc_buffer[10] = viewport.Width;
|
||||
vsc_buffer[11] = viewport.Height;
|
||||
context_->Unmap(state_.constant_buffers.vs_consts, 0);
|
||||
|
||||
// Scissoring.
|
||||
// TODO(benvanik): pull from scissor registers.
|
||||
// ScissorEnable must be set in raster state above.
|
||||
uint32_t screen_scissor_tl = register_file_[XE_GPU_REG_PA_SC_SCREEN_SCISSOR_TL].u32;
|
||||
uint32_t screen_scissor_br = register_file_[XE_GPU_REG_PA_SC_SCREEN_SCISSOR_BR].u32;
|
||||
if (screen_scissor_tl != 0 && screen_scissor_br != 0x20002000) {
|
||||
D3D11_RECT scissor_rect;
|
||||
scissor_rect.top = (screen_scissor_tl >> 16) & 0x7FFF;
|
||||
scissor_rect.left = screen_scissor_tl & 0x7FFF;
|
||||
scissor_rect.bottom = (screen_scissor_br >> 16) & 0x7FFF;
|
||||
scissor_rect.right = screen_scissor_br & 0x7FFF;
|
||||
context_->RSSetScissorRects(1, &scissor_rect);
|
||||
} else {
|
||||
context_->RSSetScissorRects(0, NULL);
|
||||
}
|
||||
|
||||
if (SetupRasterizerState(command)) {
|
||||
XELOGE("Unable to setup rasterizer state");
|
||||
return 1;
|
||||
}
|
||||
if (SetupBlendState(command)) {
|
||||
XELOGE("Unable to setup blend state");
|
||||
return 1;
|
||||
}
|
||||
if (SetupDepthStencilState(command)) {
|
||||
XELOGE("Unable to setup depth/stencil state");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupRasterizerState(const DrawCommand& command) {
|
||||
uint32_t mode_control = register_file_[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = hash_combine(mode_control);
|
||||
ID3D11RasterizerState* rasterizer_state = nullptr;
|
||||
auto it = rasterizer_state_cache_.find(key);
|
||||
if (it == rasterizer_state_cache_.end()) {
|
||||
D3D11_RASTERIZER_DESC rasterizer_desc = {};
|
||||
rasterizer_desc.FillMode = D3D11_FILL_SOLID; // D3D11_FILL_WIREFRAME;
|
||||
switch (mode_control & 0x3) {
|
||||
case 0:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
break;
|
||||
case 1:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_FRONT;
|
||||
break;
|
||||
case 2:
|
||||
rasterizer_desc.CullMode = D3D11_CULL_BACK;
|
||||
break;
|
||||
}
|
||||
if (command.prim_type == XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST) {
|
||||
// Rect lists aren't culled. There may be other things they skip too.
|
||||
rasterizer_desc.CullMode = D3D11_CULL_NONE;
|
||||
}
|
||||
rasterizer_desc.FrontCounterClockwise = (mode_control & 0x4) == 0;
|
||||
rasterizer_desc.DepthBias = 0;
|
||||
rasterizer_desc.DepthBiasClamp = 0;
|
||||
rasterizer_desc.SlopeScaledDepthBias = 0;
|
||||
rasterizer_desc.DepthClipEnable = false; // ?
|
||||
rasterizer_desc.ScissorEnable = false;
|
||||
rasterizer_desc.MultisampleEnable = false;
|
||||
rasterizer_desc.AntialiasedLineEnable = false;
|
||||
device_->CreateRasterizerState(&rasterizer_desc, &rasterizer_state);
|
||||
rasterizer_state_cache_.insert({ key, rasterizer_state });
|
||||
} else {
|
||||
rasterizer_state = it->second;
|
||||
}
|
||||
|
||||
context_->RSSetState(rasterizer_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupBlendState(const DrawCommand& command) {
|
||||
static const D3D11_BLEND blend_map[] = {
|
||||
/* 0 */ D3D11_BLEND_ZERO,
|
||||
/* 1 */ D3D11_BLEND_ONE,
|
||||
/* 2 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 3 */ D3D11_BLEND_ZERO, // ?
|
||||
/* 4 */ D3D11_BLEND_SRC_COLOR,
|
||||
/* 5 */ D3D11_BLEND_INV_SRC_COLOR,
|
||||
/* 6 */ D3D11_BLEND_SRC_ALPHA,
|
||||
/* 7 */ D3D11_BLEND_INV_SRC_ALPHA,
|
||||
/* 8 */ D3D11_BLEND_DEST_COLOR,
|
||||
/* 9 */ D3D11_BLEND_INV_DEST_COLOR,
|
||||
/* 10 */ D3D11_BLEND_DEST_ALPHA,
|
||||
/* 11 */ D3D11_BLEND_INV_DEST_ALPHA,
|
||||
/* 12 */ D3D11_BLEND_BLEND_FACTOR,
|
||||
/* 13 */ D3D11_BLEND_INV_BLEND_FACTOR,
|
||||
/* 14 */ D3D11_BLEND_SRC1_ALPHA, // ?
|
||||
/* 15 */ D3D11_BLEND_INV_SRC1_ALPHA, // ?
|
||||
/* 16 */ D3D11_BLEND_SRC_ALPHA_SAT,
|
||||
};
|
||||
static const D3D11_BLEND_OP blend_op_map[] = {
|
||||
/* 0 */ D3D11_BLEND_OP_ADD,
|
||||
/* 1 */ D3D11_BLEND_OP_SUBTRACT,
|
||||
/* 2 */ D3D11_BLEND_OP_MIN,
|
||||
/* 3 */ D3D11_BLEND_OP_MAX,
|
||||
/* 4 */ D3D11_BLEND_OP_REV_SUBTRACT,
|
||||
};
|
||||
|
||||
// alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE
|
||||
// Not in D3D11!
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb205120(v=vs.85).aspx
|
||||
uint32_t color_control = register_file_[XE_GPU_REG_RB_COLORCONTROL].u32;
|
||||
|
||||
uint32_t color_mask = register_file_[XE_GPU_REG_RB_COLOR_MASK].u32;
|
||||
uint32_t blend_control[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_0].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_1].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_2].u32,
|
||||
register_file_[XE_GPU_REG_RB_BLENDCONTROL_3].u32,
|
||||
};
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = hash_combine(color_mask,
|
||||
blend_control[0], blend_control[1],
|
||||
blend_control[2], blend_control[3]);
|
||||
ID3D11BlendState* blend_state = nullptr;
|
||||
auto it = blend_state_cache_.find(key);
|
||||
if (it == blend_state_cache_.end()) {
|
||||
D3D11_BLEND_DESC blend_desc = {0};
|
||||
//blend_desc.AlphaToCoverageEnable = false;
|
||||
// ?
|
||||
blend_desc.IndependentBlendEnable = true;
|
||||
for (int n = 0; n < poly::countof(blend_control); n++) {
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlend = blend_map[(blend_control[n] & 0x0000001F) >> 0];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlend = blend_map[(blend_control[n] & 0x00001F00) >> 8];
|
||||
// A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOp = blend_op_map[(blend_control[n] & 0x000000E0) >> 5];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND
|
||||
blend_desc.RenderTarget[n].SrcBlendAlpha = blend_map[(blend_control[n] & 0x001F0000) >> 16];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND
|
||||
blend_desc.RenderTarget[n].DestBlendAlpha = blend_map[(blend_control[n] & 0x1F000000) >> 24];
|
||||
// A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN
|
||||
blend_desc.RenderTarget[n].BlendOpAlpha = blend_op_map[(blend_control[n] & 0x00E00000) >> 21];
|
||||
// A2XX_RB_COLOR_MASK_WRITE_*
|
||||
blend_desc.RenderTarget[n].RenderTargetWriteMask = (color_mask >> (n * 4)) & 0xF;
|
||||
// A2XX_RB_COLORCONTROL_BLEND_DISABLE ?? Can't find this!
|
||||
// Just guess based on actions.
|
||||
blend_desc.RenderTarget[n].BlendEnable = !(
|
||||
(blend_desc.RenderTarget[n].SrcBlend == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlend == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOp == D3D11_BLEND_OP_ADD) &&
|
||||
(blend_desc.RenderTarget[n].SrcBlendAlpha == D3D11_BLEND_ONE) &&
|
||||
(blend_desc.RenderTarget[n].DestBlendAlpha == D3D11_BLEND_ZERO) &&
|
||||
(blend_desc.RenderTarget[n].BlendOpAlpha == D3D11_BLEND_OP_ADD));
|
||||
}
|
||||
device_->CreateBlendState(&blend_desc, &blend_state);
|
||||
blend_state_cache_.insert({ key, blend_state });
|
||||
} else {
|
||||
blend_state = it->second;
|
||||
}
|
||||
|
||||
float blend_factor[4] = {
|
||||
register_file_[XE_GPU_REG_RB_BLEND_RED].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_GREEN].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_BLUE].f32,
|
||||
register_file_[XE_GPU_REG_RB_BLEND_ALPHA].f32,
|
||||
};
|
||||
uint32_t sample_mask = 0xFFFFFFFF; // ?
|
||||
context_->OMSetBlendState(blend_state, blend_factor, sample_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupDepthStencilState(const DrawCommand& command) {
|
||||
static const D3D11_COMPARISON_FUNC compare_func_map[] = {
|
||||
/* 0 */ D3D11_COMPARISON_NEVER,
|
||||
/* 1 */ D3D11_COMPARISON_LESS,
|
||||
/* 2 */ D3D11_COMPARISON_EQUAL,
|
||||
/* 3 */ D3D11_COMPARISON_LESS_EQUAL,
|
||||
/* 4 */ D3D11_COMPARISON_GREATER,
|
||||
/* 5 */ D3D11_COMPARISON_NOT_EQUAL,
|
||||
/* 6 */ D3D11_COMPARISON_GREATER_EQUAL,
|
||||
/* 7 */ D3D11_COMPARISON_ALWAYS,
|
||||
};
|
||||
static const D3D11_STENCIL_OP stencil_op_map[] = {
|
||||
/* 0 */ D3D11_STENCIL_OP_KEEP,
|
||||
/* 1 */ D3D11_STENCIL_OP_ZERO,
|
||||
/* 2 */ D3D11_STENCIL_OP_REPLACE,
|
||||
/* 3 */ D3D11_STENCIL_OP_INCR_SAT,
|
||||
/* 4 */ D3D11_STENCIL_OP_DECR_SAT,
|
||||
/* 5 */ D3D11_STENCIL_OP_INVERT,
|
||||
/* 6 */ D3D11_STENCIL_OP_INCR,
|
||||
/* 7 */ D3D11_STENCIL_OP_DECR,
|
||||
};
|
||||
|
||||
uint32_t depth_control = register_file_[XE_GPU_REG_RB_DEPTHCONTROL].u32;
|
||||
uint32_t stencil_ref_mask = register_file_[XE_GPU_REG_RB_STENCILREFMASK].u32;
|
||||
|
||||
// Check cache.
|
||||
uint64_t key = (uint64_t(depth_control) << 32) | stencil_ref_mask;
|
||||
ID3D11DepthStencilState* depth_stencil_state = nullptr;
|
||||
auto it = depth_stencil_state_cache_.find(key);
|
||||
if (it == depth_stencil_state_cache_.end()) {
|
||||
D3D11_DEPTH_STENCIL_DESC depth_stencil_desc = {0};
|
||||
// A2XX_RB_DEPTHCONTROL_BACKFACE_ENABLE
|
||||
// ?
|
||||
// A2XX_RB_DEPTHCONTROL_Z_ENABLE
|
||||
depth_stencil_desc.DepthEnable = (depth_control & 0x00000002) != 0;
|
||||
// A2XX_RB_DEPTHCONTROL_Z_WRITE_ENABLE
|
||||
depth_stencil_desc.DepthWriteMask = (depth_control & 0x00000004) ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
// A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE
|
||||
// ?
|
||||
// A2XX_RB_DEPTHCONTROL_ZFUNC
|
||||
depth_stencil_desc.DepthFunc = compare_func_map[(depth_control & 0x00000070) >> 4];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE
|
||||
depth_stencil_desc.StencilEnable = (depth_control & 0x00000001) != 0;
|
||||
// RB_STENCILREFMASK_STENCILMASK
|
||||
depth_stencil_desc.StencilReadMask = (stencil_ref_mask & 0x0000FF00) >> 8;
|
||||
// RB_STENCILREFMASK_STENCILWRITEMASK
|
||||
depth_stencil_desc.StencilWriteMask = (stencil_ref_mask & 0x00FF0000) >> 16;
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILFUNC
|
||||
depth_stencil_desc.FrontFace.StencilFunc = compare_func_map[(depth_control & 0x00000700) >> 8];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILFAIL
|
||||
depth_stencil_desc.FrontFace.StencilFailOp = stencil_op_map[(depth_control & 0x00003800) >> 11];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILZPASS
|
||||
depth_stencil_desc.FrontFace.StencilPassOp = stencil_op_map[(depth_control & 0x0001C000) >> 14];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILZFAIL
|
||||
depth_stencil_desc.FrontFace.StencilDepthFailOp = stencil_op_map[(depth_control & 0x000E0000) >> 17];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILFUNC_BF
|
||||
depth_stencil_desc.BackFace.StencilFunc = compare_func_map[(depth_control & 0x00700000) >> 20];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILFAIL_BF
|
||||
depth_stencil_desc.BackFace.StencilFailOp = stencil_op_map[(depth_control & 0x03800000) >> 23];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILZPASS_BF
|
||||
depth_stencil_desc.BackFace.StencilPassOp = stencil_op_map[(depth_control & 0x1C000000) >> 26];
|
||||
// A2XX_RB_DEPTHCONTROL_STENCILZFAIL_BF
|
||||
depth_stencil_desc.BackFace.StencilDepthFailOp = stencil_op_map[(depth_control & 0xE0000000) >> 29];
|
||||
device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state);
|
||||
depth_stencil_state_cache_.insert({ key, depth_stencil_state });
|
||||
} else {
|
||||
depth_stencil_state = it->second;
|
||||
}
|
||||
|
||||
// RB_STENCILREFMASK_STENCILREF
|
||||
uint32_t stencil_ref = (stencil_ref_mask & 0x000000FF);
|
||||
context_->OMSetDepthStencilState(depth_stencil_state, stencil_ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupConstantBuffers(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
context_->Map(
|
||||
state_.constant_buffers.float_constants, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
memcpy(res.pData,
|
||||
command.float4_constants.values,
|
||||
command.float4_constants.count * 4 * sizeof(float));
|
||||
context_->Unmap(state_.constant_buffers.float_constants, 0);
|
||||
|
||||
context_->Map(
|
||||
state_.constant_buffers.loop_constants, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
memcpy(res.pData,
|
||||
command.loop_constants.values,
|
||||
command.loop_constants.count * sizeof(int));
|
||||
context_->Unmap(state_.constant_buffers.loop_constants, 0);
|
||||
|
||||
context_->Map(
|
||||
state_.constant_buffers.bool_constants, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
memcpy(res.pData,
|
||||
command.bool_constants.values,
|
||||
command.bool_constants.count * sizeof(int));
|
||||
context_->Unmap(state_.constant_buffers.bool_constants, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupShaders(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
if (command.vertex_shader) {
|
||||
context_->VSSetShader(
|
||||
command.vertex_shader->handle_as<ID3D11VertexShader>(), nullptr, 0);
|
||||
|
||||
// Set constant buffers.
|
||||
ID3D11Buffer* vs_constant_buffers[] = {
|
||||
state_.constant_buffers.float_constants,
|
||||
state_.constant_buffers.bool_constants,
|
||||
state_.constant_buffers.loop_constants,
|
||||
state_.constant_buffers.vs_consts,
|
||||
};
|
||||
context_->VSSetConstantBuffers(
|
||||
0, static_cast<UINT>(poly::countof(vs_constant_buffers)),
|
||||
vs_constant_buffers);
|
||||
|
||||
// Setup input layout (as encoded in vertex shader).
|
||||
auto vs = static_cast<D3D11VertexShaderResource*>(command.vertex_shader);
|
||||
context_->IASetInputLayout(vs->input_layout());
|
||||
} else {
|
||||
context_->VSSetShader(nullptr, nullptr, 0);
|
||||
context_->IASetInputLayout(nullptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Pixel shader setup.
|
||||
if (command.pixel_shader) {
|
||||
context_->PSSetShader(
|
||||
command.pixel_shader->handle_as<ID3D11PixelShader>(), nullptr, 0);
|
||||
|
||||
// Set constant buffers.
|
||||
ID3D11Buffer* vs_constant_buffers[] = {
|
||||
state_.constant_buffers.float_constants,
|
||||
state_.constant_buffers.bool_constants,
|
||||
state_.constant_buffers.loop_constants,
|
||||
};
|
||||
context_->PSSetConstantBuffers(
|
||||
0, static_cast<UINT>(poly::countof(vs_constant_buffers)),
|
||||
vs_constant_buffers);
|
||||
} else {
|
||||
context_->PSSetShader(nullptr, nullptr, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupInputAssembly(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
auto vs = static_cast<D3D11VertexShaderResource*>(command.vertex_shader);
|
||||
if (!vs) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Switch primitive topology.
|
||||
// Some are unsupported on D3D11 and must be emulated.
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitive_topology;
|
||||
D3D11GeometryShader* geometry_shader = NULL;
|
||||
switch (command.prim_type) {
|
||||
case XE_GPU_PRIMITIVE_TYPE_POINT_LIST:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||
if (vs->DemandGeometryShader(
|
||||
D3D11VertexShaderResource::POINT_SPRITE_SHADER, &geometry_shader)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_LINE_LIST:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_LINE_STRIP:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_TRIANGLE_LIST:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_TRIANGLE_STRIP:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
||||
if (vs->DemandGeometryShader(
|
||||
D3D11VertexShaderResource::RECT_LIST_SHADER, &geometry_shader)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case XE_GPU_PRIMITIVE_TYPE_QUAD_LIST:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
|
||||
if (vs->DemandGeometryShader(
|
||||
D3D11VertexShaderResource::QUAD_LIST_SHADER, &geometry_shader)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case XE_GPU_PRIMITIVE_TYPE_TRIANGLE_FAN:
|
||||
case XE_GPU_PRIMITIVE_TYPE_UNKNOWN_07:
|
||||
case XE_GPU_PRIMITIVE_TYPE_LINE_LOOP:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||
XELOGE("D3D11: unsupported primitive type %d", command.prim_type);
|
||||
break;
|
||||
}
|
||||
context_->IASetPrimitiveTopology(primitive_topology);
|
||||
|
||||
// Set the geometry shader, if we are emulating a primitive type.
|
||||
if (geometry_shader) {
|
||||
context_->GSSetShader(geometry_shader->handle(), NULL, NULL);
|
||||
context_->GSSetConstantBuffers(0, 1, &state_.constant_buffers.gs_consts);
|
||||
} else {
|
||||
context_->GSSetShader(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// Index buffer, if any. May be auto draw.
|
||||
if (command.index_buffer) {
|
||||
DXGI_FORMAT format;
|
||||
switch (command.index_buffer->info().format) {
|
||||
case INDEX_FORMAT_16BIT:
|
||||
format = DXGI_FORMAT_R16_UINT;
|
||||
break;
|
||||
case INDEX_FORMAT_32BIT:
|
||||
format = DXGI_FORMAT_R32_UINT;
|
||||
break;
|
||||
}
|
||||
context_->IASetIndexBuffer(
|
||||
command.index_buffer->handle_as<ID3D11Buffer>(),
|
||||
format, 0);
|
||||
} else {
|
||||
context_->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
|
||||
}
|
||||
|
||||
// All vertex buffers.
|
||||
for (auto i = 0; i < command.vertex_buffer_count; ++i) {
|
||||
const auto& vb = command.vertex_buffers[i];
|
||||
auto buffer = vb.buffer->handle_as<ID3D11Buffer>();
|
||||
auto stride = vb.stride;
|
||||
auto offset = vb.offset;
|
||||
context_->IASetVertexBuffers(vb.input_index, 1, &buffer,
|
||||
&stride, &offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::SetupSamplers(const DrawCommand& command) {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
for (auto i = 0; i < command.vertex_shader_sampler_count; ++i) {
|
||||
const auto& input = command.vertex_shader_samplers[i];
|
||||
if (input.texture) {
|
||||
auto texture = input.texture->handle_as<ID3D11ShaderResourceView>();
|
||||
context_->VSSetShaderResources(input.input_index, 1, &texture);
|
||||
} else {
|
||||
context_->VSSetShaderResources(input.input_index, 1, &invalid_texture_view_);
|
||||
}
|
||||
if (input.sampler_state) {
|
||||
auto sampler_state = input.sampler_state->handle_as<ID3D11SamplerState>();
|
||||
context_->VSSetSamplers(input.input_index, 1, &sampler_state);
|
||||
} else {
|
||||
context_->VSSetSamplers(input.input_index, 1, &invalid_texture_sampler_state_);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < command.pixel_shader_sampler_count; ++i) {
|
||||
const auto& input = command.pixel_shader_samplers[i];
|
||||
if (input.texture) {
|
||||
auto texture = input.texture->handle_as<ID3D11ShaderResourceView>();
|
||||
context_->PSSetShaderResources(input.input_index, 1, &texture);
|
||||
} else {
|
||||
context_->PSSetShaderResources(input.input_index, 1, &invalid_texture_view_);
|
||||
}
|
||||
if (input.sampler_state) {
|
||||
auto sampler_state = input.sampler_state->handle_as<ID3D11SamplerState>();
|
||||
context_->PSSetSamplers(input.input_index, 1, &sampler_state);
|
||||
} else {
|
||||
context_->PSSetSamplers(input.input_index, 1, &invalid_texture_sampler_state_);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::RebuildRenderTargets(uint32_t width,
|
||||
uint32_t height) {
|
||||
if (width == render_targets_.width &&
|
||||
height == render_targets_.height) {
|
||||
// Cached copies are good.
|
||||
return 0;
|
||||
}
|
||||
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// Remove old versions.
|
||||
for (int n = 0; n < poly::countof(render_targets_.color_buffers); n++) {
|
||||
auto& cb = render_targets_.color_buffers[n];
|
||||
SafeRelease(cb.buffer);
|
||||
SafeRelease(cb.color_view_8888);
|
||||
}
|
||||
SafeRelease(render_targets_.depth_buffer);
|
||||
SafeRelease(render_targets_.depth_view_d28s8);
|
||||
SafeRelease(render_targets_.depth_view_d28fs8);
|
||||
|
||||
render_targets_.width = width;
|
||||
render_targets_.height = height;
|
||||
|
||||
if (!width || !height) {
|
||||
// This should only happen when cleaning up.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int n = 0; n < poly::countof(render_targets_.color_buffers); n++) {
|
||||
auto& cb = render_targets_.color_buffers[n];
|
||||
D3D11_TEXTURE2D_DESC color_buffer_desc = {};
|
||||
color_buffer_desc.Width = width;
|
||||
color_buffer_desc.Height = height;
|
||||
color_buffer_desc.MipLevels = 1;
|
||||
color_buffer_desc.ArraySize = 1;
|
||||
color_buffer_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
color_buffer_desc.SampleDesc.Count = 1;
|
||||
color_buffer_desc.SampleDesc.Quality = 0;
|
||||
color_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
color_buffer_desc.BindFlags =
|
||||
D3D11_BIND_SHADER_RESOURCE |
|
||||
D3D11_BIND_RENDER_TARGET;
|
||||
color_buffer_desc.CPUAccessFlags = 0;
|
||||
color_buffer_desc.MiscFlags = 0;
|
||||
device_->CreateTexture2D(
|
||||
&color_buffer_desc, NULL, &cb.buffer);
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
memset(&render_target_view_desc, 0, sizeof(render_target_view_desc));
|
||||
render_target_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
// render_target_view_desc.Buffer ?
|
||||
device_->CreateRenderTargetView(
|
||||
cb.buffer,
|
||||
&render_target_view_desc,
|
||||
&cb.color_view_8888);
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC depth_stencil_desc = {};
|
||||
depth_stencil_desc.Width = width;
|
||||
depth_stencil_desc.Height = height;
|
||||
depth_stencil_desc.MipLevels = 1;
|
||||
depth_stencil_desc.ArraySize = 1;
|
||||
depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depth_stencil_desc.SampleDesc.Count = 1;
|
||||
depth_stencil_desc.SampleDesc.Quality = 0;
|
||||
depth_stencil_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depth_stencil_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
depth_stencil_desc.CPUAccessFlags = 0;
|
||||
depth_stencil_desc.MiscFlags = 0;
|
||||
device_->CreateTexture2D(
|
||||
&depth_stencil_desc, NULL, &render_targets_.depth_buffer);
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {};
|
||||
depth_stencil_view_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depth_stencil_view_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
depth_stencil_view_desc.Flags = 0;
|
||||
device_->CreateDepthStencilView(
|
||||
render_targets_.depth_buffer,
|
||||
&depth_stencil_view_desc,
|
||||
&render_targets_.depth_view_d28s8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int D3D11GraphicsDriver::Resolve() {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// No clue how this is supposed to work yet.
|
||||
ID3D11Texture2D* back_buffer = 0;
|
||||
swap_chain_->GetBuffer(0, __uuidof(ID3D11Texture2D),
|
||||
(LPVOID*)&back_buffer);
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
back_buffer->GetDesc(&desc);
|
||||
if (desc.Width == render_targets_.width &&
|
||||
desc.Height == render_targets_.height) {
|
||||
// Same size/format, so copy quickly.
|
||||
context_->CopyResource(back_buffer, render_targets_.color_buffers[0].buffer);
|
||||
} else {
|
||||
// TODO(benvanik): scale size using a quad draw.
|
||||
}
|
||||
SafeRelease(back_buffer);
|
||||
|
||||
// TODO(benvanik): remove!
|
||||
float color[4] = { 0.5f, 0.5f, 0.0f, 1.0f };
|
||||
context_->ClearRenderTargetView(
|
||||
render_targets_.color_buffers[0].color_view_8888, color);
|
||||
// TODO(benvanik): take clear values from register
|
||||
context_->ClearDepthStencilView(
|
||||
render_targets_.depth_view_d28s8, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,94 +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_GRAPHICS_DRIVER_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_GRAPHICS_DRIVER_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
|
||||
#include <xenia/gpu/graphics_driver.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_resource_cache.h>
|
||||
#include <xenia/gpu/xenos/xenos.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11GraphicsDriver : public GraphicsDriver {
|
||||
public:
|
||||
D3D11GraphicsDriver(
|
||||
Memory* memory, IDXGISwapChain* swap_chain, ID3D11Device* device);
|
||||
virtual ~D3D11GraphicsDriver();
|
||||
|
||||
ResourceCache* resource_cache() const override { return resource_cache_; }
|
||||
|
||||
int Initialize() override;
|
||||
|
||||
int Draw(const DrawCommand& command) override;
|
||||
|
||||
// TODO(benvanik): figure this out.
|
||||
int Resolve() override;
|
||||
|
||||
private:
|
||||
void InitializeInvalidTexture();
|
||||
|
||||
int UpdateState(const DrawCommand& command);
|
||||
int SetupRasterizerState(const DrawCommand& command);
|
||||
int SetupBlendState(const DrawCommand& command);
|
||||
int SetupDepthStencilState(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);
|
||||
|
||||
private:
|
||||
IDXGISwapChain* swap_chain_;
|
||||
ID3D11Device* device_;
|
||||
ID3D11DeviceContext* context_;
|
||||
|
||||
D3D11ResourceCache* resource_cache_;
|
||||
|
||||
ID3D11ShaderResourceView* invalid_texture_view_;
|
||||
ID3D11SamplerState* invalid_texture_sampler_state_;
|
||||
|
||||
std::unordered_map<uint64_t, ID3D11RasterizerState*> rasterizer_state_cache_;
|
||||
std::unordered_map<uint64_t, ID3D11BlendState*> blend_state_cache_;
|
||||
std::unordered_map<uint64_t, ID3D11DepthStencilState*> depth_stencil_state_cache_;
|
||||
|
||||
struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
struct {
|
||||
ID3D11Texture2D* buffer;
|
||||
ID3D11RenderTargetView* color_view_8888;
|
||||
} color_buffers[4];
|
||||
ID3D11Texture2D* depth_buffer;
|
||||
ID3D11DepthStencilView* depth_view_d28s8;
|
||||
ID3D11DepthStencilView* depth_view_d28fs8;
|
||||
} render_targets_;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
ID3D11Buffer* float_constants;
|
||||
ID3D11Buffer* bool_constants;
|
||||
ID3D11Buffer* loop_constants;
|
||||
ID3D11Buffer* vs_consts;
|
||||
ID3D11Buffer* gs_consts;
|
||||
} constant_buffers;
|
||||
} state_;
|
||||
};
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_GRAPHICS_DRIVER_H_
|
|
@ -1,200 +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_graphics_system.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <poly/math.h>
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/gpu/gpu-private.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_graphics_driver.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_window.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
|
||||
|
||||
D3D11GraphicsSystem::D3D11GraphicsSystem(Emulator* emulator)
|
||||
: GraphicsSystem(emulator),
|
||||
window_(nullptr), dxgi_factory_(nullptr), device_(nullptr),
|
||||
timer_queue_(nullptr), vsync_timer_(nullptr) {
|
||||
}
|
||||
|
||||
D3D11GraphicsSystem::~D3D11GraphicsSystem() {
|
||||
}
|
||||
|
||||
void D3D11GraphicsSystem::Initialize() {
|
||||
GraphicsSystem::Initialize();
|
||||
|
||||
assert_null(timer_queue_);
|
||||
assert_null(vsync_timer_);
|
||||
|
||||
timer_queue_ = CreateTimerQueue();
|
||||
CreateTimerQueueTimer(
|
||||
&vsync_timer_,
|
||||
timer_queue_,
|
||||
(WAITORTIMERCALLBACK)VsyncCallback,
|
||||
this,
|
||||
16,
|
||||
16,
|
||||
WT_EXECUTEINTIMERTHREAD);
|
||||
|
||||
// Create DXGI factory so we can get a swap chain/etc.
|
||||
HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1),
|
||||
(void**)&dxgi_factory_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("CreateDXGIFactory1 failed with %.8X", hr);
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the best adapter.
|
||||
// TODO(benvanik): enable nvperfhud/etc.
|
||||
IDXGIAdapter1* adapter = 0;
|
||||
UINT n = 0;
|
||||
while (dxgi_factory_->EnumAdapters1(n, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
adapter->Release();
|
||||
n++;
|
||||
}
|
||||
// Just go with the default for now.
|
||||
adapter = 0;
|
||||
|
||||
D3D_DRIVER_TYPE driver_type =
|
||||
adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE;
|
||||
|
||||
UINT flags = 0;
|
||||
// TODO(benvanik): runtime flag
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
|
||||
// Feature level 11.0+ only.
|
||||
D3D_FEATURE_LEVEL feature_levels[] = {
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
};
|
||||
|
||||
// Create device.
|
||||
D3D_FEATURE_LEVEL actual_feature_level;
|
||||
ID3D11DeviceContext* immediate_context;
|
||||
hr = D3D11CreateDevice(
|
||||
adapter,
|
||||
driver_type,
|
||||
0, // software driver HMODULE
|
||||
flags,
|
||||
feature_levels,
|
||||
static_cast<UINT>(poly::countof(feature_levels)),
|
||||
D3D11_SDK_VERSION,
|
||||
&device_,
|
||||
&actual_feature_level,
|
||||
&immediate_context);
|
||||
if (adapter) {
|
||||
adapter->Release();
|
||||
adapter = 0;
|
||||
}
|
||||
if (immediate_context) {
|
||||
immediate_context->Release();
|
||||
immediate_context = 0;
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11CreateDevice failed with %.8X", hr);
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
// This will pump through the run-loop and and be where our swapping
|
||||
// will take place.
|
||||
assert_null(window_);
|
||||
window_ = new D3D11Window(run_loop_, dxgi_factory_, device_);
|
||||
if (window_->Initialize(L"Xenia D3D11", 1280, 720)) {
|
||||
XELOGE("Failed to create D3D11Window");
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
emulator_->set_main_window(window_);
|
||||
|
||||
// Listen for alt-enter/etc.
|
||||
dxgi_factory_->MakeWindowAssociation(window_->handle(), 0);
|
||||
|
||||
// Create the driver.
|
||||
// This runs in the worker thread and builds command lines to present
|
||||
// in the window.
|
||||
assert_null(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");
|
||||
|
||||
auto time_since_last_swap = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::high_resolution_clock::now() - last_swap_time_);
|
||||
if (time_since_last_swap.count() > 1) {
|
||||
// Force a swap when profiling.
|
||||
if (Profiler::is_enabled()) {
|
||||
window_->Swap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11GraphicsSystem::Swap() {
|
||||
// TODO(benvanik): remove this when commands are understood.
|
||||
driver_->Resolve();
|
||||
|
||||
// Swap window.
|
||||
// If we are set to vsync this will block.
|
||||
window_->Swap();
|
||||
|
||||
last_swap_time_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void __stdcall D3D11GraphicsSystem::VsyncCallback(D3D11GraphicsSystem* gs,
|
||||
BOOLEAN) {
|
||||
static bool thread_name_set = false;
|
||||
if (!thread_name_set) {
|
||||
thread_name_set = true;
|
||||
Profiler::ThreadEnter("VsyncTimer");
|
||||
}
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
gs->MarkVblank();
|
||||
|
||||
// TODO(benvanik): we shouldn't need to do the dispatch here, but there's
|
||||
// something wrong and the CP will block waiting for code that
|
||||
// needs to be run in the interrupt.
|
||||
gs->DispatchInterruptCallback(0);
|
||||
}
|
||||
|
||||
void D3D11GraphicsSystem::Shutdown() {
|
||||
GraphicsSystem::Shutdown();
|
||||
|
||||
if (vsync_timer_) {
|
||||
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL);
|
||||
}
|
||||
if (timer_queue_) {
|
||||
DeleteTimerQueueEx(timer_queue_, NULL);
|
||||
}
|
||||
|
||||
SafeRelease(device_);
|
||||
device_ = 0;
|
||||
SafeRelease(dxgi_factory_);
|
||||
dxgi_factory_ = 0;
|
||||
delete window_;
|
||||
window_ = 0;
|
||||
}
|
|
@ -1,59 +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_GRAPHICS_SYSTEM_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_GRAPHICS_SYSTEM_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/graphics_system.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11Window;
|
||||
|
||||
|
||||
std::unique_ptr<GraphicsSystem> Create(Emulator* emulator);
|
||||
|
||||
|
||||
class D3D11GraphicsSystem : public GraphicsSystem {
|
||||
public:
|
||||
D3D11GraphicsSystem(Emulator* emulator);
|
||||
virtual ~D3D11GraphicsSystem();
|
||||
|
||||
virtual void Shutdown();
|
||||
|
||||
void Swap() override;
|
||||
|
||||
protected:
|
||||
virtual void Initialize();
|
||||
virtual void Pump();
|
||||
|
||||
private:
|
||||
static void __stdcall VsyncCallback(D3D11GraphicsSystem* gs, BOOLEAN);
|
||||
|
||||
IDXGIFactory1* dxgi_factory_;
|
||||
ID3D11Device* device_;
|
||||
D3D11Window* window_;
|
||||
|
||||
HANDLE timer_queue_;
|
||||
HANDLE vsync_timer_;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point last_swap_time_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_GRAPHICS_SYSTEM_H_
|
|
@ -1,661 +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_profiler_display.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <poly/math.h>
|
||||
#include <xenia/gpu/gpu-private.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_window.h>
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
|
||||
|
||||
namespace {
|
||||
const uint8_t profiler_font[] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x10,0x78,0x38,0x78,0x7c,0x7c,0x3c,0x44,0x38,0x04,0x44,0x40,0x44,0x44,0x38,0x78,
|
||||
0x38,0x78,0x38,0x7c,0x44,0x44,0x44,0x44,0x44,0x7c,0x00,0x00,0x40,0x00,0x04,0x00,
|
||||
0x18,0x00,0x40,0x10,0x08,0x40,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x38,0x7c,0x08,0x7c,0x1c,0x7c,0x38,0x38,
|
||||
0x10,0x28,0x28,0x10,0x00,0x20,0x10,0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x04,0x00,0x20,0x38,0x38,0x70,0x00,0x1c,0x10,0x00,0x1c,0x10,0x70,0x30,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x28,0x44,0x44,0x44,0x40,0x40,0x40,0x44,0x10,0x04,0x48,0x40,0x6c,0x44,0x44,0x44,
|
||||
0x44,0x44,0x44,0x10,0x44,0x44,0x44,0x44,0x44,0x04,0x00,0x00,0x40,0x00,0x04,0x00,
|
||||
0x24,0x00,0x40,0x00,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x30,0x44,0x04,0x18,0x40,0x20,0x04,0x44,0x44,
|
||||
0x10,0x28,0x28,0x3c,0x44,0x50,0x10,0x10,0x08,0x54,0x10,0x00,0x00,0x00,0x04,0x00,
|
||||
0x00,0x08,0x00,0x10,0x44,0x44,0x40,0x40,0x04,0x28,0x00,0x30,0x10,0x18,0x58,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x44,0x44,0x40,0x44,0x40,0x40,0x40,0x44,0x10,0x04,0x50,0x40,0x54,0x64,0x44,0x44,
|
||||
0x44,0x44,0x40,0x10,0x44,0x44,0x44,0x28,0x28,0x08,0x00,0x38,0x78,0x3c,0x3c,0x38,
|
||||
0x20,0x38,0x78,0x30,0x18,0x44,0x10,0x6c,0x78,0x38,0x78,0x3c,0x5c,0x3c,0x3c,0x44,
|
||||
0x44,0x44,0x44,0x44,0x7c,0x00,0x4c,0x10,0x04,0x08,0x28,0x78,0x40,0x08,0x44,0x44,
|
||||
0x10,0x00,0x7c,0x50,0x08,0x50,0x00,0x20,0x04,0x38,0x10,0x00,0x00,0x00,0x08,0x10,
|
||||
0x10,0x10,0x7c,0x08,0x08,0x54,0x40,0x20,0x04,0x44,0x00,0x30,0x10,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x44,0x78,0x40,0x44,0x78,0x78,0x40,0x7c,0x10,0x04,0x60,0x40,0x54,0x54,0x44,0x78,
|
||||
0x44,0x78,0x38,0x10,0x44,0x44,0x54,0x10,0x10,0x10,0x00,0x04,0x44,0x40,0x44,0x44,
|
||||
0x78,0x44,0x44,0x10,0x08,0x48,0x10,0x54,0x44,0x44,0x44,0x44,0x60,0x40,0x10,0x44,
|
||||
0x44,0x44,0x28,0x44,0x08,0x00,0x54,0x10,0x18,0x18,0x48,0x04,0x78,0x10,0x38,0x3c,
|
||||
0x10,0x00,0x28,0x38,0x10,0x20,0x00,0x20,0x04,0x10,0x7c,0x00,0x7c,0x00,0x10,0x00,
|
||||
0x00,0x20,0x00,0x04,0x10,0x5c,0x40,0x10,0x04,0x00,0x00,0x60,0x10,0x0c,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x7c,0x44,0x40,0x44,0x40,0x40,0x4c,0x44,0x10,0x04,0x50,0x40,0x44,0x4c,0x44,0x40,
|
||||
0x54,0x50,0x04,0x10,0x44,0x44,0x54,0x28,0x10,0x20,0x00,0x3c,0x44,0x40,0x44,0x7c,
|
||||
0x20,0x44,0x44,0x10,0x08,0x70,0x10,0x54,0x44,0x44,0x44,0x44,0x40,0x38,0x10,0x44,
|
||||
0x44,0x54,0x10,0x44,0x10,0x00,0x64,0x10,0x20,0x04,0x7c,0x04,0x44,0x20,0x44,0x04,
|
||||
0x10,0x00,0x7c,0x14,0x20,0x54,0x00,0x20,0x04,0x38,0x10,0x10,0x00,0x00,0x20,0x10,
|
||||
0x10,0x10,0x7c,0x08,0x10,0x58,0x40,0x08,0x04,0x00,0x00,0x30,0x10,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x44,0x44,0x44,0x44,0x40,0x40,0x44,0x44,0x10,0x44,0x48,0x40,0x44,0x44,0x44,0x40,
|
||||
0x48,0x48,0x44,0x10,0x44,0x28,0x6c,0x44,0x10,0x40,0x00,0x44,0x44,0x40,0x44,0x40,
|
||||
0x20,0x3c,0x44,0x10,0x08,0x48,0x10,0x54,0x44,0x44,0x44,0x44,0x40,0x04,0x12,0x4c,
|
||||
0x28,0x54,0x28,0x3c,0x20,0x00,0x44,0x10,0x40,0x44,0x08,0x44,0x44,0x20,0x44,0x08,
|
||||
0x00,0x00,0x28,0x78,0x44,0x48,0x00,0x10,0x08,0x54,0x10,0x10,0x00,0x00,0x40,0x00,
|
||||
0x10,0x08,0x00,0x10,0x00,0x40,0x40,0x04,0x04,0x00,0x00,0x30,0x10,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x44,0x78,0x38,0x78,0x7c,0x40,0x3c,0x44,0x38,0x38,0x44,0x7c,0x44,0x44,0x38,0x40,
|
||||
0x34,0x44,0x38,0x10,0x38,0x10,0x44,0x44,0x10,0x7c,0x00,0x3c,0x78,0x3c,0x3c,0x3c,
|
||||
0x20,0x04,0x44,0x38,0x48,0x44,0x38,0x44,0x44,0x38,0x78,0x3c,0x40,0x78,0x0c,0x34,
|
||||
0x10,0x6c,0x44,0x04,0x7c,0x00,0x38,0x38,0x7c,0x38,0x08,0x38,0x38,0x20,0x38,0x70,
|
||||
0x10,0x00,0x28,0x10,0x00,0x34,0x00,0x08,0x10,0x10,0x00,0x20,0x00,0x10,0x00,0x00,
|
||||
0x20,0x04,0x00,0x20,0x10,0x3c,0x70,0x00,0x1c,0x00,0x7c,0x1c,0x10,0x70,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
const char* shader_code = " \
|
||||
cbuffer MatrixBuffer {\n \
|
||||
float4x4 projection_matrix;\n \
|
||||
};\n \
|
||||
Texture2D texture0;\n \
|
||||
SamplerState sampler0;\n \
|
||||
struct Vertex {\n \
|
||||
float2 position : POSITION0;\n \
|
||||
float2 tex : TEXCOORD0;\n \
|
||||
float4 color : COLOR0;\n \
|
||||
};\n \
|
||||
struct Pixel {\n \
|
||||
float4 position : SV_POSITION;\n \
|
||||
float2 tex : TEXCOORD0;\n \
|
||||
float4 color : COLOR0;\n \
|
||||
};\n \
|
||||
Pixel vs(Vertex v) {\n \
|
||||
Pixel p;\n \
|
||||
p.position = float4(mul(float4(v.position, 0.0f, 1.0f), projection_matrix).xy - float2(1.0f, -1.0f), 0.0f, 1.0f);\n \
|
||||
p.tex = v.tex;\n \
|
||||
p.color = v.color;\n \
|
||||
return p;\n \
|
||||
}\n \
|
||||
float4 ps(Pixel p) : SV_TARGET {\n \
|
||||
if (p.tex.x > 1.0f) {\n \
|
||||
return float4(p.color.rgb, 0.5f);\n \
|
||||
} else {\n \
|
||||
float4 sample = texture0.Sample(sampler0, p.tex);\n \
|
||||
if(sample.w < 0.5f) {\n \
|
||||
discard;\n \
|
||||
}\n \
|
||||
return p.color * sample;\n \
|
||||
}\n \
|
||||
}\n";
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
D3D11ProfilerDisplay::D3D11ProfilerDisplay(D3D11Window* window) : window_(window) {
|
||||
draw_state_ = { 0 };
|
||||
if (!SetupState() ||
|
||||
!SetupShaders() ||
|
||||
!SetupFont()) {
|
||||
// Hrm.
|
||||
assert_always();
|
||||
}
|
||||
|
||||
// Pass through mouse events.
|
||||
window->mouse_down.AddListener([](xe::ui::MouseEvent& e) {
|
||||
Profiler::OnMouseDown(
|
||||
e.button() == xe::ui::MouseEvent::MOUSE_BUTTON_LEFT,
|
||||
e.button() == xe::ui::MouseEvent::MOUSE_BUTTON_RIGHT);
|
||||
});
|
||||
window->mouse_up.AddListener([](xe::ui::MouseEvent& e) {
|
||||
Profiler::OnMouseUp();
|
||||
});
|
||||
window->mouse_move.AddListener([](xe::ui::MouseEvent& e) {
|
||||
Profiler::OnMouseMove(e.x(), e.y());
|
||||
});
|
||||
window->mouse_wheel.AddListener([](xe::ui::MouseEvent& e) {
|
||||
Profiler::OnMouseWheel(e.x(), e.y(), -e.dy());
|
||||
});
|
||||
|
||||
// Watch for toggle/mode keys and such.
|
||||
window->key_down.AddListener([](xe::ui::KeyEvent& e) {
|
||||
Profiler::OnKeyDown(e.key_code());
|
||||
});
|
||||
window->key_up.AddListener([](xe::ui::KeyEvent& e) {
|
||||
Profiler::OnKeyUp(e.key_code());
|
||||
});
|
||||
}
|
||||
|
||||
bool D3D11ProfilerDisplay::SetupState() {
|
||||
HRESULT hr;
|
||||
auto device = window_->device();
|
||||
|
||||
D3D11_BLEND_DESC blend_desc = {0};
|
||||
blend_desc.RenderTarget[0].BlendEnable = true;
|
||||
blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||
blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blend_desc.RenderTarget[0].RenderTargetWriteMask = 0x0F;
|
||||
hr = device->CreateBlendState(&blend_desc, &blend_state_);
|
||||
assert_true(SUCCEEDED(hr));
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC depth_stencil_desc = {0};
|
||||
depth_stencil_desc.DepthEnable = false;
|
||||
depth_stencil_desc.StencilEnable = false;
|
||||
depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
hr = device->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil_state_);
|
||||
assert_true(SUCCEEDED(hr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11ProfilerDisplay::SetupShaders() {
|
||||
HRESULT hr;
|
||||
auto device = window_->device();
|
||||
|
||||
ID3DBlob* vs_code_blob = nullptr;
|
||||
ID3DBlob* vs_errors = nullptr;
|
||||
hr = D3DCompile(
|
||||
shader_code, strlen(shader_code),
|
||||
"D3D11ProfilerDisplay.vs",
|
||||
nullptr,
|
||||
nullptr,
|
||||
"vs",
|
||||
"vs_5_0",
|
||||
D3DCOMPILE_ENABLE_STRICTNESS,
|
||||
0,
|
||||
&vs_code_blob,
|
||||
&vs_errors);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to compile profiler vs: %s",
|
||||
reinterpret_cast<const char*>(vs_errors->GetBufferPointer()));
|
||||
return false;
|
||||
}
|
||||
hr = device->CreateVertexShader(vs_code_blob->GetBufferPointer(),
|
||||
vs_code_blob->GetBufferSize(),
|
||||
nullptr,
|
||||
&vertex_shader_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to create profiler vs");
|
||||
return false;
|
||||
}
|
||||
ID3DBlob* ps_code_blob = nullptr;
|
||||
ID3DBlob* ps_errors = nullptr;
|
||||
hr = D3DCompile(
|
||||
shader_code, strlen(shader_code),
|
||||
"D3D11ProfilerDisplay.ps",
|
||||
nullptr,
|
||||
nullptr,
|
||||
"ps",
|
||||
"ps_5_0",
|
||||
D3DCOMPILE_ENABLE_STRICTNESS,
|
||||
0,
|
||||
&ps_code_blob,
|
||||
&ps_errors);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to compile profiler ps: %s",
|
||||
reinterpret_cast<const char*>(ps_errors->GetBufferPointer()));
|
||||
return false;
|
||||
}
|
||||
hr = device->CreatePixelShader(ps_code_blob->GetBufferPointer(),
|
||||
ps_code_blob->GetBufferSize(),
|
||||
nullptr,
|
||||
&pixel_shader_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to create profiler ps");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC buffer_desc = { 0 };
|
||||
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
buffer_desc.ByteWidth = sizeof(float) * 16;
|
||||
hr = device->CreateBuffer(&buffer_desc, nullptr, &shader_constants_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to create profiler constant buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC element_descs[] = {
|
||||
{
|
||||
"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0,
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0,
|
||||
},
|
||||
{
|
||||
"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0,
|
||||
},
|
||||
{
|
||||
"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT,
|
||||
D3D11_INPUT_PER_VERTEX_DATA, 0,
|
||||
},
|
||||
};
|
||||
hr = device->CreateInputLayout(
|
||||
element_descs, (UINT)poly::countof(element_descs),
|
||||
vs_code_blob->GetBufferPointer(), vs_code_blob->GetBufferSize(),
|
||||
&shader_layout_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to create profiler input layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
buffer_desc.ByteWidth = sizeof(draw_state_.vertex_buffer);
|
||||
hr = device->CreateBuffer(&buffer_desc, nullptr, &vertex_buffer_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Failed to create profiler vertex buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11ProfilerDisplay::SetupFont() {
|
||||
HRESULT hr;
|
||||
auto device = window_->device();
|
||||
|
||||
// Setup font lookup table.
|
||||
for (uint32_t i = 0; i < poly::countof(font_description_.char_offsets); ++i) {
|
||||
font_description_.char_offsets[i] = 206;
|
||||
}
|
||||
for (uint32_t i = 'A'; i <= 'Z'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'A')*8+1;
|
||||
}
|
||||
for (uint32_t i = 'a'; i <= 'z'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'a')*8+217;
|
||||
}
|
||||
for (uint32_t i = '0'; i <= '9'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'0')*8+433;
|
||||
}
|
||||
for (uint32_t i = '!'; i <= '/'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'!')*8+513;
|
||||
}
|
||||
for (uint32_t i = ':'; i <= '@'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-':')*8+625+8;
|
||||
}
|
||||
for (uint32_t i = '['; i <= '_'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'[')*8+681+8;
|
||||
}
|
||||
for (uint32_t i = '{'; i <= '~'; ++i) {
|
||||
font_description_.char_offsets[i] = (i-'{')*8+721+8;
|
||||
}
|
||||
|
||||
// Unpack font bitmap into an RGBA texture.
|
||||
const int FONT_TEX_X = 1024;
|
||||
const int FONT_TEX_Y = 9;
|
||||
const int UNPACKED_SIZE = FONT_TEX_X * FONT_TEX_Y * 4;
|
||||
uint32_t unpacked[UNPACKED_SIZE];
|
||||
int idx = 0;
|
||||
int end = FONT_TEX_X * FONT_TEX_Y / 8;
|
||||
for (int i = 0; i < end; i++) {
|
||||
uint8_t b = profiler_font[i];
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
unpacked[idx++] = b & 0x80 ? 0xFFFFFFFFu : 0;
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC texture_desc = { 0 };
|
||||
texture_desc.Width = FONT_TEX_X;
|
||||
texture_desc.Height = FONT_TEX_Y;
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.ArraySize = 1;
|
||||
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
texture_desc.SampleDesc.Count = 1;
|
||||
texture_desc.SampleDesc.Quality = 0;
|
||||
texture_desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.CPUAccessFlags = 0;
|
||||
texture_desc.MiscFlags = 0;
|
||||
D3D11_SUBRESOURCE_DATA initial_data = { 0 };
|
||||
initial_data.pSysMem = unpacked;
|
||||
initial_data.SysMemPitch = FONT_TEX_X * 4;
|
||||
initial_data.SysMemSlicePitch = 0;
|
||||
ID3D11Texture2D* font_texture = nullptr;
|
||||
hr = device->CreateTexture2D(&texture_desc, &initial_data, &font_texture);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Unable to create profiler font texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC texture_view_desc = {};
|
||||
texture_view_desc.Format = texture_desc.Format;
|
||||
texture_view_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
||||
texture_view_desc.Texture2D.MipLevels = 1;
|
||||
texture_view_desc.Texture2D.MostDetailedMip = 0;
|
||||
hr = device->CreateShaderResourceView(
|
||||
font_texture, &texture_view_desc, &font_texture_view_);
|
||||
SafeRelease(font_texture);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Unable to create profiler font texture view");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc = {};
|
||||
sampler_desc.Filter = D3D11_ENCODE_BASIC_FILTER(
|
||||
D3D11_FILTER_TYPE_POINT, D3D11_FILTER_TYPE_POINT,
|
||||
D3D11_FILTER_TYPE_POINT, false);
|
||||
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
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;
|
||||
hr = device->CreateSamplerState(
|
||||
&sampler_desc, &font_sampler_state_);
|
||||
if (FAILED(hr)) {
|
||||
PFATAL("D3D11: unable to create invalid sampler state");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
D3D11ProfilerDisplay::~D3D11ProfilerDisplay() {
|
||||
SafeRelease(blend_state_);
|
||||
SafeRelease(depth_stencil_state_);
|
||||
SafeRelease(vertex_shader_);
|
||||
SafeRelease(pixel_shader_);
|
||||
SafeRelease(shader_constants_);
|
||||
SafeRelease(shader_layout_);
|
||||
SafeRelease(font_texture_view_);
|
||||
SafeRelease(font_sampler_state_);
|
||||
SafeRelease(vertex_buffer_);
|
||||
}
|
||||
|
||||
uint32_t D3D11ProfilerDisplay::width() const {
|
||||
return window_->width();
|
||||
}
|
||||
|
||||
uint32_t D3D11ProfilerDisplay::height() const {
|
||||
return window_->height();
|
||||
}
|
||||
|
||||
void D3D11ProfilerDisplay::Begin() {
|
||||
auto context = window_->context();
|
||||
|
||||
D3D11_VIEWPORT viewport;
|
||||
viewport.TopLeftX = 0.0f;
|
||||
viewport.TopLeftY = 0.0f;
|
||||
viewport.Width = static_cast<float>(width());
|
||||
viewport.Height = static_cast<float>(height());
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
context->RSSetViewports(1, &viewport);
|
||||
|
||||
// Setup projection matrix.
|
||||
float left = viewport.TopLeftX;
|
||||
float right = viewport.TopLeftX + viewport.Width;
|
||||
float bottom = viewport.TopLeftY + viewport.Height;
|
||||
float top = viewport.TopLeftY;
|
||||
float z_near = viewport.MinDepth;
|
||||
float z_far = viewport.MaxDepth;
|
||||
float projection[16] = { 0 };
|
||||
projection[0] = 2.0f / (right - left);
|
||||
projection[5] = 2.0f / (top - bottom);
|
||||
projection[10] = -2.0f / (z_far - z_near);
|
||||
projection[12] = -(right + left) / (right - left);
|
||||
projection[13] = -(top + bottom) / (top - bottom);
|
||||
projection[14] = -(z_far + z_near) / (z_far - z_near);
|
||||
projection[15] = 1.0f;
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
context->Map(shader_constants_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
memcpy(res.pData, projection, sizeof(projection));
|
||||
context->Unmap(shader_constants_, 0);
|
||||
|
||||
// Setup state.
|
||||
context->OMSetBlendState(blend_state_, { 0 }, 0xFFFFFFFF);
|
||||
context->OMSetDepthStencilState(depth_stencil_state_, 0);
|
||||
|
||||
// Bind shaders.
|
||||
context->GSSetShader(nullptr, nullptr, 0);
|
||||
context->VSSetShader(vertex_shader_, nullptr, 0);
|
||||
context->VSSetConstantBuffers(0, 1, &shader_constants_);
|
||||
context->PSSetShader(pixel_shader_, nullptr, 0);
|
||||
context->PSSetConstantBuffers(0, 1, &shader_constants_);
|
||||
ID3D11SamplerState* ps_samplers[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {
|
||||
font_sampler_state_,
|
||||
nullptr,
|
||||
};
|
||||
context->PSSetSamplers(0, static_cast<UINT>(poly::countof(ps_samplers)),
|
||||
ps_samplers);
|
||||
ID3D11ShaderResourceView*
|
||||
ps_resources[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {
|
||||
font_texture_view_, nullptr,
|
||||
};
|
||||
context->PSSetShaderResources(
|
||||
0, static_cast<UINT>(poly::countof(ps_resources)), ps_resources);
|
||||
context->IASetInputLayout(shader_layout_);
|
||||
}
|
||||
|
||||
void D3D11ProfilerDisplay::End() {
|
||||
Flush();
|
||||
}
|
||||
|
||||
D3D11ProfilerDisplay::Vertex* D3D11ProfilerDisplay::AllocateVertices(
|
||||
D3D_PRIMITIVE_TOPOLOGY primitive, size_t count) {
|
||||
if (draw_state_.vertex_index + count >
|
||||
poly::countof(draw_state_.vertex_buffer)) {
|
||||
Flush();
|
||||
}
|
||||
assert_true(draw_state_.vertex_index + count <=
|
||||
poly::countof(draw_state_.vertex_buffer));
|
||||
|
||||
size_t head = draw_state_.vertex_index;
|
||||
draw_state_.vertex_index += count;
|
||||
|
||||
if (draw_state_.command_index &&
|
||||
draw_state_.commands[draw_state_.command_index - 1].primitive ==
|
||||
primitive) {
|
||||
draw_state_.commands[draw_state_.command_index - 1].vertex_count += count;
|
||||
} else {
|
||||
assert_true(draw_state_.command_index <
|
||||
poly::countof(draw_state_.commands));
|
||||
draw_state_.commands[draw_state_.command_index].primitive = primitive;
|
||||
draw_state_.commands[draw_state_.command_index].vertex_count = count;
|
||||
++draw_state_.command_index;
|
||||
}
|
||||
return &draw_state_.vertex_buffer[head];
|
||||
}
|
||||
|
||||
void D3D11ProfilerDisplay::Flush() {
|
||||
auto context = window_->context();
|
||||
if (!draw_state_.vertex_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE res;
|
||||
context->Map(vertex_buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &res);
|
||||
memcpy(res.pData, draw_state_.vertex_buffer, sizeof(Vertex) * draw_state_.vertex_index);
|
||||
context->Unmap(vertex_buffer_, 0);
|
||||
|
||||
uint32_t stride = 20;
|
||||
uint32_t offset = 0;
|
||||
context->IASetVertexBuffers(0, 1, &vertex_buffer_, &stride, &offset);
|
||||
|
||||
size_t vertex_index = 0;
|
||||
for (int i = 0; i < draw_state_.command_index; ++i) {
|
||||
size_t count = draw_state_.commands[i].vertex_count;
|
||||
context->IASetPrimitiveTopology(draw_state_.commands[i].primitive);
|
||||
context->Draw((UINT)count, (UINT)vertex_index);
|
||||
vertex_index += count;
|
||||
}
|
||||
|
||||
draw_state_.vertex_index = 0;
|
||||
draw_state_.command_index = 0;
|
||||
}
|
||||
|
||||
#define Q0(d, member, v) d[0].member = v
|
||||
#define Q1(d, member, v) d[1].member = v; d[3].member = v
|
||||
#define Q2(d, member, v) d[4].member = v
|
||||
#define Q3(d, member, v) d[2].member = v; d[5].member = v
|
||||
|
||||
void D3D11ProfilerDisplay::DrawBox(
|
||||
int x, int y, int x1, int y1, uint32_t color, BoxType type) {
|
||||
Vertex* v = AllocateVertices(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, 6);
|
||||
uint32_t color0;
|
||||
uint32_t color1;
|
||||
if (type == BOX_TYPE_FLAT) {
|
||||
color0 = 0xFF000000 |
|
||||
((color & 0xFF) << 16) |
|
||||
(color & 0xFF00FF00) |
|
||||
((color >> 16) & 0xFF);
|
||||
color1 = color0;
|
||||
} else {
|
||||
uint32_t r = 0xFF & (color >> 16);
|
||||
uint32_t g = 0xFF & (color >> 8);
|
||||
uint32_t b = 0xFF & color;
|
||||
uint32_t max_c = std::max(std::max(std::max(r, g), b), 30u);
|
||||
uint32_t min_c = std::min(std::min(std::min(r, g), b), 180u);
|
||||
uint32_t r0 = 0xFF & ((r + max_c)/2);
|
||||
uint32_t g0 = 0xFF & ((g + max_c)/2);
|
||||
uint32_t b0 = 0xFF & ((b + max_c)/2);
|
||||
uint32_t r1 = 0xFF & ((r + min_c) / 2);
|
||||
uint32_t g1 = 0xFF & ((g + min_c) / 2);
|
||||
uint32_t b1 = 0xFF & ((b + min_c) / 2);
|
||||
color0 = r0 | (g0 << 8) | (b0 << 16) | (0xFF000000 & color);
|
||||
color1 = r1 | (g1 << 8) | (b1 << 16) | (0xFF000000 & color);
|
||||
}
|
||||
Q0(v, x, (float)x);
|
||||
Q0(v, y, (float)y);
|
||||
Q0(v, color, color0);
|
||||
Q0(v, u, 2.0f);
|
||||
Q0(v, v, 2.0f);
|
||||
Q1(v, x, (float)x1);
|
||||
Q1(v, y, (float)y);
|
||||
Q1(v, color, color0);
|
||||
Q1(v, u, 3.0f);
|
||||
Q1(v, v, 2.0f);
|
||||
Q2(v, x, (float)x1);
|
||||
Q2(v, y, (float)y1);
|
||||
Q2(v, color, color1);
|
||||
Q2(v, u, 3.0f);
|
||||
Q2(v, v, 3.0f);
|
||||
Q3(v, x, (float)x);
|
||||
Q3(v, y, (float)y1);
|
||||
Q3(v, color, color1);
|
||||
Q3(v, u, 2.0f);
|
||||
Q3(v, v, 3.0f);
|
||||
}
|
||||
|
||||
void D3D11ProfilerDisplay::DrawLine2D(
|
||||
uint32_t count, float* vertices, uint32_t color) {
|
||||
if (!count || !vertices) {
|
||||
return;
|
||||
}
|
||||
color = 0xFF000000 |
|
||||
((color & 0xFF) << 16) |
|
||||
(color & 0xFF00FF00) |
|
||||
((color >> 16) & 0xFF);
|
||||
Vertex* v = AllocateVertices(D3D11_PRIMITIVE_TOPOLOGY_LINELIST, 2 * (count - 1));
|
||||
for (uint32_t i = 0; i < count - 1; ++i) {
|
||||
v[0].x = vertices[i * 2];
|
||||
v[0].y = vertices[i * 2 + 1];
|
||||
v[0].color = color;
|
||||
v[0].u = 2.0f;
|
||||
v[0].v = 2.0f;
|
||||
v[1].x = vertices[(i + 1) * 2];
|
||||
v[1].y = vertices[(i + 1) * 2 + 1] ;
|
||||
v[1].color = color;
|
||||
v[1].u = 2.0f;
|
||||
v[1].v = 2.0f;
|
||||
v += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11ProfilerDisplay::DrawText(
|
||||
int x, int y, uint32_t color, const char* text, size_t text_length) {
|
||||
const float offset_u = 5.0f / 1024.0f;
|
||||
float fx = (float)x;
|
||||
float fy = (float)y;
|
||||
float fy2 = fy + (MICROPROFILE_TEXT_HEIGHT + 1);
|
||||
color = 0xFF000000 |
|
||||
((color & 0xFF) << 16) |
|
||||
(color & 0xFF00FF00) |
|
||||
((color >> 16) & 0xFF);
|
||||
Vertex* v = AllocateVertices(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, 6 * text_length);
|
||||
const char* s = text;
|
||||
for (uint32_t j = 0; j < text_length; ++j) {
|
||||
int16_t nOffset = font_description_.char_offsets[(int)*s++];
|
||||
float fOffset = nOffset / 1024.f;
|
||||
Q0(v, x, fx);
|
||||
Q0(v, y, fy);
|
||||
Q0(v, color, color);
|
||||
Q0(v, u, fOffset);
|
||||
Q0(v, v, 0.0f);
|
||||
Q1(v, x, fx + MICROPROFILE_TEXT_WIDTH);
|
||||
Q1(v, y, fy);
|
||||
Q1(v, color, color);
|
||||
Q1(v, u, fOffset + offset_u);
|
||||
Q1(v, v, 0.0f);
|
||||
Q2(v, x, fx + MICROPROFILE_TEXT_WIDTH);
|
||||
Q2(v, y, fy2);
|
||||
Q2(v, color, color);
|
||||
Q2(v, u, fOffset + offset_u);
|
||||
Q2(v, v, 1.0f);
|
||||
Q3(v, x, fx);
|
||||
Q3(v, y, fy2);
|
||||
Q3(v, color, color);
|
||||
Q3(v, u, fOffset);
|
||||
Q3(v, v, 1.0f);
|
||||
fx += MICROPROFILE_TEXT_WIDTH + 1;
|
||||
v += 6;
|
||||
}
|
||||
}
|
|
@ -1,80 +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_PROFILER_DISPLAY_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_PROFILER_DISPLAY_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11Window;
|
||||
|
||||
class D3D11ProfilerDisplay : public ProfilerDisplay {
|
||||
public:
|
||||
D3D11ProfilerDisplay(D3D11Window* window);
|
||||
virtual ~D3D11ProfilerDisplay();
|
||||
|
||||
uint32_t width() const override;
|
||||
uint32_t height() const override;
|
||||
|
||||
// TODO(benvanik): GPU timestamping.
|
||||
|
||||
void Begin() override;
|
||||
void End() override;
|
||||
void DrawBox(int x, int y, int x1, int y1, uint32_t color, BoxType type) override;
|
||||
void DrawLine2D(uint32_t count, float* vertices, uint32_t color) override;
|
||||
void DrawText(int x, int y, uint32_t color, const char* text, size_t text_length) override;
|
||||
|
||||
private:
|
||||
bool SetupState();
|
||||
bool SetupShaders();
|
||||
bool SetupFont();
|
||||
|
||||
struct Vertex {
|
||||
float x, y;
|
||||
float u, v;
|
||||
uint32_t color;
|
||||
};
|
||||
struct {
|
||||
size_t vertex_index;
|
||||
Vertex vertex_buffer[16 << 10];
|
||||
struct {
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitive;
|
||||
size_t vertex_count;
|
||||
} commands[32];
|
||||
size_t command_index;
|
||||
} draw_state_;
|
||||
Vertex* AllocateVertices(D3D_PRIMITIVE_TOPOLOGY primitive, size_t count);
|
||||
void Flush();
|
||||
|
||||
D3D11Window* window_;
|
||||
ID3D11BlendState* blend_state_;
|
||||
ID3D11DepthStencilState* depth_stencil_state_;
|
||||
ID3D11VertexShader* vertex_shader_;
|
||||
ID3D11PixelShader* pixel_shader_;
|
||||
ID3D11Buffer* shader_constants_;
|
||||
ID3D11InputLayout* shader_layout_;
|
||||
ID3D11ShaderResourceView* font_texture_view_;
|
||||
ID3D11SamplerState* font_sampler_state_;
|
||||
ID3D11Buffer* vertex_buffer_;
|
||||
|
||||
struct {
|
||||
uint16_t char_offsets[256];
|
||||
} font_description_;
|
||||
};
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_PROFILER_DISPLAY_H_
|
|
@ -1,71 +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_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() {
|
||||
SafeRelease(device_);
|
||||
SafeRelease(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);
|
||||
}
|
|
@ -1,58 +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_RESOURCE_CACHE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_RESOURCE_CACHE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/resource_cache.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_
|
|
@ -1,105 +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_sampler_state_resource.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;
|
||||
|
||||
|
||||
D3D11SamplerStateResource::D3D11SamplerStateResource(
|
||||
D3D11ResourceCache* resource_cache, const Info& info)
|
||||
: SamplerStateResource(info),
|
||||
resource_cache_(resource_cache),
|
||||
handle_(nullptr) {
|
||||
}
|
||||
|
||||
D3D11SamplerStateResource::~D3D11SamplerStateResource() {
|
||||
SafeRelease(handle_);
|
||||
}
|
||||
|
||||
int D3D11SamplerStateResource::Prepare() {
|
||||
if (handle_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc = {};
|
||||
// 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[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,
|
||||
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[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;
|
||||
sampler_desc.BorderColor[0];
|
||||
sampler_desc.BorderColor[1];
|
||||
sampler_desc.BorderColor[2];
|
||||
sampler_desc.BorderColor[3];
|
||||
sampler_desc.MinLOD;
|
||||
sampler_desc.MaxLOD;
|
||||
|
||||
HRESULT hr = resource_cache_->device()->CreateSamplerState(
|
||||
&sampler_desc, &handle_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("D3D11: unable to create sampler state");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,47 +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_SAMPLER_STATE_RESOURCE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_SAMPLER_STATE_RESOURCE_H_
|
||||
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/sampler_state_resource.h>
|
||||
#include <xenia/gpu/xenos/ucode.h>
|
||||
#include <xenia/gpu/xenos/xenos.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_
|
|
@ -1,375 +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_shader_resource.h>
|
||||
|
||||
#include <poly/math.h>
|
||||
#include <xenia/core/hash.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 = hash64(disasm_source, strlen(disasm_source)); // ?
|
||||
char file_name[poly::max_path];
|
||||
snprintf(file_name, poly::countof(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);
|
||||
}
|
||||
SafeRelease(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) {
|
||||
memset(geometry_shaders_, 0, sizeof(geometry_shaders_));
|
||||
}
|
||||
|
||||
D3D11VertexShaderResource::~D3D11VertexShaderResource() {
|
||||
SafeRelease(handle_);
|
||||
SafeRelease(input_layout_);
|
||||
for (int i = 0; i < poly::countof(geometry_shaders_); ++i) {
|
||||
delete geometry_shaders_[i];
|
||||
}
|
||||
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_ = strdup(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 = malloc(byte_code_length);
|
||||
memcpy(byte_code, shader_blob->GetBufferPointer(), byte_code_length);
|
||||
SafeRelease(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");
|
||||
free(byte_code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create input layout.
|
||||
ret = CreateInputLayout(byte_code, byte_code_length);
|
||||
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*)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:
|
||||
assert_always();
|
||||
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:
|
||||
assert_always();
|
||||
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() {
|
||||
SafeRelease(handle_);
|
||||
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_ = strdup(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 = malloc(byte_code_length);
|
||||
memcpy(byte_code, shader_blob->GetBufferPointer(), byte_code_length);
|
||||
SafeRelease(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");
|
||||
free(byte_code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(byte_code);
|
||||
is_prepared_ = true;
|
||||
return 0;
|
||||
}
|
|
@ -1,91 +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_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
|
@ -1,125 +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_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 = vsnprintf(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);
|
||||
int TranslateALU_RETAIN_PREV(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_
|
|
@ -1,216 +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_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() {
|
||||
SafeRelease(texture_);
|
||||
SafeRelease(handle_);
|
||||
}
|
||||
|
||||
int D3D11TextureResource::CreateHandle() {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC 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 = {};
|
||||
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 = {};
|
||||
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");
|
||||
assert_always();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int D3D11TextureResource::CreateHandleCube() {
|
||||
XELOGE("D3D11: CreateTextureCube not yet implemented");
|
||||
assert_always();
|
||||
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;
|
||||
}
|
|
@ -1,59 +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_RESOURCE_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_TEXTURE_RESOURCE_H_
|
||||
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/gpu/texture_resource.h>
|
||||
#include <xenia/gpu/xenos/xenos.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_
|
|
@ -1,140 +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_window.h>
|
||||
|
||||
#include <xenia/gpu/d3d11/d3d11_profiler_display.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::gpu;
|
||||
using namespace xe::gpu::d3d11;
|
||||
using namespace xe::ui;
|
||||
using namespace xe::ui::win32;
|
||||
|
||||
|
||||
D3D11Window::D3D11Window(
|
||||
xe_run_loop_ref run_loop,
|
||||
IDXGIFactory1* dxgi_factory, ID3D11Device* device) :
|
||||
Win32Window(run_loop) {
|
||||
dxgi_factory_ = dxgi_factory;
|
||||
dxgi_factory_->AddRef();
|
||||
device_ = device;
|
||||
device_->AddRef();
|
||||
device_->GetImmediateContext(&context_);
|
||||
|
||||
swap_chain_ = 0;
|
||||
render_target_view_ = 0;
|
||||
|
||||
closing.AddListener([](UIEvent& e) {
|
||||
xe_run_loop_quit(e.window()->run_loop());
|
||||
});
|
||||
}
|
||||
|
||||
D3D11Window::~D3D11Window() {
|
||||
Profiler::set_display(nullptr);
|
||||
if (context_) {
|
||||
context_->ClearState();
|
||||
}
|
||||
SafeRelease(render_target_view_);
|
||||
SafeRelease(context_);
|
||||
SafeRelease(swap_chain_);
|
||||
SafeRelease(device_);
|
||||
SafeRelease(dxgi_factory_);
|
||||
}
|
||||
|
||||
int D3D11Window::Initialize(const std::wstring& title, uint32_t width,
|
||||
uint32_t height) {
|
||||
int result = Win32Window::Initialize(title, width, height);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Setup swap chain.
|
||||
DXGI_SWAP_CHAIN_DESC desc = {};
|
||||
desc.OutputWindow = handle();
|
||||
desc.Windowed = TRUE;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
// Setup buffers.
|
||||
desc.BufferCount = 2;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferDesc.Width = width;
|
||||
desc.BufferDesc.Height = height;
|
||||
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.BufferDesc.RefreshRate.Numerator = 60;
|
||||
desc.BufferDesc.RefreshRate.Denominator = 1;
|
||||
|
||||
// Disable multisampling.
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
|
||||
// Create!
|
||||
HRESULT hr = dxgi_factory_->CreateSwapChain(
|
||||
device_,
|
||||
&desc,
|
||||
&swap_chain_);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("CreateSwapChain failed with %.8X", hr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create a render target view to draw into.
|
||||
ID3D11Texture2D* back_buffer = 0;
|
||||
hr = swap_chain_->GetBuffer(
|
||||
0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("GetBuffer (back_buffer) failed with %.8X", hr);
|
||||
return 1;
|
||||
}
|
||||
hr = device_->CreateRenderTargetView(
|
||||
back_buffer, NULL, &render_target_view_);
|
||||
back_buffer->Release();
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("CreateRenderTargetView (back_buffer) failed with %.8X", hr);
|
||||
return 1;
|
||||
}
|
||||
context_->OMSetRenderTargets(1, &render_target_view_, NULL);
|
||||
|
||||
// Setup profiler display.
|
||||
if (Profiler::is_enabled()) {
|
||||
std::unique_ptr<D3D11ProfilerDisplay> profiler_display(
|
||||
new D3D11ProfilerDisplay(this));
|
||||
Profiler::set_display(std::move(profiler_display));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void D3D11Window::Swap() {
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
|
||||
// Present profiler.
|
||||
context_->OMSetRenderTargets(1, &render_target_view_, NULL);
|
||||
Profiler::Present();
|
||||
|
||||
// Swap buffers.
|
||||
// TODO(benvanik): control vsync with flag.
|
||||
bool vsync = true;
|
||||
HRESULT hr = swap_chain_->Present(vsync ? 1 : 0, 0);
|
||||
if (FAILED(hr)) {
|
||||
XELOGE("Present failed with %.8X", hr);
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D11Window::OnResize(uint32_t width, uint32_t height) {
|
||||
if (!Win32Window::OnResize(width, height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(benvanik): resize swap buffers?
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,52 +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_WINDOW_H_
|
||||
#define XENIA_GPU_D3D11_D3D11_WINDOW_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/gpu/d3d11/d3d11_gpu-private.h>
|
||||
#include <xenia/ui/win32/win32_window.h>
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
namespace d3d11 {
|
||||
|
||||
class D3D11Window : public xe::ui::win32::Win32Window {
|
||||
public:
|
||||
D3D11Window(
|
||||
xe_run_loop_ref run_loop,
|
||||
IDXGIFactory1* dxgi_factory, ID3D11Device* device);
|
||||
~D3D11Window() override;
|
||||
|
||||
ID3D11Device* device() const { return device_; }
|
||||
IDXGISwapChain* swap_chain() const { return swap_chain_; }
|
||||
ID3D11DeviceContext* context() const { return context_; }
|
||||
|
||||
int Initialize(const std::wstring& title, uint32_t width,
|
||||
uint32_t height) override;
|
||||
|
||||
void Swap();
|
||||
|
||||
protected:
|
||||
bool OnResize(uint32_t width, uint32_t height) override;
|
||||
|
||||
private:
|
||||
IDXGIFactory1* dxgi_factory_;
|
||||
ID3D11Device* device_;
|
||||
IDXGISwapChain* swap_chain_;
|
||||
ID3D11DeviceContext* context_;
|
||||
ID3D11RenderTargetView* render_target_view_;
|
||||
};
|
||||
|
||||
} // namespace d3d11
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_GPU_D3D11_D3D11_WINDOW_H_
|
|
@ -1,30 +0,0 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'd3d11_buffer_resource.cc',
|
||||
'd3d11_buffer_resource.h',
|
||||
'd3d11_geometry_shader.cc',
|
||||
'd3d11_geometry_shader.h',
|
||||
'd3d11_gpu-private.h',
|
||||
'd3d11_gpu.cc',
|
||||
'd3d11_gpu.h',
|
||||
'd3d11_graphics_driver.cc',
|
||||
'd3d11_graphics_driver.h',
|
||||
'd3d11_graphics_system.cc',
|
||||
'd3d11_graphics_system.h',
|
||||
'd3d11_profiler_display.cc',
|
||||
'd3d11_profiler_display.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',
|
||||
],
|
||||
}
|
Loading…
Reference in New Issue