Purge more unused

This commit is contained in:
Stenzek 2023-08-02 01:58:57 +10:00
parent ba4eeb5e94
commit 7d7a06b9f7
18 changed files with 620 additions and 1286 deletions

View File

@ -33,11 +33,7 @@
<ClCompile Include="cpu_types.cpp" />
<ClCompile Include="digital_controller.cpp" />
<ClCompile Include="game_database.cpp" />
<ClCompile Include="gpu\d3d11\shader_cache.cpp" />
<ClCompile Include="gpu\d3d11\shader_compiler.cpp" />
<ClCompile Include="gpu\d3d11\stream_buffer.cpp" />
<ClCompile Include="gpu\d3d11_device.cpp" />
<ClCompile Include="gpu\d3d11_texture.cpp" />
<ClCompile Include="gpu\d3d12\context.cpp" />
<ClCompile Include="gpu\d3d12\descriptor_heap_manager.cpp" />
<ClCompile Include="gpu\d3d12\shader_cache.cpp" />
@ -158,12 +154,8 @@
</ClInclude>
<ClInclude Include="digital_controller.h" />
<ClInclude Include="game_database.h" />
<ClInclude Include="gpu\d3d11\shader_cache.h" />
<ClInclude Include="gpu\d3d11\shader_compiler.h" />
<ClInclude Include="gpu\d3d11\stream_buffer.h" />
<ClInclude Include="gpu\d3d11_device.h" />
<ClInclude Include="gpu\d3d_shaders.h" />
<ClInclude Include="gpu\d3d11_texture.h" />
<ClInclude Include="gpu\d3d12\context.h" />
<ClInclude Include="gpu\d3d12\descriptor_heap_manager.h" />
<ClInclude Include="gpu\d3d12\shader_cache.h" />

View File

@ -74,15 +74,6 @@
<ClCompile Include="gpu\vulkan_gpu_device.cpp">
<Filter>gpu</Filter>
</ClCompile>
<ClCompile Include="gpu\d3d11\stream_buffer.cpp">
<Filter>gpu\d3d11</Filter>
</ClCompile>
<ClCompile Include="gpu\d3d11\shader_cache.cpp">
<Filter>gpu\d3d11</Filter>
</ClCompile>
<ClCompile Include="gpu\d3d11\shader_compiler.cpp">
<Filter>gpu\d3d11</Filter>
</ClCompile>
<ClCompile Include="gpu\d3d12\shader_cache.cpp">
<Filter>gpu\d3d12</Filter>
</ClCompile>
@ -185,9 +176,6 @@
<ClCompile Include="gpu\gpu_texture.cpp">
<Filter>gpu</Filter>
</ClCompile>
<ClCompile Include="gpu\d3d11_texture.cpp">
<Filter>gpu</Filter>
</ClCompile>
<ClCompile Include="gpu\gpu_shader_cache.cpp">
<Filter>gpu</Filter>
</ClCompile>
@ -272,15 +260,6 @@
<ClInclude Include="gpu\vulkan_gpu_device.h">
<Filter>gpu</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d11\shader_compiler.h">
<Filter>gpu\d3d11</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d11\stream_buffer.h">
<Filter>gpu\d3d11</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d11\shader_cache.h">
<Filter>gpu\d3d11</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d12\shader_cache.h">
<Filter>gpu\d3d12</Filter>
</ClInclude>
@ -392,9 +371,6 @@
<ClInclude Include="gpu\gpu_texture.h">
<Filter>gpu</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d11_texture.h">
<Filter>gpu</Filter>
</ClInclude>
<ClInclude Include="gpu\d3d_shaders.h">
<Filter>gpu</Filter>
</ClInclude>
@ -406,9 +382,6 @@
<Filter Include="gpu">
<UniqueIdentifier>{7b18fac1-ee2b-4816-8537-eb8f32d40ada}</UniqueIdentifier>
</Filter>
<Filter Include="gpu\d3d11">
<UniqueIdentifier>{f5b7a4af-72c7-406f-b787-9036115c3580}</UniqueIdentifier>
</Filter>
<Filter Include="gpu\d3d12">
<UniqueIdentifier>{17c2f89b-5cf4-4d3a-9343-a03c1c668b85}</UniqueIdentifier>
</Filter>

View File

@ -1,307 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "shader_cache.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/md5_digest.h"
#include "shader_compiler.h"
#include <d3dcompiler.h>
Log_SetChannel(D3D11::ShaderCache);
namespace D3D11 {
#pragma pack(push, 1)
struct CacheIndexEntry
{
u64 source_hash_low;
u64 source_hash_high;
u32 source_length;
u32 shader_type;
u32 file_offset;
u32 blob_size;
};
#pragma pack(pop)
ShaderCache::ShaderCache() = default;
ShaderCache::~ShaderCache()
{
if (m_index_file)
std::fclose(m_index_file);
if (m_blob_file)
std::fclose(m_blob_file);
}
bool ShaderCache::CacheIndexKey::operator==(const CacheIndexKey& key) const
{
return (source_hash_low == key.source_hash_low && source_hash_high == key.source_hash_high &&
source_length == key.source_length && shader_type == key.shader_type);
}
bool ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
{
return (source_hash_low != key.source_hash_low || source_hash_high != key.source_hash_high ||
source_length != key.source_length || shader_type != key.shader_type);
}
void ShaderCache::Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug)
{
m_feature_level = feature_level;
m_version = version;
m_debug = debug;
if (!base_path.empty())
{
const std::string base_filename = GetCacheBaseFileName(base_path, feature_level, debug);
const std::string index_filename = base_filename + ".idx";
const std::string blob_filename = base_filename + ".bin";
if (!ReadExisting(index_filename, blob_filename))
CreateNew(index_filename, blob_filename);
}
}
bool ShaderCache::CreateNew(const std::string& index_filename, const std::string& blob_filename)
{
if (FileSystem::FileExists(index_filename.c_str()))
{
Log_WarningPrintf("Removing existing index file '%s'", index_filename.c_str());
FileSystem::DeleteFile(index_filename.c_str());
}
if (FileSystem::FileExists(blob_filename.c_str()))
{
Log_WarningPrintf("Removing existing blob file '%s'", blob_filename.c_str());
FileSystem::DeleteFile(blob_filename.c_str());
}
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "wb");
if (!m_index_file)
{
Log_ErrorPrintf("Failed to open index file '%s' for writing", index_filename.c_str());
return false;
}
const u32 index_version = FILE_VERSION;
if (std::fwrite(&index_version, sizeof(index_version), 1, m_index_file) != 1 ||
std::fwrite(&m_version, sizeof(m_version), 1, m_index_file) != 1)
{
Log_ErrorPrintf("Failed to write version to index file '%s'", index_filename.c_str());
std::fclose(m_index_file);
m_index_file = nullptr;
FileSystem::DeleteFile(index_filename.c_str());
return false;
}
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "w+b");
if (!m_blob_file)
{
Log_ErrorPrintf("Failed to open blob file '%s' for writing", blob_filename.c_str());
std::fclose(m_index_file);
m_index_file = nullptr;
FileSystem::DeleteFile(index_filename.c_str());
return false;
}
return true;
}
bool ShaderCache::ReadExisting(const std::string& index_filename, const std::string& blob_filename)
{
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "r+b");
if (!m_index_file)
return false;
u32 file_version = 0;
u32 data_version = 0;
if (std::fread(&file_version, sizeof(file_version), 1, m_index_file) != 1 || file_version != FILE_VERSION ||
std::fread(&data_version, sizeof(data_version), 1, m_index_file) != 1 || data_version != m_version)
{
Log_ErrorPrintf("Bad file/data version in '%s'", index_filename.c_str());
std::fclose(m_index_file);
m_index_file = nullptr;
return false;
}
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "a+b");
if (!m_blob_file)
{
Log_ErrorPrintf("Blob file '%s' is missing", blob_filename.c_str());
std::fclose(m_index_file);
m_index_file = nullptr;
return false;
}
std::fseek(m_blob_file, 0, SEEK_END);
const u32 blob_file_size = static_cast<u32>(std::ftell(m_blob_file));
for (;;)
{
CacheIndexEntry entry;
if (std::fread(&entry, sizeof(entry), 1, m_index_file) != 1 ||
(entry.file_offset + entry.blob_size) > blob_file_size)
{
if (std::feof(m_index_file))
break;
Log_ErrorPrintf("Failed to read entry from '%s', corrupt file?", index_filename.c_str());
m_index.clear();
std::fclose(m_blob_file);
m_blob_file = nullptr;
std::fclose(m_index_file);
m_index_file = nullptr;
return false;
}
const CacheIndexKey key{entry.source_hash_low, entry.source_hash_high, entry.source_length,
static_cast<ShaderCompiler::Type>(entry.shader_type)};
const CacheIndexData data{entry.file_offset, entry.blob_size};
m_index.emplace(key, data);
}
// ensure we don't write before seeking
std::fseek(m_index_file, 0, SEEK_END);
Log_InfoPrintf("Read %zu entries from '%s'", m_index.size(), index_filename.c_str());
return true;
}
std::string ShaderCache::GetCacheBaseFileName(const std::string_view& base_path, D3D_FEATURE_LEVEL feature_level,
bool debug)
{
std::string base_filename(base_path);
base_filename += FS_OSPATH_SEPARATOR_STR "d3d_shaders_";
switch (feature_level)
{
case D3D_FEATURE_LEVEL_10_0:
base_filename += "sm40";
break;
case D3D_FEATURE_LEVEL_10_1:
base_filename += "sm41";
break;
case D3D_FEATURE_LEVEL_11_0:
base_filename += "sm50";
break;
default:
base_filename += "unk";
break;
}
if (debug)
base_filename += "_debug";
return base_filename;
}
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(ShaderCompiler::Type type, const std::string_view& shader_code)
{
union
{
struct
{
u64 hash_low;
u64 hash_high;
};
u8 hash[16];
};
MD5Digest digest;
digest.Update(shader_code.data(), static_cast<u32>(shader_code.length()));
digest.Final(hash);
return CacheIndexKey{hash_low, hash_high, static_cast<u32>(shader_code.length()), type};
}
ShaderCache::ComPtr<ID3DBlob> ShaderCache::GetShaderBlob(ShaderCompiler::Type type, std::string_view shader_code)
{
const auto key = GetCacheKey(type, shader_code);
auto iter = m_index.find(key);
if (iter == m_index.end())
return CompileAndAddShaderBlob(key, shader_code);
ComPtr<ID3DBlob> blob;
HRESULT hr = D3DCreateBlob(iter->second.blob_size, blob.GetAddressOf());
if (FAILED(hr) || std::fseek(m_blob_file, iter->second.file_offset, SEEK_SET) != 0 ||
std::fread(blob->GetBufferPointer(), 1, iter->second.blob_size, m_blob_file) != iter->second.blob_size)
{
Log_ErrorPrintf("Read blob from file failed");
return {};
}
return blob;
}
ShaderCache::ComPtr<ID3D11VertexShader> ShaderCache::GetVertexShader(ID3D11Device* device, std::string_view shader_code)
{
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Vertex, std::move(shader_code));
if (!blob)
return {};
return D3D11::ShaderCompiler::CreateVertexShader(device, blob.Get());
}
ShaderCache::ComPtr<ID3D11GeometryShader> ShaderCache::GetGeometryShader(ID3D11Device* device,
std::string_view shader_code)
{
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Geometry, std::move(shader_code));
if (!blob)
return {};
return D3D11::ShaderCompiler::CreateGeometryShader(device, blob.Get());
}
ShaderCache::ComPtr<ID3D11PixelShader> ShaderCache::GetPixelShader(ID3D11Device* device, std::string_view shader_code)
{
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Pixel, std::move(shader_code));
if (!blob)
return {};
return D3D11::ShaderCompiler::CreatePixelShader(device, blob.Get());
}
ShaderCache::ComPtr<ID3D11ComputeShader> ShaderCache::GetComputeShader(ID3D11Device* device,
std::string_view shader_code)
{
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Compute, std::move(shader_code));
if (!blob)
return {};
return D3D11::ShaderCompiler::CreateComputeShader(device, blob.Get());
}
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileAndAddShaderBlob(const CacheIndexKey& key,
std::string_view shader_code)
{
ComPtr<ID3DBlob> blob = ShaderCompiler::CompileShader(key.shader_type, m_feature_level, shader_code, m_debug);
if (!blob)
return {};
if (!m_blob_file || std::fseek(m_blob_file, 0, SEEK_END) != 0)
return blob;
CacheIndexData data;
data.file_offset = static_cast<u32>(std::ftell(m_blob_file));
data.blob_size = static_cast<u32>(blob->GetBufferSize());
CacheIndexEntry entry = {};
entry.source_hash_low = key.source_hash_low;
entry.source_hash_high = key.source_hash_high;
entry.source_length = key.source_length;
entry.shader_type = static_cast<u32>(key.shader_type);
entry.blob_size = data.blob_size;
entry.file_offset = data.file_offset;
if (std::fwrite(blob->GetBufferPointer(), 1, entry.blob_size, m_blob_file) != entry.blob_size ||
std::fflush(m_blob_file) != 0 || std::fwrite(&entry, sizeof(entry), 1, m_index_file) != 1 ||
std::fflush(m_index_file) != 0)
{
Log_ErrorPrintf("Failed to write shader blob to file");
return blob;
}
m_index.emplace(key, data);
return blob;
}
} // namespace D3D11

View File

@ -1,88 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/hash_combine.h"
#include "common/types.h"
#include "common/windows_headers.h"
#include "shader_compiler.h"
#include <cstdio>
#include <d3d11.h>
#include <string_view>
#include <unordered_map>
#include <vector>
#include <wrl/client.h>
namespace D3D11 {
class ShaderCache
{
public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
ShaderCache();
~ShaderCache();
void Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
ComPtr<ID3DBlob> GetShaderBlob(ShaderCompiler::Type type, std::string_view shader_code);
ComPtr<ID3D11VertexShader> GetVertexShader(ID3D11Device* device, std::string_view shader_code);
ComPtr<ID3D11GeometryShader> GetGeometryShader(ID3D11Device* device, std::string_view shader_code);
ComPtr<ID3D11PixelShader> GetPixelShader(ID3D11Device* device, std::string_view shader_code);
ComPtr<ID3D11ComputeShader> GetComputeShader(ID3D11Device* device, std::string_view shader_code);
private:
static constexpr u32 FILE_VERSION = 2;
struct CacheIndexKey
{
u64 source_hash_low;
u64 source_hash_high;
u32 source_length;
ShaderCompiler::Type shader_type;
bool operator==(const CacheIndexKey& key) const;
bool operator!=(const CacheIndexKey& key) const;
};
struct CacheIndexEntryHasher
{
std::size_t operator()(const CacheIndexKey& e) const noexcept
{
std::size_t h = 0;
hash_combine(h, e.source_hash_low, e.source_hash_high, e.source_length, e.shader_type);
return h;
}
};
struct CacheIndexData
{
u32 file_offset;
u32 blob_size;
};
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
static std::string GetCacheBaseFileName(const std::string_view& base_path, D3D_FEATURE_LEVEL feature_level,
bool debug);
static CacheIndexKey GetCacheKey(ShaderCompiler::Type type, const std::string_view& shader_code);
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
void Close();
ComPtr<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, std::string_view shader_code);
std::FILE* m_index_file = nullptr;
std::FILE* m_blob_file = nullptr;
CacheIndex m_index;
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
u32 m_version = 0;
bool m_debug = false;
};
} // namespace D3D11

View File

@ -1,202 +0,0 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "shader_compiler.h"
#include "common/log.h"
#include "common/string_util.h"
#include <array>
#include <d3dcompiler.h>
#include <fstream>
Log_SetChannel(D3D11);
namespace D3D11::ShaderCompiler {
static unsigned s_next_bad_shader_id = 1;
ComPtr<ID3DBlob> CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug)
{
const char* target;
switch (feature_level)
{
case D3D_FEATURE_LEVEL_10_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_10_1:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_11_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_11_1:
default:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
target = targets[static_cast<int>(type)];
}
break;
}
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
ComPtr<ID3DBlob> blob;
ComPtr<ID3DBlob> error_blob;
const HRESULT hr =
D3DCompile(code.data(), code.size(), "0", nullptr, nullptr, "main", target, debug ? flags_debug : flags_non_debug,
0, blob.GetAddressOf(), error_blob.GetAddressOf());
std::string error_string;
if (error_blob)
{
error_string.append(static_cast<const char*>(error_blob->GetBufferPointer()), error_blob->GetBufferSize());
error_blob.Reset();
}
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to compile '%s':\n%s", target, error_string.c_str());
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream::out | std::ofstream::binary);
if (ofs.is_open())
{
ofs << code;
ofs << "\n\nCompile as " << target << " failed: " << hr << "\n";
ofs.write(error_string.c_str(), error_string.size());
ofs.close();
}
return {};
}
if (!error_string.empty())
Log_WarningPrintf("'%s' compiled with warnings:\n%s", target, error_string.c_str());
return blob;
}
ComPtr<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, std::string_view code, bool debug)
{
ComPtr<ID3DBlob> blob = CompileShader(Type::Vertex, device->GetFeatureLevel(), std::move(code), debug);
if (!blob)
return {};
return CreateVertexShader(device, blob.Get());
}
ComPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, std::string_view code, bool debug)
{
ComPtr<ID3DBlob> blob = CompileShader(Type::Geometry, device->GetFeatureLevel(), std::move(code), debug);
if (!blob)
return {};
return CreateGeometryShader(device, blob.Get());
}
ComPtr<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, std::string_view code, bool debug)
{
ComPtr<ID3DBlob> blob = CompileShader(Type::Pixel, device->GetFeatureLevel(), std::move(code), debug);
if (!blob)
return {};
return CreatePixelShader(device, blob.Get());
}
ComPtr<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, std::string_view code, bool debug)
{
ComPtr<ID3DBlob> blob = CompileShader(Type::Compute, device->GetFeatureLevel(), std::move(code), debug);
if (!blob)
return {};
return CreateComputeShader(device, blob.Get());
}
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
ComPtr<ID3D11VertexShader> shader;
const HRESULT hr = device->CreateVertexShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to create vertex shader: 0x%08X", hr);
return {};
}
return shader;
}
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob)
{
return CreateVertexShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
ComPtr<ID3D11GeometryShader> shader;
const HRESULT hr = device->CreateGeometryShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to create geometry shader: 0x%08X", hr);
return {};
}
return shader;
}
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob)
{
return CreateGeometryShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
ComPtr<ID3D11PixelShader> shader;
const HRESULT hr = device->CreatePixelShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to create pixel shader: 0x%08X", hr);
return {};
}
return shader;
}
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob)
{
return CreatePixelShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
ComPtr<ID3D11ComputeShader> shader;
const HRESULT hr = device->CreateComputeShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to create compute shader: 0x%08X", hr);
return {};
}
return shader;
}
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob)
{
return CreateComputeShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
} // namespace D3D11::ShaderCompiler

View File

@ -1,39 +0,0 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/windows_headers.h"
#include <d3d11.h>
#include <string_view>
#include <type_traits>
#include <wrl/client.h>
namespace D3D11::ShaderCompiler {
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
enum class Type
{
Vertex,
Geometry,
Pixel,
Compute
};
ComPtr<ID3DBlob> CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug);
ComPtr<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, std::string_view code, bool debug);
ComPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, std::string_view code, bool debug);
ComPtr<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, std::string_view code, bool debug);
ComPtr<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, std::string_view code, bool debug);
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob);
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob);
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob);
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob);
}; // namespace D3D11::ShaderCompiler

View File

@ -1,113 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "stream_buffer.h"
#include "common/align.h"
#include "common/assert.h"
#include "common/log.h"
Log_SetChannel(D3D11);
namespace D3D11 {
StreamBuffer::StreamBuffer() : m_size(0), m_position(0) {}
StreamBuffer::StreamBuffer(ComPtr<ID3D11Buffer> buffer) : m_buffer(std::move(buffer)), m_position(0)
{
D3D11_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_size = desc.ByteWidth;
}
StreamBuffer::~StreamBuffer()
{
Release();
}
bool StreamBuffer::Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size)
{
CD3D11_BUFFER_DESC desc(size, bind_flags, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, 0, 0);
ComPtr<ID3D11Buffer> buffer;
HRESULT hr = device->CreateBuffer(&desc, nullptr, &buffer);
if (FAILED(hr))
{
Log_ErrorPrintf("Creating buffer failed: 0x%08X", hr);
return false;
}
m_buffer = std::move(buffer);
m_size = size;
m_position = 0;
D3D11_FEATURE_DATA_D3D11_OPTIONS options = {};
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
if (SUCCEEDED(hr))
{
if (bind_flags & D3D11_BIND_CONSTANT_BUFFER)
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicConstantBuffer;
else if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicBufferSRV;
else
m_use_map_no_overwrite = true;
if (!m_use_map_no_overwrite)
{
Log_WarningPrintf("Unable to use MAP_NO_OVERWRITE on buffer with bind flag %u, this may affect performance. "
"Update your driver/operating system.",
static_cast<unsigned>(bind_flags));
}
}
else
{
Log_WarningPrintf("ID3D11Device::CheckFeatureSupport() failed: 0x%08X", hr);
m_use_map_no_overwrite = false;
}
return true;
}
void StreamBuffer::Adopt(ComPtr<ID3D11Buffer> buffer)
{
m_buffer = std::move(buffer);
D3D11_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_size = desc.ByteWidth;
m_position = 0;
}
void StreamBuffer::Release()
{
m_buffer.Reset();
}
StreamBuffer::MappingResult StreamBuffer::Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size)
{
m_position = Common::AlignUp(m_position, alignment);
if ((m_position + min_size) >= m_size || !m_use_map_no_overwrite)
{
// wrap around
m_position = 0;
}
D3D11_MAPPED_SUBRESOURCE sr;
const D3D11_MAP map_type = (m_position == 0) ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
const HRESULT hr = context->Map(m_buffer.Get(), 0, map_type, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Map failed: 0x%08X (alignment %u, minsize %u, size %u, position %u, map type %u)", hr, alignment,
min_size, m_size, m_position, static_cast<u32>(map_type));
Panic("Map failed");
return {};
}
return MappingResult{static_cast<char*>(sr.pData) + m_position, m_position, m_position / alignment,
(m_size - m_position) / alignment};
}
void StreamBuffer::Unmap(ID3D11DeviceContext* context, u32 used_size)
{
context->Unmap(m_buffer.Get(), 0);
m_position += used_size;
}
} // namespace D3D11

View File

@ -1,47 +0,0 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/types.h"
#include "common/windows_headers.h"
#include <d3d11.h>
#include <wrl/client.h>
namespace D3D11 {
class StreamBuffer
{
public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
StreamBuffer();
StreamBuffer(ComPtr<ID3D11Buffer> buffer);
~StreamBuffer();
ALWAYS_INLINE ID3D11Buffer* GetD3DBuffer() const { return m_buffer.Get(); }
ALWAYS_INLINE ID3D11Buffer* const* GetD3DBufferArray() const { return m_buffer.GetAddressOf(); }
ALWAYS_INLINE u32 GetSize() const { return m_size; }
ALWAYS_INLINE u32 GetPosition() const { return m_position; }
bool Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size);
void Adopt(ComPtr<ID3D11Buffer> buffer);
void Release();
struct MappingResult
{
void* pointer;
u32 buffer_offset;
u32 index_aligned; // offset / alignment, suitable for base vertex
u32 space_aligned; // remaining space / alignment
};
MappingResult Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size);
void Unmap(ID3D11DeviceContext* context, u32 used_size);
private:
ComPtr<ID3D11Buffer> m_buffer;
u32 m_size;
u32 m_position;
bool m_use_map_no_overwrite = false;
};
} // namespace D3D11

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "d3d11_device.h"
@ -7,6 +7,7 @@
#include "../shader_cache_version.h"
#include "common/assert.h"
#include "common/align.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
@ -25,7 +26,12 @@ Log_SetChannel(D3D11Device);
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
static constexpr std::array<DXGI_FORMAT, static_cast<u32>(GPUTexture::Format::Count)> s_dxgi_mapping = {
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B5G6R5_UNORM,
DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_D16_UNORM}};
static constexpr std::array<float, 4> s_clear_color = {};
static unsigned s_next_bad_shader_id = 1;
static void SetD3DDebugObjectName(ID3D11DeviceChild* obj, const std::string_view& name)
@ -36,6 +42,109 @@ static void SetD3DDebugObjectName(ID3D11DeviceChild* obj, const std::string_view
obj->SetPrivateData(guid, static_cast<UINT>(wname.length()) * 2u, wname.c_str());
}
D3D11StreamBuffer::D3D11StreamBuffer() : m_size(0), m_position(0)
{
}
D3D11StreamBuffer::D3D11StreamBuffer(ComPtr<ID3D11Buffer> buffer) : m_buffer(std::move(buffer)), m_position(0)
{
D3D11_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_size = desc.ByteWidth;
}
D3D11StreamBuffer::~D3D11StreamBuffer()
{
Release();
}
bool D3D11StreamBuffer::Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size)
{
CD3D11_BUFFER_DESC desc(size, bind_flags, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, 0, 0);
ComPtr<ID3D11Buffer> buffer;
HRESULT hr = device->CreateBuffer(&desc, nullptr, &buffer);
if (FAILED(hr))
{
Log_ErrorPrintf("Creating buffer failed: 0x%08X", hr);
return false;
}
m_buffer = std::move(buffer);
m_size = size;
m_position = 0;
D3D11_FEATURE_DATA_D3D11_OPTIONS options = {};
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
if (SUCCEEDED(hr))
{
if (bind_flags & D3D11_BIND_CONSTANT_BUFFER)
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicConstantBuffer;
else if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicBufferSRV;
else
m_use_map_no_overwrite = true;
if (!m_use_map_no_overwrite)
{
Log_WarningPrintf("Unable to use MAP_NO_OVERWRITE on buffer with bind flag %u, this may affect performance. "
"Update your driver/operating system.",
static_cast<unsigned>(bind_flags));
}
}
else
{
Log_WarningPrintf("ID3D11Device::CheckFeatureSupport() failed: 0x%08X", hr);
m_use_map_no_overwrite = false;
}
return true;
}
void D3D11StreamBuffer::Adopt(ComPtr<ID3D11Buffer> buffer)
{
m_buffer = std::move(buffer);
D3D11_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_size = desc.ByteWidth;
m_position = 0;
}
void D3D11StreamBuffer::Release()
{
m_buffer.Reset();
}
D3D11StreamBuffer::MappingResult D3D11StreamBuffer::Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size)
{
m_position = Common::AlignUp(m_position, alignment);
if ((m_position + min_size) >= m_size || !m_use_map_no_overwrite)
{
// wrap around
m_position = 0;
}
D3D11_MAPPED_SUBRESOURCE sr;
const D3D11_MAP map_type = (m_position == 0) ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
const HRESULT hr = context->Map(m_buffer.Get(), 0, map_type, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Map failed: 0x%08X (alignment %u, minsize %u, size %u, position %u, map type %u)", hr, alignment,
min_size, m_size, m_position, static_cast<u32>(map_type));
Panic("Map failed");
return {};
}
return MappingResult{static_cast<char*>(sr.pData) + m_position, m_position, m_position / alignment,
(m_size - m_position) / alignment};
}
void D3D11StreamBuffer::Unmap(ID3D11DeviceContext* context, u32 used_size)
{
context->Unmap(m_buffer.Get(), 0);
m_position += used_size;
}
D3D11Device::D3D11Device() = default;
D3D11Device::~D3D11Device()
@ -679,7 +788,7 @@ bool D3D11Device::Render(bool skip_present)
if (m_gpu_timing_enabled)
KickTimestampQuery();
return true;
}
@ -1487,6 +1596,321 @@ std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::Grap
primitives[static_cast<u8>(config.primitive)]));
}
D3D11Texture::D3D11Texture() = default;
D3D11Texture::D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv,
ComPtr<ID3D11View> rtv)
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_rtv_dsv(std::move(rtv))
{
const D3D11_TEXTURE2D_DESC desc = GetDesc();
m_width = static_cast<u16>(desc.Width);
m_height = static_cast<u16>(desc.Height);
m_layers = static_cast<u8>(desc.ArraySize);
m_levels = static_cast<u8>(desc.MipLevels);
m_samples = static_cast<u8>(desc.SampleDesc.Count);
m_format = LookupBaseFormat(desc.Format);
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
}
D3D11Texture::~D3D11Texture()
{
Destroy();
}
DXGI_FORMAT D3D11Texture::GetDXGIFormat(Format format)
{
return s_dxgi_mapping[static_cast<u8>(format)];
}
GPUTexture::Format D3D11Texture::LookupBaseFormat(DXGI_FORMAT dformat)
{
for (u32 i = 0; i < static_cast<u32>(s_dxgi_mapping.size()); i++)
{
if (s_dxgi_mapping[i] == dformat)
return static_cast<Format>(i);
}
return GPUTexture::Format::Unknown;
}
D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
{
D3D11_TEXTURE2D_DESC desc;
m_texture->GetDesc(&desc);
return desc;
}
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
{
if (m_state == GPUTexture::State::Dirty)
return;
// TODO: 11.1
if (IsDepthStencil())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DDSV());
else
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
}
else if (IsRenderTarget())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DRTV());
else
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
}
m_state = GPUTexture::State::Dirty;
}
bool D3D11Texture::IsValid() const
{
return static_cast<bool>(m_texture);
}
bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer /*= 0*/,
u32 level /*= 0*/)
{
if (m_dynamic)
{
void* map;
u32 map_stride;
if (!Map(&map, &map_stride, x, y, width, height, layer, level))
return false;
StringUtil::StrideMemCpy(map, map_stride, data, pitch, GetPixelSize() * width, height);
Unmap();
return true;
}
const CD3D11_BOX box(static_cast<LONG>(x), static_cast<LONG>(y), 0, static_cast<LONG>(x + width),
static_cast<LONG>(y + height), 1);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
m_state = GPUTexture::State::Dirty;
return true;
}
bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer /*= 0*/,
u32 level /*= 0*/)
{
if (!m_dynamic || (x + width) > m_width || (y + height) > m_height || layer > m_layers || level > m_levels)
return false;
const bool discard = (width == m_width && height == m_height);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
D3D11_MAPPED_SUBRESOURCE sr;
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
return false;
}
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
*map_stride = sr.RowPitch;
m_mapped_subresource = srnum;
m_state = GPUTexture::State::Dirty;
return true;
}
void D3D11Texture::Unmap()
{
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), m_mapped_subresource);
m_mapped_subresource = 0;
}
bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
Format format, const void* initial_data /* = nullptr */, u32 initial_data_stride /* = 0 */,
bool dynamic /* = false */)
{
if (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ||
layers > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION || (layers > 1 && samples > 1))
{
Log_ErrorPrintf("Texture bounds (%ux%ux%u, %u mips, %u samples) are too large", width, height, layers, levels,
samples);
return false;
}
u32 bind_flags = 0;
switch (type)
{
case Type::RenderTarget:
bind_flags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
break;
case Type::DepthStencil:
bind_flags = D3D11_BIND_DEPTH_STENCIL; // | D3D11_BIND_SHADER_RESOURCE;
break;
case Type::Texture:
bind_flags = D3D11_BIND_SHADER_RESOURCE;
break;
case Type::RWTexture:
bind_flags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
break;
default:
break;
}
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormat(format), width, height, layers, levels, bind_flags,
dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, dynamic ? D3D11_CPU_ACCESS_WRITE : 0,
samples, 0, 0);
D3D11_SUBRESOURCE_DATA srd;
srd.pSysMem = initial_data;
srd.SysMemPitch = initial_data_stride;
srd.SysMemSlicePitch = initial_data_stride * height;
ComPtr<ID3D11Texture2D> texture;
const HRESULT tex_hr = device->CreateTexture2D(&desc, initial_data ? &srd : nullptr, texture.GetAddressOf());
if (FAILED(tex_hr))
{
Log_ErrorPrintf(
"Create texture failed: 0x%08X (%ux%u levels:%u samples:%u format:%u bind_flags:%X initial_data:%p)", tex_hr,
width, height, levels, samples, static_cast<unsigned>(format), bind_flags, initial_data);
return false;
}
ComPtr<ID3D11ShaderResourceView> srv;
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
{
const D3D11_SRV_DIMENSION srv_dimension =
(desc.SampleDesc.Count > 1) ?
D3D11_SRV_DIMENSION_TEXTURE2DMS :
(desc.ArraySize > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D);
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create SRV for texture failed: 0x%08X", hr);
return false;
}
}
ComPtr<ID3D11View> rtv_dsv;
if (bind_flags & D3D11_BIND_RENDER_TARGET)
{
const D3D11_RTV_DIMENSION rtv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11RenderTargetView> rtv;
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create RTV for texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(rtv);
}
else if (bind_flags & D3D11_BIND_DEPTH_STENCIL)
{
const D3D11_DSV_DIMENSION dsv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11DepthStencilView> dsv;
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create DSV for texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(dsv);
}
m_texture = std::move(texture);
m_srv = std::move(srv);
m_rtv_dsv = std::move(rtv_dsv);
m_width = static_cast<u16>(width);
m_height = static_cast<u16>(height);
m_layers = static_cast<u8>(layers);
m_levels = static_cast<u8>(levels);
m_samples = static_cast<u8>(samples);
m_format = format;
m_dynamic = dynamic;
return true;
}
bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
{
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
ComPtr<ID3D11ShaderResourceView> srv;
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
{
const D3D11_SRV_DIMENSION srv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create SRV for adopted texture failed: 0x%08X", hr);
return false;
}
}
ComPtr<ID3D11View> rtv_dsv;
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
{
const D3D11_RTV_DIMENSION rtv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11RenderTargetView> rtv;
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create RTV for adopted texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(rtv);
}
else if (desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
{
const D3D11_DSV_DIMENSION dsv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11DepthStencilView> dsv;
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create DSV for adopted texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(dsv);
}
m_texture = std::move(texture);
m_srv = std::move(srv);
m_rtv_dsv = std::move(rtv_dsv);
m_width = static_cast<u16>(desc.Width);
m_height = static_cast<u16>(desc.Height);
m_layers = static_cast<u8>(desc.ArraySize);
m_levels = static_cast<u8>(desc.MipLevels);
m_samples = static_cast<u8>(desc.SampleDesc.Count);
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
m_state = GPUTexture::State::Dirty;
return true;
}
void D3D11Texture::Destroy()
{
m_rtv_dsv.Reset();
m_srv.Reset();
m_texture.Reset();
m_dynamic = false;
ClearBaseProperties();
}
void D3D11Device::PushDebugGroup(const char* fmt, ...)
{
if (!m_annotation)

View File

@ -6,8 +6,6 @@
#include "common/timer.h"
#include "common/window_info.h"
#include "common/windows_headers.h"
#include "d3d11/stream_buffer.h"
#include "d3d11_texture.h"
#include "gpu_device.h"
#include "postprocessing_chain.h"
#include <d3d11_1.h>
@ -21,6 +19,43 @@
class D3D11Device;
class D3D11StreamBuffer
{
public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
D3D11StreamBuffer();
D3D11StreamBuffer(ComPtr<ID3D11Buffer> buffer);
~D3D11StreamBuffer();
ALWAYS_INLINE ID3D11Buffer* GetD3DBuffer() const { return m_buffer.Get(); }
ALWAYS_INLINE ID3D11Buffer* const* GetD3DBufferArray() const { return m_buffer.GetAddressOf(); }
ALWAYS_INLINE u32 GetSize() const { return m_size; }
ALWAYS_INLINE u32 GetPosition() const { return m_position; }
bool Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size);
void Adopt(ComPtr<ID3D11Buffer> buffer);
void Release();
struct MappingResult
{
void* pointer;
u32 buffer_offset;
u32 index_aligned; // offset / alignment, suitable for base vertex
u32 space_aligned; // remaining space / alignment
};
MappingResult Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size);
void Unmap(ID3D11DeviceContext* context, u32 used_size);
private:
ComPtr<ID3D11Buffer> m_buffer;
u32 m_size;
u32 m_position;
bool m_use_map_no_overwrite = false;
};
class D3D11Framebuffer final : public GPUFramebuffer
{
friend D3D11Device;
@ -126,6 +161,74 @@ private:
D3D11_PRIMITIVE_TOPOLOGY m_topology;
};
class D3D11Texture final : public GPUTexture
{
friend D3D11Device;
public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
D3D11Texture();
D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, ComPtr<ID3D11View> rtv);
~D3D11Texture();
static DXGI_FORMAT GetDXGIFormat(Format format);
static Format LookupBaseFormat(DXGI_FORMAT dformat);
ALWAYS_INLINE ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); }
ALWAYS_INLINE ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
ALWAYS_INLINE ID3D11RenderTargetView* GetD3DRTV() const
{
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE ID3D11DepthStencilView* GetD3DDSV() const
{
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE ID3D11ShaderResourceView* const* GetD3DSRVArray() const { return m_srv.GetAddressOf(); }
ALWAYS_INLINE ID3D11RenderTargetView* const* GetD3DRTVArray() const
{
return reinterpret_cast<ID3D11RenderTargetView* const*>(m_rtv_dsv.GetAddressOf());
}
ALWAYS_INLINE DXGI_FORMAT GetDXGIFormat() const { return GetDXGIFormat(m_format); }
ALWAYS_INLINE bool IsDynamic() const { return m_dynamic; }
ALWAYS_INLINE operator ID3D11Texture2D*() const { return m_texture.Get(); }
ALWAYS_INLINE operator ID3D11ShaderResourceView*() const { return m_srv.Get(); }
ALWAYS_INLINE operator ID3D11RenderTargetView*() const
{
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE operator ID3D11DepthStencilView*() const
{
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE operator bool() const { return static_cast<bool>(m_texture); }
bool Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
Format format, const void* initial_data = nullptr, u32 initial_data_stride = 0, bool dynamic = false);
bool Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture);
void Destroy();
D3D11_TEXTURE2D_DESC GetDesc() const;
void CommitClear(ID3D11DeviceContext* context);
bool IsValid() const override;
bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override;
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
void Unmap() override;
private:
ComPtr<ID3D11Texture2D> m_texture;
ComPtr<ID3D11ShaderResourceView> m_srv;
ComPtr<ID3D11View> m_rtv_dsv;
u32 m_mapped_subresource = 0;
bool m_dynamic = false;
};
class D3D11Device final : public GPUDevice
{
public:
@ -278,9 +381,9 @@ private:
bool m_using_flip_model_swap_chain = true;
bool m_using_allow_tearing = false;
D3D11::StreamBuffer m_vertex_buffer;
D3D11::StreamBuffer m_index_buffer;
D3D11::StreamBuffer m_uniform_buffer;
D3D11StreamBuffer m_vertex_buffer;
D3D11StreamBuffer m_index_buffer;
D3D11StreamBuffer m_uniform_buffer;
D3D11Framebuffer* m_current_framebuffer = nullptr;
D3D11Pipeline* m_current_pipeline = nullptr;

View File

@ -1,329 +0,0 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "d3d11_texture.h"
#include "common/assert.h"
#include "common/log.h"
#include "common/string_util.h"
#include "d3d11_device.h"
#include <array>
Log_SetChannel(D3D11);
static constexpr std::array<DXGI_FORMAT, static_cast<u32>(GPUTexture::Format::Count)> s_dxgi_mapping = {
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B5G6R5_UNORM,
DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_D16_UNORM}};
D3D11Texture::D3D11Texture() = default;
D3D11Texture::D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv,
ComPtr<ID3D11View> rtv)
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_rtv_dsv(std::move(rtv))
{
const D3D11_TEXTURE2D_DESC desc = GetDesc();
m_width = static_cast<u16>(desc.Width);
m_height = static_cast<u16>(desc.Height);
m_layers = static_cast<u8>(desc.ArraySize);
m_levels = static_cast<u8>(desc.MipLevels);
m_samples = static_cast<u8>(desc.SampleDesc.Count);
m_format = LookupBaseFormat(desc.Format);
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
}
D3D11Texture::~D3D11Texture()
{
Destroy();
}
DXGI_FORMAT D3D11Texture::GetDXGIFormat(Format format)
{
return s_dxgi_mapping[static_cast<u8>(format)];
}
GPUTexture::Format D3D11Texture::LookupBaseFormat(DXGI_FORMAT dformat)
{
for (u32 i = 0; i < static_cast<u32>(s_dxgi_mapping.size()); i++)
{
if (s_dxgi_mapping[i] == dformat)
return static_cast<Format>(i);
}
return GPUTexture::Format::Unknown;
}
D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
{
D3D11_TEXTURE2D_DESC desc;
m_texture->GetDesc(&desc);
return desc;
}
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
{
if (m_state == GPUTexture::State::Dirty)
return;
// TODO: 11.1
if (IsDepthStencil())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DDSV());
else
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
}
else if (IsRenderTarget())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DRTV());
else
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
}
m_state = GPUTexture::State::Dirty;
}
bool D3D11Texture::IsValid() const
{
return static_cast<bool>(m_texture);
}
bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer /*= 0*/,
u32 level /*= 0*/)
{
if (m_dynamic)
{
void* map;
u32 map_stride;
if (!Map(&map, &map_stride, x, y, width, height, layer, level))
return false;
StringUtil::StrideMemCpy(map, map_stride, data, pitch, GetPixelSize() * width, height);
Unmap();
return true;
}
const CD3D11_BOX box(static_cast<LONG>(x), static_cast<LONG>(y), 0, static_cast<LONG>(x + width),
static_cast<LONG>(y + height), 1);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
m_state = GPUTexture::State::Dirty;
return true;
}
bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer /*= 0*/,
u32 level /*= 0*/)
{
if (!m_dynamic || (x + width) > m_width || (y + height) > m_height || layer > m_layers || level > m_levels)
return false;
const bool discard = (width == m_width && height == m_height);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
D3D11_MAPPED_SUBRESOURCE sr;
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
return false;
}
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
*map_stride = sr.RowPitch;
m_mapped_subresource = srnum;
m_state = GPUTexture::State::Dirty;
return true;
}
void D3D11Texture::Unmap()
{
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), m_mapped_subresource);
m_mapped_subresource = 0;
}
bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
Format format, const void* initial_data /* = nullptr */, u32 initial_data_stride /* = 0 */,
bool dynamic /* = false */)
{
if (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ||
layers > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION || (layers > 1 && samples > 1))
{
Log_ErrorPrintf("Texture bounds (%ux%ux%u, %u mips, %u samples) are too large", width, height, layers, levels,
samples);
return false;
}
u32 bind_flags = 0;
switch (type)
{
case Type::RenderTarget:
bind_flags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
break;
case Type::DepthStencil:
bind_flags = D3D11_BIND_DEPTH_STENCIL; // | D3D11_BIND_SHADER_RESOURCE;
break;
case Type::Texture:
bind_flags = D3D11_BIND_SHADER_RESOURCE;
break;
case Type::RWTexture:
bind_flags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
break;
default:
break;
}
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormat(format), width, height, layers, levels, bind_flags,
dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, dynamic ? D3D11_CPU_ACCESS_WRITE : 0,
samples, 0, 0);
D3D11_SUBRESOURCE_DATA srd;
srd.pSysMem = initial_data;
srd.SysMemPitch = initial_data_stride;
srd.SysMemSlicePitch = initial_data_stride * height;
ComPtr<ID3D11Texture2D> texture;
const HRESULT tex_hr = device->CreateTexture2D(&desc, initial_data ? &srd : nullptr, texture.GetAddressOf());
if (FAILED(tex_hr))
{
Log_ErrorPrintf(
"Create texture failed: 0x%08X (%ux%u levels:%u samples:%u format:%u bind_flags:%X initial_data:%p)", tex_hr,
width, height, levels, samples, static_cast<unsigned>(format), bind_flags, initial_data);
return false;
}
ComPtr<ID3D11ShaderResourceView> srv;
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
{
const D3D11_SRV_DIMENSION srv_dimension =
(desc.SampleDesc.Count > 1) ?
D3D11_SRV_DIMENSION_TEXTURE2DMS :
(desc.ArraySize > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D);
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create SRV for texture failed: 0x%08X", hr);
return false;
}
}
ComPtr<ID3D11View> rtv_dsv;
if (bind_flags & D3D11_BIND_RENDER_TARGET)
{
const D3D11_RTV_DIMENSION rtv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11RenderTargetView> rtv;
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create RTV for texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(rtv);
}
else if (bind_flags & D3D11_BIND_DEPTH_STENCIL)
{
const D3D11_DSV_DIMENSION dsv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11DepthStencilView> dsv;
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create DSV for texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(dsv);
}
m_texture = std::move(texture);
m_srv = std::move(srv);
m_rtv_dsv = std::move(rtv_dsv);
m_width = static_cast<u16>(width);
m_height = static_cast<u16>(height);
m_layers = static_cast<u8>(layers);
m_levels = static_cast<u8>(levels);
m_samples = static_cast<u8>(samples);
m_format = format;
m_dynamic = dynamic;
return true;
}
bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
{
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
ComPtr<ID3D11ShaderResourceView> srv;
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
{
const D3D11_SRV_DIMENSION srv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create SRV for adopted texture failed: 0x%08X", hr);
return false;
}
}
ComPtr<ID3D11View> rtv_dsv;
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
{
const D3D11_RTV_DIMENSION rtv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11RenderTargetView> rtv;
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create RTV for adopted texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(rtv);
}
else if (desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
{
const D3D11_DSV_DIMENSION dsv_dimension =
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
ComPtr<ID3D11DepthStencilView> dsv;
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Create DSV for adopted texture failed: 0x%08X", hr);
return false;
}
rtv_dsv = std::move(dsv);
}
m_texture = std::move(texture);
m_srv = std::move(srv);
m_rtv_dsv = std::move(rtv_dsv);
m_width = static_cast<u16>(desc.Width);
m_height = static_cast<u16>(desc.Height);
m_layers = static_cast<u8>(desc.ArraySize);
m_levels = static_cast<u8>(desc.MipLevels);
m_samples = static_cast<u8>(desc.SampleDesc.Count);
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
m_state = GPUTexture::State::Dirty;
return true;
}
void D3D11Texture::Destroy()
{
m_rtv_dsv.Reset();
m_srv.Reset();
m_texture.Reset();
m_dynamic = false;
ClearBaseProperties();
}

View File

@ -1,78 +0,0 @@
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/windows_headers.h"
#include "gpu_texture.h"
#include <d3d11.h>
#include <wrl/client.h>
class D3D11Device;
class D3D11Texture final : public GPUTexture
{
friend D3D11Device;
public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
D3D11Texture();
D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, ComPtr<ID3D11View> rtv);
~D3D11Texture();
static DXGI_FORMAT GetDXGIFormat(Format format);
static Format LookupBaseFormat(DXGI_FORMAT dformat);
ALWAYS_INLINE ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); }
ALWAYS_INLINE ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
ALWAYS_INLINE ID3D11RenderTargetView* GetD3DRTV() const
{
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE ID3D11DepthStencilView* GetD3DDSV() const
{
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE ID3D11ShaderResourceView* const* GetD3DSRVArray() const { return m_srv.GetAddressOf(); }
ALWAYS_INLINE ID3D11RenderTargetView* const* GetD3DRTVArray() const
{
return reinterpret_cast<ID3D11RenderTargetView* const*>(m_rtv_dsv.GetAddressOf());
}
ALWAYS_INLINE DXGI_FORMAT GetDXGIFormat() const { return GetDXGIFormat(m_format); }
ALWAYS_INLINE bool IsDynamic() const { return m_dynamic; }
ALWAYS_INLINE operator ID3D11Texture2D*() const { return m_texture.Get(); }
ALWAYS_INLINE operator ID3D11ShaderResourceView*() const { return m_srv.Get(); }
ALWAYS_INLINE operator ID3D11RenderTargetView*() const
{
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE operator ID3D11DepthStencilView*() const
{
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
}
ALWAYS_INLINE operator bool() const { return static_cast<bool>(m_texture); }
bool Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
Format format, const void* initial_data = nullptr, u32 initial_data_stride = 0, bool dynamic = false);
bool Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture);
void Destroy();
D3D11_TEXTURE2D_DESC GetDesc() const;
void CommitClear(ID3D11DeviceContext* context);
bool IsValid() const override;
bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override;
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
void Unmap() override;
private:
ComPtr<ID3D11Texture2D> m_texture;
ComPtr<ID3D11ShaderResourceView> m_srv;
ComPtr<ID3D11View> m_rtv_dsv;
u32 m_mapped_subresource = 0;
bool m_dynamic = false;
};

View File

@ -2,11 +2,13 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "shader_cache.h"
#include "../d3d11/shader_compiler.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/md5_digest.h"
#include "common/string_util.h"
#include <array>
#include <d3dcompiler.h>
#include <fstream>
Log_SetChannel(D3D12::ShaderCache);
namespace D3D12 {
@ -358,29 +360,86 @@ ShaderCache::ComPtr<ID3D12PipelineState> ShaderCache::GetPipelineState(ID3D12Dev
return pso;
}
static unsigned s_next_bad_shader_id = 1;
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileShader(EntryType type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug)
{
const char* target;
switch (feature_level)
{
case D3D_FEATURE_LEVEL_10_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_10_1:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_11_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_11_1:
default:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
target = targets[static_cast<int>(type)];
}
break;
}
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
ComPtr<ID3DBlob> blob;
ComPtr<ID3DBlob> error_blob;
const HRESULT hr =
D3DCompile(code.data(), code.size(), "0", nullptr, nullptr, "main", target, debug ? flags_debug : flags_non_debug,
0, blob.GetAddressOf(), error_blob.GetAddressOf());
std::string error_string;
if (error_blob)
{
error_string.append(static_cast<const char*>(error_blob->GetBufferPointer()), error_blob->GetBufferSize());
error_blob.Reset();
}
if (FAILED(hr))
{
Log_ErrorPrintf("Failed to compile '%s':\n%s", target, error_string.c_str());
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream::out | std::ofstream::binary);
if (ofs.is_open())
{
ofs << code;
ofs << "\n\nCompile as " << target << " failed: " << hr << "\n";
ofs.write(error_string.c_str(), error_string.size());
ofs.close();
}
return {};
}
if (!error_string.empty())
Log_WarningPrintf("'%s' compiled with warnings:\n%s", target, error_string.c_str());
return blob;
}
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileAndAddShaderBlob(const CacheIndexKey& key,
std::string_view shader_code)
{
ComPtr<ID3DBlob> blob;
switch (key.type)
{
case EntryType::VertexShader:
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_feature_level, shader_code,
m_debug);
break;
case EntryType::GeometryShader:
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Geometry, m_feature_level, shader_code,
m_debug);
break;
case EntryType::PixelShader:
blob =
D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_feature_level, shader_code, m_debug);
break;
default:
break;
}
ComPtr<ID3DBlob> blob = CompileShader(key.type, m_feature_level, shader_code, m_debug);
if (!blob)
return {};

View File

@ -87,6 +87,8 @@ private:
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
static ComPtr<ID3DBlob> CompileShader(EntryType type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug);
static std::string GetCacheBaseFileName(const std::string_view& base_path, const std::string_view& type,
D3D_FEATURE_LEVEL feature_level, bool debug);
static CacheIndexKey GetShaderCacheKey(EntryType type, const std::string_view& shader_code);

View File

@ -6,7 +6,6 @@
#include "common/assert.h"
#include "common/log.h"
#include "common/string_util.h"
#include "d3d11/shader_compiler.h"
#include "d3d12/context.h"
#include "d3d12/shader_cache.h"
#include "d3d12/util.h"

View File

@ -4,14 +4,7 @@
#include "gpu_hw_d3d11.h"
#include "common/assert.h"
#include "common/log.h"
#include "common/timer.h"
#include "gpu/d3d11_device.h"
#include "gpu/gpu_device.h"
#include "gpu_hw_shadergen.h"
#include "gpu_sw_backend.h"
#include "shader_cache_version.h"
#include "system.h"
#include "util/state_wrapper.h"
Log_SetChannel(GPU_HW_D3D11);
GPU_HW_D3D11::GPU_HW_D3D11() = default;

View File

@ -2,15 +2,8 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "gpu/d3d11/shader_cache.h"
#include "gpu/d3d11/stream_buffer.h"
#include "gpu/d3d11_texture.h"
#include "gpu/d3d11_device.h"
#include "gpu_hw.h"
#include <array>
#include <d3d11.h>
#include <memory>
#include <tuple>
#include <wrl/client.h>
class GPU_HW_D3D11 final : public GPU_HW
{
@ -33,7 +26,7 @@ private:
bool CreateTextureBuffer();
D3D11::StreamBuffer m_texture_stream_buffer;
D3D11StreamBuffer m_texture_stream_buffer;
ComPtr<ID3D11ShaderResourceView> m_texture_stream_buffer_srv_r16ui;
};

View File

@ -7,7 +7,6 @@
#include "common/log.h"
#include "common/scoped_guard.h"
#include "common/timer.h"
#include "gpu/d3d11/shader_compiler.h"
#include "gpu/d3d12/context.h"
#include "gpu/d3d12/descriptor_heap_manager.h"
#include "gpu/d3d12/shader_cache.h"
@ -214,7 +213,7 @@ void GPU_HW_D3D12::SetCapabilities()
m_max_resolution_scale = max_texture_scale;
m_max_multisamples = 1;
for (u32 multisamples = 2; multisamples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; multisamples++)
for (u32 multisamples = 2; multisamples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; multisamples++)
{
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS fd = {DXGI_FORMAT_R8G8B8A8_UNORM, static_cast<UINT>(multisamples)};