More abstraction
This commit is contained in:
parent
dbf31ff75d
commit
de08feeffb
|
@ -15,8 +15,6 @@ add_library(common
|
|||
fifo_queue.h
|
||||
file_system.cpp
|
||||
file_system.h
|
||||
gpu_texture.cpp
|
||||
gpu_texture.h
|
||||
image.cpp
|
||||
image.h
|
||||
hash_combine.h
|
||||
|
@ -66,28 +64,6 @@ target_link_libraries(common PRIVATE stb libchdr zlib minizip Zstd::Zstd "${CMAK
|
|||
|
||||
if(WIN32)
|
||||
target_sources(common PRIVATE
|
||||
d3d12/context.cpp
|
||||
d3d12/context.h
|
||||
d3d12/descriptor_heap_manager.cpp
|
||||
d3d12/descriptor_heap_manager.h
|
||||
d3d12/shader_cache.cpp
|
||||
d3d12/shader_cache.h
|
||||
d3d12/staging_texture.cpp
|
||||
d3d12/staging_texture.h
|
||||
d3d12/stream_buffer.cpp
|
||||
d3d12/stream_buffer.h
|
||||
d3d12/texture.cpp
|
||||
d3d12/texture.h
|
||||
d3d12/util.cpp
|
||||
d3d12/util.h
|
||||
d3d11/shader_cache.cpp
|
||||
d3d11/shader_cache.h
|
||||
d3d11/shader_compiler.cpp
|
||||
d3d11/shader_compiler.h
|
||||
d3d11/stream_buffer.cpp
|
||||
d3d11/stream_buffer.h
|
||||
d3d11/texture.cpp
|
||||
d3d11/texture.h
|
||||
http_downloader_winhttp.cpp
|
||||
http_downloader_winhttp.h
|
||||
thirdparty/StackWalker.cpp
|
||||
|
@ -113,147 +89,6 @@ if(ANDROID)
|
|||
target_link_libraries(common PRIVATE log)
|
||||
endif()
|
||||
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/x11_window.cpp
|
||||
gl/x11_window.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_X11=1")
|
||||
target_include_directories(common PRIVATE "${X11_INCLUDE_DIR}" "${X11_Xrandr_INCLUDE_PATH}")
|
||||
target_link_libraries(common PRIVATE "${X11_LIBRARIES}" "${X11_Xrandr_LIB}")
|
||||
endif()
|
||||
|
||||
if(USE_WAYLAND)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_WAYLAND=1")
|
||||
elseif(SUPPORTS_WAYLAND)
|
||||
message(WARNING "Wayland support for renderers is disabled.\nDuckStation will FAIL to start on Wayland.")
|
||||
endif()
|
||||
|
||||
if(USE_DRMKMS)
|
||||
target_sources(common PRIVATE
|
||||
drm_display.cpp
|
||||
drm_display.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC Libdrm::Libdrm)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENGL)
|
||||
target_sources(common PRIVATE
|
||||
gl/context.cpp
|
||||
gl/context.h
|
||||
gl/program.cpp
|
||||
gl/program.h
|
||||
gl/shader_cache.cpp
|
||||
gl/shader_cache.h
|
||||
gl/stream_buffer.cpp
|
||||
gl/stream_buffer.h
|
||||
gl/texture.cpp
|
||||
gl/texture.h
|
||||
)
|
||||
target_compile_definitions(common PUBLIC "WITH_OPENGL=1")
|
||||
target_link_libraries(common PRIVATE glad)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_wgl.cpp
|
||||
gl/context_wgl.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(USE_EGL)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl.cpp
|
||||
gl/context_egl.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_EGL=1")
|
||||
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_x11.cpp
|
||||
gl/context_egl_x11.h
|
||||
)
|
||||
|
||||
# We set EGL_NO_X11 because otherwise X comes in with its macros and breaks
|
||||
# a bunch of files from compiling, if we include the EGL headers. This just
|
||||
# makes the data types opaque, we can still use it with X11 if needed.
|
||||
target_compile_definitions(common PRIVATE "-DEGL_NO_X11=1")
|
||||
endif()
|
||||
if(ANDROID AND USE_EGL)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_android.cpp
|
||||
gl/context_egl_android.h
|
||||
)
|
||||
endif()
|
||||
if(USE_DRMKMS)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_GBM=1")
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_gbm.cpp
|
||||
gl/context_egl_gbm.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC GBM::GBM)
|
||||
endif()
|
||||
if(USE_FBDEV)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_FBDEV=1")
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_fbdev.cpp
|
||||
gl/context_egl_fbdev.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_glx.cpp
|
||||
gl/context_glx.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_GLX=1")
|
||||
endif()
|
||||
|
||||
if(USE_WAYLAND)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_wayland.cpp
|
||||
gl/context_egl_wayland.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_agl.mm
|
||||
gl/context_agl.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
target_sources(common PRIVATE
|
||||
vulkan/builders.cpp
|
||||
vulkan/builders.h
|
||||
vulkan/context.cpp
|
||||
vulkan/context.h
|
||||
vulkan/loader.h
|
||||
vulkan/loader.cpp
|
||||
vulkan/shader_cache.cpp
|
||||
vulkan/shader_cache.h
|
||||
vulkan/shader_compiler.cpp
|
||||
vulkan/shader_compiler.h
|
||||
vulkan/stream_buffer.cpp
|
||||
vulkan/stream_buffer.h
|
||||
vulkan/swap_chain.cpp
|
||||
vulkan/swap_chain.h
|
||||
vulkan/texture.cpp
|
||||
vulkan/texture.h
|
||||
vulkan/util.cpp
|
||||
vulkan/util.h
|
||||
)
|
||||
target_compile_definitions(common PUBLIC "WITH_VULKAN=1")
|
||||
target_link_libraries(common PRIVATE glslang)
|
||||
|
||||
if(APPLE)
|
||||
# Needed for Vulkan Swap Chain.
|
||||
target_link_libraries(common PRIVATE "objc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
# We need -lrt for shm_unlink
|
||||
target_link_libraries(common PRIVATE rt)
|
||||
|
|
|
@ -54,8 +54,6 @@ add_library(core
|
|||
gte_types.h
|
||||
host.cpp
|
||||
host.h
|
||||
host_display.cpp
|
||||
host_display.h
|
||||
host_interface_progress_callback.cpp
|
||||
host_interface_progress_callback.h
|
||||
host_settings.h
|
||||
|
@ -122,6 +120,47 @@ target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
|||
target_link_libraries(core PUBLIC Threads::Threads common util zlib)
|
||||
target_link_libraries(core PRIVATE stb xxhash imgui rapidjson tinyxml2)
|
||||
|
||||
target_sources(core PRIVATE
|
||||
gpu/gpu_device.cpp
|
||||
gpu/gpu_device.h
|
||||
gpu/gpu_pipeline.h
|
||||
gpu/gpu_shader.h
|
||||
gpu/gpu_texture.cpp
|
||||
gpu/gpu_texture.h
|
||||
gpu/postprocessing_chain.cpp
|
||||
gpu/postprocessing_chain.h
|
||||
gpu/postprocessing_shader.cpp
|
||||
gpu/postprocessing_shader.h
|
||||
gpu/postprocessing_shadergen.cpp
|
||||
gpu/postprocessing_shadergen.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(core PRIVATE
|
||||
d3d12/context.cpp
|
||||
d3d12/context.h
|
||||
d3d12/descriptor_heap_manager.cpp
|
||||
d3d12/descriptor_heap_manager.h
|
||||
d3d12/shader_cache.cpp
|
||||
d3d12/shader_cache.h
|
||||
d3d12/staging_texture.cpp
|
||||
d3d12/staging_texture.h
|
||||
d3d12/stream_buffer.cpp
|
||||
d3d12/stream_buffer.h
|
||||
d3d12/texture.cpp
|
||||
d3d12/texture.h
|
||||
d3d12/util.cpp
|
||||
d3d12/util.h
|
||||
d3d11/shader_cache.cpp
|
||||
d3d11/shader_cache.h
|
||||
d3d11/shader_compiler.cpp
|
||||
d3d11/shader_compiler.h
|
||||
d3d11/stream_buffer.cpp
|
||||
d3d11/stream_buffer.h
|
||||
d3d11/texture.cpp
|
||||
d3d11/texture.h
|
||||
)
|
||||
endif()
|
||||
if(WIN32)
|
||||
target_sources(core PRIVATE
|
||||
gpu_hw_d3d12.cpp
|
||||
|
@ -132,10 +171,116 @@ if(WIN32)
|
|||
target_link_libraries(core PRIVATE winmm.lib)
|
||||
endif()
|
||||
|
||||
if(ENABLE_CUBEB)
|
||||
target_compile_definitions(core PUBLIC "WITH_CUBEB=1")
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/x11_window.cpp
|
||||
gl/x11_window.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_X11=1")
|
||||
target_include_directories(common PRIVATE "${X11_INCLUDE_DIR}" "${X11_Xrandr_INCLUDE_PATH}")
|
||||
target_link_libraries(common PRIVATE "${X11_LIBRARIES}" "${X11_Xrandr_LIB}")
|
||||
endif()
|
||||
|
||||
if(USE_WAYLAND)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_WAYLAND=1")
|
||||
elseif(SUPPORTS_WAYLAND)
|
||||
message(WARNING "Wayland support for renderers is disabled.\nDuckStation will FAIL to start on Wayland.")
|
||||
endif()
|
||||
|
||||
if(USE_DRMKMS)
|
||||
target_sources(common PRIVATE
|
||||
drm_display.cpp
|
||||
drm_display.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC Libdrm::Libdrm)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENGL)
|
||||
target_sources(common PRIVATE
|
||||
gpu/gl/context.cpp
|
||||
gpu/gl/context.h
|
||||
gpu/gl/program.cpp
|
||||
gpu/gl/program.h
|
||||
gpu/gl/shader_cache.cpp
|
||||
gpu/gl/shader_cache.h
|
||||
gpu/gl/stream_buffer.cpp
|
||||
gpu/gl/stream_buffer.h
|
||||
gpu/gl/texture.cpp
|
||||
gpu/gl/texture.h
|
||||
)
|
||||
target_compile_definitions(common PUBLIC "WITH_OPENGL=1")
|
||||
target_link_libraries(common PRIVATE glad)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_wgl.cpp
|
||||
gl/context_wgl.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(USE_EGL)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl.cpp
|
||||
gl/context_egl.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_EGL=1")
|
||||
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_x11.cpp
|
||||
gl/context_egl_x11.h
|
||||
)
|
||||
|
||||
# We set EGL_NO_X11 because otherwise X comes in with its macros and breaks
|
||||
# a bunch of files from compiling, if we include the EGL headers. This just
|
||||
# makes the data types opaque, we can still use it with X11 if needed.
|
||||
target_compile_definitions(common PRIVATE "-DEGL_NO_X11=1")
|
||||
endif()
|
||||
if(ANDROID AND USE_EGL)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_android.cpp
|
||||
gl/context_egl_android.h
|
||||
)
|
||||
endif()
|
||||
if(USE_DRMKMS)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_GBM=1")
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_gbm.cpp
|
||||
gl/context_egl_gbm.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC GBM::GBM)
|
||||
endif()
|
||||
if(USE_FBDEV)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_FBDEV=1")
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_fbdev.cpp
|
||||
gl/context_egl_fbdev.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_X11)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_glx.cpp
|
||||
gl/context_glx.h
|
||||
)
|
||||
target_compile_definitions(common PRIVATE "-DUSE_GLX=1")
|
||||
endif()
|
||||
|
||||
if(USE_WAYLAND)
|
||||
target_sources(common PRIVATE
|
||||
gl/context_egl_wayland.cpp
|
||||
gl/context_egl_wayland.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_sources(common PRIVATE
|
||||
gpu/gl/context_agl.mm
|
||||
gpu/gl/context_agl.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(ENABLE_OPENGL)
|
||||
target_sources(core PRIVATE
|
||||
gpu_hw_opengl.cpp
|
||||
|
@ -144,6 +289,35 @@ if(ENABLE_OPENGL)
|
|||
target_link_libraries(core PRIVATE glad)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
target_sources(common PRIVATE
|
||||
gpu/vulkan/builders.cpp
|
||||
gpu/vulkan/builders.h
|
||||
gpu/vulkan/context.cpp
|
||||
gpu/vulkan/context.h
|
||||
gpu/vulkan/loader.h
|
||||
gpu/vulkan/loader.cpp
|
||||
gpu/vulkan/shader_cache.cpp
|
||||
gpu/vulkan/shader_cache.h
|
||||
gpu/vulkan/shader_compiler.cpp
|
||||
gpu/vulkan/shader_compiler.h
|
||||
gpu/vulkan/stream_buffer.cpp
|
||||
gpu/vulkan/stream_buffer.h
|
||||
gpu/vulkan/swap_chain.cpp
|
||||
gpu/vulkan/swap_chain.h
|
||||
gpu/vulkan/texture.cpp
|
||||
gpu/vulkan/texture.h
|
||||
gpu/vulkan/util.cpp
|
||||
gpu/vulkan/util.h
|
||||
)
|
||||
target_compile_definitions(common PUBLIC "WITH_VULKAN=1")
|
||||
target_link_libraries(common PRIVATE glslang)
|
||||
|
||||
if(APPLE)
|
||||
# Needed for Vulkan Swap Chain.
|
||||
target_link_libraries(common PRIVATE "objc")
|
||||
endif()
|
||||
endif()
|
||||
if(ENABLE_VULKAN)
|
||||
target_sources(core PRIVATE
|
||||
gpu_hw_vulkan.cpp
|
||||
|
@ -151,6 +325,10 @@ if(ENABLE_VULKAN)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_CUBEB)
|
||||
target_compile_definitions(core PUBLIC "WITH_CUBEB=1")
|
||||
endif()
|
||||
|
||||
if(${CPU_ARCH} STREQUAL "x64")
|
||||
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../dep/xbyak/xbyak")
|
||||
target_compile_definitions(core PUBLIC "WITH_RECOMPILER=1" "WITH_MMAP_FASTMEM=1")
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
<ClCompile Include="gpu\d3d11\shader_compiler.cpp" />
|
||||
<ClCompile Include="gpu\d3d11\stream_buffer.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_device.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_pipeline.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_shader.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_texture.cpp" />
|
||||
<ClCompile Include="gpu\d3d12\context.cpp" />
|
||||
<ClCompile Include="gpu\d3d12\descriptor_heap_manager.cpp" />
|
||||
|
@ -163,8 +161,6 @@
|
|||
<ClInclude Include="gpu\d3d11\shader_compiler.h" />
|
||||
<ClInclude Include="gpu\d3d11\stream_buffer.h" />
|
||||
<ClInclude Include="gpu\d3d11_device.h" />
|
||||
<ClInclude Include="gpu\d3d11_pipeline.h" />
|
||||
<ClInclude Include="gpu\d3d11_shader.h" />
|
||||
<ClInclude Include="gpu\d3d_shaders.h" />
|
||||
<ClInclude Include="gpu\d3d11_texture.h" />
|
||||
<ClInclude Include="gpu\d3d12\context.h" />
|
||||
|
@ -201,8 +197,6 @@
|
|||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\gpu_device.h" />
|
||||
<ClInclude Include="gpu\gpu_pipeline.h" />
|
||||
<ClInclude Include="gpu\gpu_shader.h" />
|
||||
<ClInclude Include="gpu\gpu_texture.h" />
|
||||
<ClInclude Include="gpu\imgui_impl_dx12.h" />
|
||||
<ClInclude Include="gpu\imgui_impl_opengl3.h" />
|
||||
|
|
|
@ -188,12 +188,6 @@
|
|||
<ClCompile Include="gpu\d3d11_texture.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11_shader.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11_pipeline.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="types.h" />
|
||||
|
@ -401,18 +395,6 @@
|
|||
<ClInclude Include="gpu\d3d_shaders.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\gpu_pipeline.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\gpu_shader.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11_shader.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11_pipeline.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="gpu">
|
||||
|
|
|
@ -558,6 +558,9 @@ bool D3D11Device::SetFullscreen(bool fullscreen, u32 width, u32 height, float re
|
|||
|
||||
bool D3D11Device::CreateResources()
|
||||
{
|
||||
if (!GPUDevice::CreateResources())
|
||||
return false;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
m_display_vertex_shader =
|
||||
|
@ -1304,3 +1307,505 @@ float D3D11Device::GetAndResetAccumulatedGPUTime()
|
|||
m_accumulated_gpu_time = 0.0f;
|
||||
return value;
|
||||
}
|
||||
|
||||
D3D11Framebuffer::D3D11Framebuffer(ComPtr<ID3D11RenderTargetView> rtv, ComPtr<ID3D11DepthStencilView> dsv)
|
||||
: m_rtv(std::move(rtv)), m_dsv(std::move(dsv))
|
||||
{
|
||||
}
|
||||
|
||||
D3D11Framebuffer::~D3D11Framebuffer() = default;
|
||||
|
||||
void D3D11Framebuffer::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
Panic("Implement me");
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUFramebuffer> D3D11Device::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level,
|
||||
GPUTexture* ds, u32 ds_layer, u32 ds_level)
|
||||
{
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
HRESULT hr;
|
||||
|
||||
if (rt)
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
|
||||
rtv_desc.Format = static_cast<D3D11Texture*>(rt)->GetDXGIFormat();
|
||||
if (rt->IsMultisampled())
|
||||
{
|
||||
Assert(rt_level == 0);
|
||||
if (rt->GetLayers() > 1)
|
||||
{
|
||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
rtv_desc.Texture2DMSArray.ArraySize = rt->GetLayers();
|
||||
rtv_desc.Texture2DMSArray.FirstArraySlice = rt_layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rt->GetLayers() > 1)
|
||||
{
|
||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtv_desc.Texture2DArray.ArraySize = rt->GetLayers();
|
||||
rtv_desc.Texture2DArray.FirstArraySlice = rt_layer;
|
||||
rtv_desc.Texture2DArray.MipSlice = rt_level;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtv_desc.Texture2D.MipSlice = rt_level;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = m_device->CreateRenderTargetView(static_cast<D3D11Texture*>(rt)->GetD3DTexture(), &rtv_desc,
|
||||
rtv.GetAddressOf())))
|
||||
{
|
||||
Log_ErrorPrintf("CreateRenderTargetView() failed: %08X", hr);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (ds)
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
|
||||
dsv_desc.Format = static_cast<D3D11Texture*>(ds)->GetDXGIFormat();
|
||||
if (ds->IsMultisampled())
|
||||
{
|
||||
Assert(rt_level == 0);
|
||||
if (ds->GetLayers() > 1)
|
||||
{
|
||||
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
dsv_desc.Texture2DMSArray.ArraySize = ds->GetLayers();
|
||||
dsv_desc.Texture2DMSArray.FirstArraySlice = rt_layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ds->GetLayers() > 1)
|
||||
{
|
||||
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsv_desc.Texture2DArray.ArraySize = ds->GetLayers();
|
||||
dsv_desc.Texture2DArray.FirstArraySlice = rt_layer;
|
||||
dsv_desc.Texture2DArray.MipSlice = rt_level;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
dsv_desc.Texture2D.MipSlice = rt_level;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = m_device->CreateDepthStencilView(static_cast<D3D11Texture*>(ds)->GetD3DTexture(), &dsv_desc,
|
||||
dsv.GetAddressOf())))
|
||||
{
|
||||
Log_ErrorPrintf("CreateDepthStencilView() failed: %08X", hr);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return std::unique_ptr<GPUFramebuffer>(new D3D11Framebuffer(std::move(rtv), std::move(dsv)));
|
||||
}
|
||||
|
||||
D3D11Sampler::D3D11Sampler(ComPtr<ID3D11SamplerState> ss) : m_ss(std::move(ss)) {}
|
||||
|
||||
D3D11Sampler::~D3D11Sampler() = default;
|
||||
|
||||
void D3D11Sampler::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
Panic("Not implemented");
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUSampler> D3D11Device::CreateSampler(const GPUSampler::Config& config)
|
||||
{
|
||||
static constexpr std::array<D3D11_TEXTURE_ADDRESS_MODE, static_cast<u8>(GPUSampler::AddressMode::MaxCount)> ta = {{
|
||||
D3D11_TEXTURE_ADDRESS_WRAP, // Repeat
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP, // ClampToEdge
|
||||
D3D11_TEXTURE_ADDRESS_BORDER, // ClampToBorder
|
||||
}};
|
||||
|
||||
D3D11_SAMPLER_DESC desc = {};
|
||||
desc.AddressU = ta[static_cast<u8>(config.address_u.GetValue())];
|
||||
desc.AddressV = ta[static_cast<u8>(config.address_v.GetValue())];
|
||||
desc.AddressW = ta[static_cast<u8>(config.address_w.GetValue())];
|
||||
desc.BorderColor[0] = static_cast<float>(config.border_color & 0xFF) / 255.0f;
|
||||
desc.BorderColor[1] = static_cast<float>((config.border_color >> 8) & 0xFF) / 255.0f;
|
||||
desc.BorderColor[2] = static_cast<float>((config.border_color >> 16) & 0xFF) / 255.0f;
|
||||
desc.BorderColor[3] = static_cast<float>((config.border_color >> 24) & 0xFF) / 255.0f;
|
||||
desc.MinLOD = static_cast<float>(config.min_lod);
|
||||
desc.MaxLOD = static_cast<float>(config.max_lod);
|
||||
|
||||
if (config.anisotropy > 0)
|
||||
{
|
||||
desc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
desc.MaxAnisotropy = config.anisotropy;
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr u8 filter_count = static_cast<u8>(GPUSampler::Filter::MaxCount);
|
||||
static constexpr D3D11_FILTER filters[filter_count][filter_count][filter_count] = {
|
||||
{
|
||||
{D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT},
|
||||
{D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT, D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT},
|
||||
},
|
||||
{
|
||||
{D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR, D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR},
|
||||
{D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, D3D11_FILTER_MIN_MAG_MIP_LINEAR},
|
||||
}};
|
||||
|
||||
desc.Filter = filters[static_cast<u8>(config.mip_filter.GetValue())][static_cast<u8>(config.min_filter.GetValue())]
|
||||
[static_cast<u8>(config.mag_filter.GetValue())];
|
||||
desc.MaxAnisotropy = 1;
|
||||
}
|
||||
|
||||
// TODO: Pool?
|
||||
ComPtr<ID3D11SamplerState> ss;
|
||||
const HRESULT hr = m_device->CreateSamplerState(&desc, ss.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("CreateSamplerState() failed: %08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::unique_ptr<GPUSampler>(new D3D11Sampler(std::move(ss)));
|
||||
}
|
||||
|
||||
D3D11Shader::D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader, std::vector<u8> bytecode)
|
||||
: GPUShader(stage), m_shader(std::move(shader)), m_bytecode(std::move(bytecode))
|
||||
{
|
||||
}
|
||||
|
||||
D3D11Shader::~D3D11Shader() = default;
|
||||
|
||||
ID3D11VertexShader* D3D11Shader::GetVertexShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Vertex);
|
||||
return static_cast<ID3D11VertexShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11PixelShader* D3D11Shader::GetPixelShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Pixel);
|
||||
return static_cast<ID3D11PixelShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11ComputeShader* D3D11Shader::GetComputeShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Compute);
|
||||
return static_cast<ID3D11ComputeShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
void D3D11Shader::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
Panic("Implement me");
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data)
|
||||
{
|
||||
ComPtr<ID3D11DeviceChild> shader;
|
||||
std::vector<u8> bytecode;
|
||||
switch (stage)
|
||||
{
|
||||
case GPUShader::Stage::Vertex:
|
||||
shader = D3D11::ShaderCompiler::CreateVertexShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
bytecode.resize(data.size());
|
||||
std::memcpy(bytecode.data(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Pixel:
|
||||
shader = D3D11::ShaderCompiler::CreatePixelShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Compute:
|
||||
shader = D3D11::ShaderCompiler::CreateComputeShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
default:
|
||||
UnreachableCode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!shader)
|
||||
return {};
|
||||
|
||||
return std::unique_ptr<GPUShader>(new D3D11Shader(stage, std::move(shader), std::move(bytecode)));
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||
std::vector<u8>* out_binary /* = nullptr */)
|
||||
{
|
||||
// TODO: This shouldn't be dependent on build type.
|
||||
#ifdef _DEBUG
|
||||
constexpr bool debug = true;
|
||||
#else
|
||||
constexpr bool debug = false;
|
||||
#endif
|
||||
|
||||
ComPtr<ID3DBlob> blob;
|
||||
switch (stage)
|
||||
{
|
||||
case GPUShader::Stage::Vertex:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Pixel:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Compute:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Compute, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
default:
|
||||
UnreachableCode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_binary)
|
||||
{
|
||||
const size_t size = blob->GetBufferSize();
|
||||
out_binary->resize(size);
|
||||
std::memcpy(out_binary->data(), blob->GetBufferPointer(), size);
|
||||
}
|
||||
|
||||
return CreateShaderFromBinary(
|
||||
stage, gsl::span<const u8>(static_cast<const u8*>(blob->GetBufferPointer()), blob->GetBufferSize()));
|
||||
}
|
||||
|
||||
D3D11Pipeline::D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds,
|
||||
ComPtr<ID3D11BlendState> bs, ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs,
|
||||
ComPtr<ID3D11PixelShader> ps, D3D11_PRIMITIVE_TOPOLOGY topology)
|
||||
: m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)),
|
||||
m_ps(std::move(ps)), m_topology(topology)
|
||||
{
|
||||
}
|
||||
|
||||
D3D11Pipeline::~D3D11Pipeline() = default;
|
||||
|
||||
void D3D11Pipeline::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void D3D11Pipeline::Bind(ID3D11DeviceContext* context)
|
||||
{
|
||||
context->IASetInputLayout(GetInputLayout());
|
||||
context->IASetPrimitiveTopology(GetPrimitiveTopology());
|
||||
context->RSSetState(GetRasterizerState());
|
||||
context->OMSetDepthStencilState(GetDepthStencilState(), 0);
|
||||
context->OMSetBlendState(GetBlendState(), nullptr, 0xFFFFFFFFu);
|
||||
context->VSSetShader(GetVertexShader(), nullptr, 0);
|
||||
context->PSSetShader(GetPixelShader(), nullptr, 0);
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> drs;
|
||||
|
||||
const auto it = m_rasterization_states.find(rs.key);
|
||||
if (it != m_rasterization_states.end())
|
||||
{
|
||||
drs = it->second;
|
||||
return drs;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_CULL_MODE, static_cast<u32>(GPUPipeline::CullMode::MaxCount)> cull_mapping = {{
|
||||
D3D11_CULL_NONE, // None
|
||||
D3D11_CULL_FRONT, // Front
|
||||
D3D11_CULL_BACK, // Back
|
||||
}};
|
||||
|
||||
D3D11_RASTERIZER_DESC desc = {};
|
||||
desc.FillMode = D3D11_FILL_SOLID;
|
||||
desc.CullMode = cull_mapping[static_cast<u8>(rs.cull_mode.GetValue())];
|
||||
desc.ScissorEnable = TRUE;
|
||||
// desc.MultisampleEnable ???
|
||||
|
||||
HRESULT hr = m_device->CreateRasterizerState(&desc, drs.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||
|
||||
m_rasterization_states.emplace(rs.key, drs);
|
||||
return drs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds)
|
||||
{
|
||||
ComPtr<ID3D11DepthStencilState> dds;
|
||||
|
||||
const auto it = m_depth_states.find(ds.key);
|
||||
if (it != m_depth_states.end())
|
||||
{
|
||||
dds = it->second;
|
||||
return dds;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_COMPARISON_FUNC, static_cast<u32>(GPUPipeline::DepthFunc::MaxCount)> func_mapping =
|
||||
{{
|
||||
D3D11_COMPARISON_NEVER, // Never
|
||||
D3D11_COMPARISON_ALWAYS, // Always
|
||||
D3D11_COMPARISON_LESS, // Less
|
||||
D3D11_COMPARISON_LESS_EQUAL, // LessEqual
|
||||
D3D11_COMPARISON_GREATER, // Greater
|
||||
D3D11_COMPARISON_GREATER_EQUAL, // GreaterEqual
|
||||
D3D11_COMPARISON_EQUAL, // Equal
|
||||
}};
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC desc = {};
|
||||
desc.DepthEnable = ds.depth_test != GPUPipeline::DepthFunc::Never;
|
||||
desc.DepthFunc = func_mapping[static_cast<u8>(ds.depth_test.GetValue())];
|
||||
desc.DepthWriteMask = ds.depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
|
||||
HRESULT hr = m_device->CreateDepthStencilState(&desc, dds.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||
|
||||
m_depth_states.emplace(ds.key, dds);
|
||||
return dds;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs)
|
||||
{
|
||||
ComPtr<ID3D11BlendState> dbs;
|
||||
|
||||
const auto it = m_blend_states.find(bs.key);
|
||||
if (it != m_blend_states.end())
|
||||
{
|
||||
dbs = it->second;
|
||||
return dbs;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_BLEND, static_cast<u32>(GPUPipeline::BlendFunc::MaxCount)> blend_mapping = {{
|
||||
D3D11_BLEND_ZERO, // Zero
|
||||
D3D11_BLEND_ONE, // One
|
||||
D3D11_BLEND_SRC_COLOR, // SrcColor
|
||||
D3D11_BLEND_INV_SRC_COLOR, // InvSrcColor
|
||||
D3D11_BLEND_DEST_COLOR, // DstColor
|
||||
D3D11_BLEND_INV_DEST_COLOR, // InvDstColor
|
||||
D3D11_BLEND_SRC_ALPHA, // SrcAlpha
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // InvSrcAlpha
|
||||
D3D11_BLEND_SRC1_ALPHA, // SrcAlpha1
|
||||
D3D11_BLEND_INV_SRC1_ALPHA, // InvSrcAlpha1
|
||||
D3D11_BLEND_DEST_ALPHA, // DstAlpha
|
||||
D3D11_BLEND_INV_DEST_ALPHA, // InvDstAlpha
|
||||
}};
|
||||
|
||||
static constexpr std::array<D3D11_BLEND_OP, static_cast<u32>(GPUPipeline::BlendOp::MaxCount)> op_mapping = {{
|
||||
D3D11_BLEND_OP_ADD, // Add
|
||||
D3D11_BLEND_OP_SUBTRACT, // Subtract
|
||||
D3D11_BLEND_OP_REV_SUBTRACT, // ReverseSubtract
|
||||
D3D11_BLEND_OP_MIN, // Min
|
||||
D3D11_BLEND_OP_MAX, // Max
|
||||
}};
|
||||
|
||||
D3D11_BLEND_DESC blend_desc = {};
|
||||
D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[0];
|
||||
tgt_desc.BlendEnable = bs.enable;
|
||||
tgt_desc.RenderTargetWriteMask = bs.write_mask;
|
||||
if (bs.enable)
|
||||
{
|
||||
tgt_desc.SrcBlend = blend_mapping[static_cast<u8>(bs.src_blend.GetValue())];
|
||||
tgt_desc.DestBlend = blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())];
|
||||
tgt_desc.BlendOp = op_mapping[static_cast<u8>(bs.blend_op.GetValue())];
|
||||
tgt_desc.SrcBlendAlpha = blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())];
|
||||
tgt_desc.DestBlendAlpha = blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())];
|
||||
tgt_desc.BlendOpAlpha = op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())];
|
||||
}
|
||||
|
||||
HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create blend state with %08X", hr);
|
||||
|
||||
m_blend_states.emplace(bs.key, dbs);
|
||||
return dbs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipeline::InputLayout& il,
|
||||
const D3D11Shader* vs)
|
||||
{
|
||||
ComPtr<ID3D11InputLayout> dil;
|
||||
const auto it = m_input_layouts.find(il);
|
||||
if (it != m_input_layouts.end())
|
||||
{
|
||||
dil = it->second;
|
||||
return dil;
|
||||
}
|
||||
|
||||
static constexpr std::array<const char*, static_cast<u32>(GPUPipeline::VertexAttribute::Semantic::MaxCount)>
|
||||
semantics = {{
|
||||
"POSITION", // Position
|
||||
"TEXCOORD", // Texcoord
|
||||
"COLOR", // Color
|
||||
}};
|
||||
|
||||
static constexpr u32 MAX_COMPONENTS = 4;
|
||||
static constexpr const DXGI_FORMAT
|
||||
format_mapping[static_cast<u8>(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = {
|
||||
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT}, // Float
|
||||
{DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UINT}, // UInt8
|
||||
{DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_SINT}, // SInt8
|
||||
{DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM}, // UNorm8
|
||||
{DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UINT}, // UInt16
|
||||
{DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_SINT}, // SInt16
|
||||
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UNORM}, // UNorm16
|
||||
{DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_UINT}, // UInt32
|
||||
{DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_SINT}, // SInt32
|
||||
};
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC* elems =
|
||||
static_cast<D3D11_INPUT_ELEMENT_DESC*>(alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * il.vertex_attributes.size()));
|
||||
for (size_t i = 0; i < il.vertex_attributes.size(); i++)
|
||||
{
|
||||
const GPUPipeline::VertexAttribute& va = il.vertex_attributes[i];
|
||||
Assert(va.components > 0 && va.components < MAX_COMPONENTS);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC& elem = elems[i];
|
||||
elem.SemanticName = semantics[static_cast<u8>(va.semantic.GetValue())];
|
||||
elem.SemanticIndex = va.semantic_index;
|
||||
elem.Format = format_mapping[static_cast<u8>(va.type.GetValue())][va.components - 1];
|
||||
elem.InputSlot = 0;
|
||||
elem.AlignedByteOffset = va.offset;
|
||||
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
elem.InstanceDataStepRate = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = m_device->CreateInputLayout(elems, static_cast<UINT>(il.vertex_attributes.size()),
|
||||
vs->GetBytecode().data(), vs->GetBytecode().size(), dil.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create input layout with %08X", hr);
|
||||
|
||||
m_input_layouts.emplace(il, dil);
|
||||
return dil;
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization);
|
||||
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth);
|
||||
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend);
|
||||
|
||||
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, static_cast<u32>(GPUPipeline::Primitive::MaxCount)> primitives =
|
||||
{{
|
||||
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, // Points
|
||||
D3D11_PRIMITIVE_TOPOLOGY_LINELIST, // Lines
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Triangles
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TriangleStrips
|
||||
}};
|
||||
|
||||
return std::unique_ptr<GPUPipeline>(
|
||||
new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), nullptr,
|
||||
static_cast<const D3D11Shader*>(config.vertex_shader)->GetVertexShader(),
|
||||
static_cast<const D3D11Shader*>(config.pixel_shader)->GetPixelShader(),
|
||||
primitives[static_cast<u8>(config.primitive)]));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "d3d11/stream_buffer.h"
|
||||
#include "d3d11_texture.h"
|
||||
#include "gpu_device.h"
|
||||
#include "gpu_pipeline.h"
|
||||
#include "postprocessing_chain.h"
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
|
@ -19,8 +18,107 @@
|
|||
#include <vector>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class D3D11Pipeline;
|
||||
class D3D11Shader;
|
||||
class D3D11Device;
|
||||
|
||||
class D3D11Framebuffer final : public GPUFramebuffer
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
public:
|
||||
~D3D11Framebuffer() override;
|
||||
|
||||
ALWAYS_INLINE ID3D11RenderTargetView* GetRTV() const { return m_rtv.Get(); }
|
||||
ALWAYS_INLINE ID3D11DepthStencilView* GetDSV() const { return m_dsv.Get(); }
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
private:
|
||||
D3D11Framebuffer(ComPtr<ID3D11RenderTargetView> rtv, ComPtr<ID3D11DepthStencilView> dsv);
|
||||
|
||||
ComPtr<ID3D11RenderTargetView> m_rtv;
|
||||
ComPtr<ID3D11DepthStencilView> m_dsv;
|
||||
};
|
||||
|
||||
class D3D11Sampler final : public GPUSampler
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
public:
|
||||
~D3D11Sampler() override;
|
||||
|
||||
ALWAYS_INLINE ID3D11SamplerState* GetSamplerState() const { return m_ss.Get(); }
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
private:
|
||||
D3D11Sampler(ComPtr<ID3D11SamplerState> ss);
|
||||
|
||||
ComPtr<ID3D11SamplerState> m_ss;
|
||||
};
|
||||
|
||||
class D3D11Shader final : public GPUShader
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
public:
|
||||
~D3D11Shader() override;
|
||||
|
||||
ID3D11VertexShader* GetVertexShader() const;
|
||||
ID3D11PixelShader* GetPixelShader() const;
|
||||
ID3D11ComputeShader* GetComputeShader() const;
|
||||
|
||||
ALWAYS_INLINE const std::vector<u8>& GetBytecode() const { return m_bytecode; }
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
private:
|
||||
D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader, std::vector<u8> bytecode);
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceChild> m_shader;
|
||||
std::vector<u8> m_bytecode; // only for VS
|
||||
};
|
||||
|
||||
class D3D11Pipeline final : public GPUPipeline
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
public:
|
||||
~D3D11Pipeline() override;
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
ALWAYS_INLINE ID3D11RasterizerState* GetRasterizerState() const { return m_rs.Get(); }
|
||||
ALWAYS_INLINE ID3D11DepthStencilState* GetDepthStencilState() const { return m_ds.Get(); }
|
||||
ALWAYS_INLINE ID3D11BlendState* GetBlendState() const { return m_bs.Get(); }
|
||||
ALWAYS_INLINE ID3D11InputLayout* GetInputLayout() const { return m_il.Get(); }
|
||||
ALWAYS_INLINE ID3D11VertexShader* GetVertexShader() const { return m_vs.Get(); }
|
||||
ALWAYS_INLINE ID3D11PixelShader* GetPixelShader() const { return m_ps.Get(); }
|
||||
ALWAYS_INLINE D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_topology; }
|
||||
|
||||
void Bind(ID3D11DeviceContext* context);
|
||||
|
||||
private:
|
||||
D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds, ComPtr<ID3D11BlendState> bs,
|
||||
ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs, ComPtr<ID3D11PixelShader> ps,
|
||||
D3D11_PRIMITIVE_TOPOLOGY topology);
|
||||
|
||||
ComPtr<ID3D11RasterizerState> m_rs;
|
||||
ComPtr<ID3D11DepthStencilState> m_ds;
|
||||
ComPtr<ID3D11BlendState> m_bs;
|
||||
ComPtr<ID3D11InputLayout> m_il;
|
||||
ComPtr<ID3D11VertexShader> m_vs;
|
||||
ComPtr<ID3D11PixelShader> m_ps;
|
||||
D3D11_PRIMITIVE_TOPOLOGY m_topology;
|
||||
};
|
||||
|
||||
class D3D11Device final : public GPUDevice
|
||||
{
|
||||
|
@ -62,6 +160,8 @@ public:
|
|||
GPUTexture::Type type, GPUTexture::Format format,
|
||||
const void* data = nullptr, u32 data_stride = 0,
|
||||
bool dynamic = false) override;
|
||||
std::unique_ptr<GPUSampler> CreateSampler(const GPUSampler::Config& config) override;
|
||||
|
||||
bool DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data,
|
||||
u32 out_data_stride) override;
|
||||
bool SupportsTextureFormat(GPUTexture::Format format) const override;
|
||||
|
@ -70,6 +170,9 @@ public:
|
|||
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
|
||||
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
|
||||
|
||||
std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, GPUTexture* ds,
|
||||
u32 ds_layer, u32 ds_level) override;
|
||||
|
||||
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data) override;
|
||||
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||
std::vector<u8>* out_binary = nullptr) override;
|
||||
|
@ -92,7 +195,8 @@ private:
|
|||
using RasterizationStateMap = std::unordered_map<u8, ComPtr<ID3D11RasterizerState>>;
|
||||
using DepthStateMap = std::unordered_map<u8, ComPtr<ID3D11DepthStencilState>>;
|
||||
using BlendStateMap = std::unordered_map<u32, ComPtr<ID3D11BlendState>>;
|
||||
using InputLayoutMap = std::unordered_map<GPUPipeline::InputLayout, ComPtr<ID3D11InputLayout>, GPUPipeline::InputLayoutHash>;
|
||||
using InputLayoutMap =
|
||||
std::unordered_map<GPUPipeline::InputLayout, ComPtr<ID3D11InputLayout>, GPUPipeline::InputLayoutHash>;
|
||||
|
||||
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 64;
|
||||
static constexpr u32 IMGUI_VERTEX_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d11_pipeline.h"
|
||||
#include "d3d11_device.h"
|
||||
#include "d3d11_shader.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
|
||||
#include <array>
|
||||
#include <malloc.h>
|
||||
|
||||
Log_SetChannel(D3D11Device);
|
||||
|
||||
D3D11Pipeline::D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds,
|
||||
ComPtr<ID3D11BlendState> bs, ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs,
|
||||
ComPtr<ID3D11PixelShader> ps, D3D11_PRIMITIVE_TOPOLOGY topology)
|
||||
: m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)),
|
||||
m_ps(std::move(ps)), m_topology(topology)
|
||||
{
|
||||
}
|
||||
|
||||
D3D11Pipeline::~D3D11Pipeline() = default;
|
||||
|
||||
void D3D11Pipeline::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void D3D11Pipeline::Bind(ID3D11DeviceContext* context)
|
||||
{
|
||||
context->IASetInputLayout(GetInputLayout());
|
||||
context->IASetPrimitiveTopology(GetPrimitiveTopology());
|
||||
context->RSSetState(GetRasterizerState());
|
||||
context->OMSetDepthStencilState(GetDepthStencilState(), 0);
|
||||
context->OMSetBlendState(GetBlendState(), nullptr, 0xFFFFFFFFu);
|
||||
context->VSSetShader(GetVertexShader(), nullptr, 0);
|
||||
context->PSSetShader(GetPixelShader(), nullptr, 0);
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> drs;
|
||||
|
||||
const auto it = m_rasterization_states.find(rs.key);
|
||||
if (it != m_rasterization_states.end())
|
||||
{
|
||||
drs = it->second;
|
||||
return drs;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_CULL_MODE, static_cast<u32>(GPUPipeline::CullMode::MaxCount)> cull_mapping = {{
|
||||
D3D11_CULL_NONE, // None
|
||||
D3D11_CULL_FRONT, // Front
|
||||
D3D11_CULL_BACK, // Back
|
||||
}};
|
||||
|
||||
D3D11_RASTERIZER_DESC desc = {};
|
||||
desc.FillMode = D3D11_FILL_SOLID;
|
||||
desc.CullMode = cull_mapping[static_cast<u8>(rs.cull_mode.GetValue())];
|
||||
desc.ScissorEnable = TRUE;
|
||||
// desc.MultisampleEnable ???
|
||||
|
||||
HRESULT hr = m_device->CreateRasterizerState(&desc, drs.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||
|
||||
m_rasterization_states.emplace(rs.key, drs);
|
||||
return drs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds)
|
||||
{
|
||||
ComPtr<ID3D11DepthStencilState> dds;
|
||||
|
||||
const auto it = m_depth_states.find(ds.key);
|
||||
if (it != m_depth_states.end())
|
||||
{
|
||||
dds = it->second;
|
||||
return dds;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_COMPARISON_FUNC, static_cast<u32>(GPUPipeline::DepthFunc::MaxCount)> func_mapping =
|
||||
{{
|
||||
D3D11_COMPARISON_NEVER, // Never
|
||||
D3D11_COMPARISON_ALWAYS, // Always
|
||||
D3D11_COMPARISON_LESS, // Less
|
||||
D3D11_COMPARISON_LESS_EQUAL, // LessEqual
|
||||
D3D11_COMPARISON_GREATER, // Greater
|
||||
D3D11_COMPARISON_GREATER_EQUAL, // GreaterEqual
|
||||
D3D11_COMPARISON_EQUAL, // Equal
|
||||
}};
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC desc = {};
|
||||
desc.DepthEnable = ds.depth_test != GPUPipeline::DepthFunc::Never;
|
||||
desc.DepthFunc = func_mapping[static_cast<u8>(ds.depth_test.GetValue())];
|
||||
desc.DepthWriteMask = ds.depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
|
||||
HRESULT hr = m_device->CreateDepthStencilState(&desc, dds.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||
|
||||
m_depth_states.emplace(ds.key, dds);
|
||||
return dds;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs)
|
||||
{
|
||||
ComPtr<ID3D11BlendState> dbs;
|
||||
|
||||
const auto it = m_blend_states.find(bs.key);
|
||||
if (it != m_blend_states.end())
|
||||
{
|
||||
dbs = it->second;
|
||||
return dbs;
|
||||
}
|
||||
|
||||
static constexpr std::array<D3D11_BLEND, static_cast<u32>(GPUPipeline::BlendFunc::MaxCount)> blend_mapping = {{
|
||||
D3D11_BLEND_ZERO, // Zero
|
||||
D3D11_BLEND_ONE, // One
|
||||
D3D11_BLEND_SRC_COLOR, // SrcColor
|
||||
D3D11_BLEND_INV_SRC_COLOR, // InvSrcColor
|
||||
D3D11_BLEND_DEST_COLOR, // DstColor
|
||||
D3D11_BLEND_INV_DEST_COLOR, // InvDstColor
|
||||
D3D11_BLEND_SRC_ALPHA, // SrcAlpha
|
||||
D3D11_BLEND_INV_SRC_ALPHA, // InvSrcAlpha
|
||||
D3D11_BLEND_SRC1_ALPHA, // SrcAlpha1
|
||||
D3D11_BLEND_INV_SRC1_ALPHA, // InvSrcAlpha1
|
||||
D3D11_BLEND_DEST_ALPHA, // DstAlpha
|
||||
D3D11_BLEND_INV_DEST_ALPHA, // InvDstAlpha
|
||||
}};
|
||||
|
||||
static constexpr std::array<D3D11_BLEND_OP, static_cast<u32>(GPUPipeline::BlendOp::MaxCount)> op_mapping = {{
|
||||
D3D11_BLEND_OP_ADD, // Add
|
||||
D3D11_BLEND_OP_SUBTRACT, // Subtract
|
||||
D3D11_BLEND_OP_REV_SUBTRACT, // ReverseSubtract
|
||||
D3D11_BLEND_OP_MIN, // Min
|
||||
D3D11_BLEND_OP_MAX, // Max
|
||||
}};
|
||||
|
||||
D3D11_BLEND_DESC blend_desc = {};
|
||||
D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[0];
|
||||
tgt_desc.BlendEnable = bs.enable;
|
||||
tgt_desc.RenderTargetWriteMask = bs.write_mask;
|
||||
if (bs.enable)
|
||||
{
|
||||
tgt_desc.SrcBlend = blend_mapping[static_cast<u8>(bs.src_blend.GetValue())];
|
||||
tgt_desc.DestBlend = blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())];
|
||||
tgt_desc.BlendOp = op_mapping[static_cast<u8>(bs.blend_op.GetValue())];
|
||||
tgt_desc.SrcBlendAlpha = blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())];
|
||||
tgt_desc.DestBlendAlpha = blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())];
|
||||
tgt_desc.BlendOpAlpha = op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())];
|
||||
}
|
||||
|
||||
HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create blend state with %08X", hr);
|
||||
|
||||
m_blend_states.emplace(bs.key, dbs);
|
||||
return dbs;
|
||||
}
|
||||
|
||||
D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipeline::InputLayout& il,
|
||||
const D3D11Shader* vs)
|
||||
{
|
||||
ComPtr<ID3D11InputLayout> dil;
|
||||
const auto it = m_input_layouts.find(il);
|
||||
if (it != m_input_layouts.end())
|
||||
{
|
||||
dil = it->second;
|
||||
return dil;
|
||||
}
|
||||
|
||||
static constexpr std::array<const char*, static_cast<u32>(GPUPipeline::VertexAttribute::Semantic::MaxCount)>
|
||||
semantics = {{
|
||||
"POSITION", // Position
|
||||
"TEXCOORD", // Texcoord
|
||||
"COLOR", // Color
|
||||
}};
|
||||
|
||||
static constexpr u32 MAX_COMPONENTS = 4;
|
||||
static constexpr const DXGI_FORMAT
|
||||
format_mapping[static_cast<u8>(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = {
|
||||
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT}, // Float
|
||||
{DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UINT}, // UInt8
|
||||
{DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_SINT}, // SInt8
|
||||
{DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM}, // UNorm8
|
||||
{DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UINT}, // UInt16
|
||||
{DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_SINT}, // SInt16
|
||||
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UNORM}, // UNorm16
|
||||
{DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_UINT}, // UInt32
|
||||
{DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_SINT}, // SInt32
|
||||
};
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC* elems =
|
||||
static_cast<D3D11_INPUT_ELEMENT_DESC*>(alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * il.vertex_attributes.size()));
|
||||
for (size_t i = 0; i < il.vertex_attributes.size(); i++)
|
||||
{
|
||||
const GPUPipeline::VertexAttribute& va = il.vertex_attributes[i];
|
||||
Assert(va.components > 0 && va.components < MAX_COMPONENTS);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC& elem = elems[i];
|
||||
elem.SemanticName = semantics[static_cast<u8>(va.semantic.GetValue())];
|
||||
elem.SemanticIndex = va.semantic_index;
|
||||
elem.Format = format_mapping[static_cast<u8>(va.type.GetValue())][va.components - 1];
|
||||
elem.InputSlot = 0;
|
||||
elem.AlignedByteOffset = va.offset;
|
||||
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
elem.InstanceDataStepRate = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = m_device->CreateInputLayout(elems, static_cast<UINT>(il.vertex_attributes.size()),
|
||||
vs->GetBytecode().data(), vs->GetBytecode().size(), dil.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("Failed to create input layout with %08X", hr);
|
||||
|
||||
m_input_layouts.emplace(il, dil);
|
||||
return dil;
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||
{
|
||||
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization);
|
||||
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth);
|
||||
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend);
|
||||
|
||||
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, static_cast<u32>(GPUPipeline::Primitive::MaxCount)> primitives =
|
||||
{{
|
||||
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, // Points
|
||||
D3D11_PRIMITIVE_TOPOLOGY_LINELIST, // Lines
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Triangles
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TriangleStrips
|
||||
}};
|
||||
|
||||
return std::unique_ptr<GPUPipeline>(
|
||||
new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), nullptr,
|
||||
static_cast<const D3D11Shader*>(config.vertex_shader)->GetD3DVertexShader(),
|
||||
static_cast<const D3D11Shader*>(config.pixel_shader)->GetD3DPixelShader(),
|
||||
primitives[static_cast<u8>(config.primitive)]));
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gpu_pipeline.h"
|
||||
|
||||
#include "common/windows_headers.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "gsl/span"
|
||||
|
||||
class D3D11Device;
|
||||
|
||||
class D3D11Pipeline final : public GPUPipeline
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
public:
|
||||
~D3D11Pipeline() override;
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
ALWAYS_INLINE ID3D11RasterizerState* GetRasterizerState() const { return m_rs.Get(); }
|
||||
ALWAYS_INLINE ID3D11DepthStencilState* GetDepthStencilState() const { return m_ds.Get(); }
|
||||
ALWAYS_INLINE ID3D11BlendState* GetBlendState() const { return m_bs.Get(); }
|
||||
ALWAYS_INLINE ID3D11InputLayout* GetInputLayout() const { return m_il.Get(); }
|
||||
ALWAYS_INLINE ID3D11VertexShader* GetVertexShader() const { return m_vs.Get(); }
|
||||
ALWAYS_INLINE ID3D11PixelShader* GetPixelShader() const { return m_ps.Get(); }
|
||||
ALWAYS_INLINE D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_topology; }
|
||||
|
||||
void Bind(ID3D11DeviceContext* context);
|
||||
|
||||
private:
|
||||
D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds, ComPtr<ID3D11BlendState> bs,
|
||||
ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs, ComPtr<ID3D11PixelShader> ps,
|
||||
D3D11_PRIMITIVE_TOPOLOGY topology);
|
||||
|
||||
ComPtr<ID3D11RasterizerState> m_rs;
|
||||
ComPtr<ID3D11DepthStencilState> m_ds;
|
||||
ComPtr<ID3D11BlendState> m_bs;
|
||||
ComPtr<ID3D11InputLayout> m_il;
|
||||
ComPtr<ID3D11VertexShader> m_vs;
|
||||
ComPtr<ID3D11PixelShader> m_ps;
|
||||
D3D11_PRIMITIVE_TOPOLOGY m_topology;
|
||||
};
|
|
@ -1,113 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d11_shader.h"
|
||||
#include "d3d11/shader_compiler.h"
|
||||
#include "d3d11_device.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
D3D11Shader::D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader)
|
||||
: GPUShader(stage), m_shader(std::move(shader))
|
||||
{
|
||||
}
|
||||
|
||||
D3D11Shader::~D3D11Shader() = default;
|
||||
|
||||
ID3D11VertexShader* D3D11Shader::GetD3DVertexShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Vertex);
|
||||
return static_cast<ID3D11VertexShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11PixelShader* D3D11Shader::GetD3DPixelShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Pixel);
|
||||
return static_cast<ID3D11PixelShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11ComputeShader* D3D11Shader::GetD3DComputeShader() const
|
||||
{
|
||||
DebugAssert(m_stage == Stage::Compute);
|
||||
return static_cast<ID3D11ComputeShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
void D3D11Shader::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
Panic("Implement me");
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data)
|
||||
{
|
||||
ComPtr<ID3D11DeviceChild> shader;
|
||||
std::vector<u8> bytecode;
|
||||
switch (stage)
|
||||
{
|
||||
case GPUShader::Stage::Vertex:
|
||||
shader = D3D11::ShaderCompiler::CreateVertexShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
bytecode.resize(data.size());
|
||||
std::memcpy(bytecode.data(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Pixel:
|
||||
shader = D3D11::ShaderCompiler::CreatePixelShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Compute:
|
||||
shader = D3D11::ShaderCompiler::CreateComputeShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||
break;
|
||||
|
||||
default:
|
||||
UnreachableCode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!shader)
|
||||
return {};
|
||||
|
||||
return std::unique_ptr<GPUShader>(new D3D11Shader(stage, std::move(shader), std::move(bytecode)));
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||
std::vector<u8>* out_binary /* = nullptr */)
|
||||
{
|
||||
// TODO: This shouldn't be dependent on build type.
|
||||
#ifdef _DEBUG
|
||||
constexpr bool debug = true;
|
||||
#else
|
||||
constexpr bool debug = false;
|
||||
#endif
|
||||
|
||||
ComPtr<ID3DBlob> blob;
|
||||
switch (stage)
|
||||
{
|
||||
case GPUShader::Stage::Vertex:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Pixel:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
case GPUShader::Stage::Compute:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Compute, m_device->GetFeatureLevel(),
|
||||
source, debug);
|
||||
break;
|
||||
|
||||
default:
|
||||
UnreachableCode();
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_binary)
|
||||
{
|
||||
const size_t size = blob->GetBufferSize();
|
||||
out_binary->resize(size);
|
||||
std::memcpy(out_binary->data(), blob->GetBufferPointer(), size);
|
||||
}
|
||||
|
||||
return CreateShaderFromBinary(
|
||||
stage, gsl::span<const u8>(static_cast<const u8*>(blob->GetBufferPointer()), blob->GetBufferSize()));
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gpu_shader.h"
|
||||
|
||||
#include "common/windows_headers.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "gsl/span"
|
||||
|
||||
class D3D11Device;
|
||||
|
||||
class D3D11Shader final : public GPUShader
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
public:
|
||||
~D3D11Shader() override;
|
||||
|
||||
ID3D11VertexShader* GetD3DVertexShader() const;
|
||||
ID3D11PixelShader* GetD3DPixelShader() const;
|
||||
ID3D11ComputeShader* GetD3DComputeShader() const;
|
||||
|
||||
ALWAYS_INLINE const std::vector<u8>& GetBytecode() const { return m_bytecode; }
|
||||
|
||||
void SetDebugName(const std::string_view& name) override;
|
||||
|
||||
private:
|
||||
D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader, std::vector<u8> bytecode);
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceChild> m_shader;
|
||||
std::vector<u8> m_bytecode; // only for VS
|
||||
};
|
|
@ -21,6 +21,10 @@
|
|||
#include <vector>
|
||||
Log_SetChannel(GPUDevice);
|
||||
|
||||
// FIXME
|
||||
#include "common/windows_headers.h"
|
||||
#include "d3d_shaders.h"
|
||||
|
||||
std::unique_ptr<GPUDevice> g_host_display;
|
||||
|
||||
size_t GPUPipeline::InputLayoutHash::operator()(const InputLayout& il) const
|
||||
|
@ -103,12 +107,182 @@ RenderAPI GPUDevice::GetPreferredAPI()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool GPUDevice::CreateResources()
|
||||
{
|
||||
GPUSampler::Config config = {};
|
||||
config.address_u = GPUSampler::AddressMode::ClampToEdge;
|
||||
config.address_v = GPUSampler::AddressMode::ClampToEdge;
|
||||
config.address_w = GPUSampler::AddressMode::ClampToEdge;
|
||||
config.min_filter = GPUSampler::Filter::Nearest;
|
||||
config.mag_filter = GPUSampler::Filter::Nearest;
|
||||
if (!(m_point_sampler = CreateSampler(config)))
|
||||
return false;
|
||||
|
||||
config.min_filter = GPUSampler::Filter::Linear;
|
||||
config.mag_filter = GPUSampler::Filter::Linear;
|
||||
if (!(m_linear_sampler = CreateSampler(config)))
|
||||
return false;
|
||||
|
||||
if (!CreateImGuiResources())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPUDevice::DestroyResources()
|
||||
{
|
||||
DestroyImGuiResources();
|
||||
|
||||
m_cursor_texture.reset();
|
||||
m_linear_sampler.reset();
|
||||
m_point_sampler.reset();
|
||||
}
|
||||
|
||||
bool GPUDevice::CreateImGuiResources()
|
||||
{
|
||||
std::unique_ptr<GPUShader> imgui_vs = CreateShaderFromBinary(GPUShader::Stage::Vertex, s_imgui_vs_bytecode);
|
||||
std::unique_ptr<GPUShader> imgui_ps = CreateShaderFromBinary(GPUShader::Stage::Pixel, s_imgui_ps_bytecode);
|
||||
if (!imgui_vs || !imgui_ps)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create ImGui shaders.");
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr GPUPipeline::VertexAttribute attributes[] = {
|
||||
GPUPipeline::VertexAttribute::Make(GPUPipeline::VertexAttribute::Semantic::Position, 0,
|
||||
GPUPipeline::VertexAttribute::Type::Float, 2, offsetof(ImDrawVert, pos)),
|
||||
GPUPipeline::VertexAttribute::Make(GPUPipeline::VertexAttribute::Semantic::Texcoord, 0,
|
||||
GPUPipeline::VertexAttribute::Type::Float, 2, offsetof(ImDrawVert, uv)),
|
||||
GPUPipeline::VertexAttribute::Make(GPUPipeline::VertexAttribute::Semantic::Color, 0,
|
||||
GPUPipeline::VertexAttribute::Type::UNorm8, 4, offsetof(ImDrawVert, col)),
|
||||
};
|
||||
|
||||
GPUPipeline::GraphicsConfig config;
|
||||
config.layout = GPUPipeline::Layout::SingleTexture;
|
||||
config.primitive = GPUPipeline::Primitive::Triangles;
|
||||
config.input_layout.vertex_attributes = attributes;
|
||||
config.input_layout.vertex_stride = sizeof(ImDrawVert);
|
||||
config.vertex_shader = imgui_vs.get();
|
||||
config.pixel_shader = imgui_ps.get();
|
||||
config.rasterization = GPUPipeline::RasterizationState::GetNoCullState();
|
||||
config.depth = GPUPipeline::DepthState::GetNoTestsState();
|
||||
config.blend = GPUPipeline::BlendState::GetAlphaBlendingState();
|
||||
config.color_format = GPUTexture::Format::RGBA8; // FIXME m_window_info.surface_format;
|
||||
config.depth_format = GPUTexture::Format::Unknown;
|
||||
config.samples = 1;
|
||||
config.per_sample_shading = false;
|
||||
|
||||
m_imgui_pipeline = CreatePipeline(config);
|
||||
if (!m_imgui_pipeline)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to compile ImGui pipeline.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPUDevice::DestroyImGuiResources()
|
||||
{
|
||||
m_imgui_font_texture.reset();
|
||||
}
|
||||
|
||||
void GPUDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, u32* map_base_vertex)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::UnmapVertexBuffer(u32 used_vertex_count)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::MapIndexBuffer(u32 index_count, u16** map_ptr, u32* map_space, u32* map_base_index)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::UnmapIndexBuffer(u32 used_index_count)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::UploadVertexBuffer(const void* vertices, u32 vertex_size, u32 vertex_count, u32* base_vertex)
|
||||
{
|
||||
void* map;
|
||||
u32 space;
|
||||
MapVertexBuffer(vertex_size, vertex_count, &map, &space, base_vertex);
|
||||
std::memcpy(map, vertices, vertex_size * vertex_count);
|
||||
UnmapVertexBuffer(vertex_count);
|
||||
}
|
||||
|
||||
void GPUDevice::UploadIndexBuffer(const u16* indices, u32 index_count, u32* base_index)
|
||||
{
|
||||
u16* map;
|
||||
u32 space;
|
||||
MapIndexBuffer(index_count, &map, &space, base_index);
|
||||
std::memcpy(map, indices, sizeof(u16) * index_count);
|
||||
UnmapIndexBuffer(index_count);
|
||||
}
|
||||
|
||||
void GPUDevice::PushUniformBuffer(const void* data, u32 data_size)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetFramebuffer(GPUFramebuffer* fb)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetPipeline(GPUPipeline* pipeline)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetViewport(u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetScissor(u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::SetViewportAndScissor(u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::Draw(u32 base_vertex, u32 vertex_count)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::DrawIndexed(u32 base_index, u32 index_count, u32 base_vertex)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
}
|
||||
|
||||
void GPUDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
|
||||
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height)
|
||||
{
|
||||
|
@ -146,6 +320,21 @@ std::unique_ptr<GPUPipeline> GPUDevice::CreatePipeline(const GPUPipeline::Graphi
|
|||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUSampler> GPUDevice::CreateSampler(const GPUSampler::Config& config)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUFramebuffer> GPUDevice::CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, GPUTexture* ds,
|
||||
u32 ds_layer, u32 ds_level)
|
||||
{
|
||||
// TODO: REMOVE ME
|
||||
UnreachableCode();
|
||||
return {};
|
||||
}
|
||||
|
||||
bool GPUDevice::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate)
|
||||
{
|
||||
if (!mode.empty())
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "gpu_pipeline.h"
|
||||
#include "gpu_shader.h"
|
||||
|
||||
#include "gpu_texture.h"
|
||||
|
||||
#include "common/bitfield.h"
|
||||
#include "common/rectangle.h"
|
||||
#include "common/types.h"
|
||||
#include "common/window_info.h"
|
||||
|
@ -28,7 +28,307 @@ enum class RenderAPI : u32
|
|||
OpenGLES
|
||||
};
|
||||
|
||||
// Interface to the frontend's renderer.
|
||||
class GPUFramebuffer
|
||||
{
|
||||
public:
|
||||
GPUFramebuffer() = default;
|
||||
virtual ~GPUFramebuffer() = default;
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
};
|
||||
|
||||
class GPUSampler
|
||||
{
|
||||
public:
|
||||
enum class Filter
|
||||
{
|
||||
Nearest,
|
||||
Linear,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class AddressMode
|
||||
{
|
||||
Repeat,
|
||||
ClampToEdge,
|
||||
ClampToBorder,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
struct Config
|
||||
{
|
||||
BitField<u64, Filter, 0, 1> min_filter;
|
||||
BitField<u64, Filter, 1, 1> mag_filter;
|
||||
BitField<u64, Filter, 2, 1> mip_filter;
|
||||
BitField<u64, AddressMode, 3, 2> address_u;
|
||||
BitField<u64, AddressMode, 5, 2> address_v;
|
||||
BitField<u64, AddressMode, 7, 2> address_w;
|
||||
BitField<u64, u8, 9, 5> anisotropy;
|
||||
BitField<u64, u8, 14, 4> min_lod;
|
||||
BitField<u64, u8, 18, 4> max_lod;
|
||||
BitField<u64, u32, 32, 32> border_color;
|
||||
u64 key;
|
||||
};
|
||||
|
||||
GPUSampler() = default;
|
||||
virtual ~GPUSampler() = default;
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
};
|
||||
|
||||
class GPUShader
|
||||
{
|
||||
public:
|
||||
enum class Stage
|
||||
{
|
||||
Vertex,
|
||||
Pixel,
|
||||
Compute
|
||||
};
|
||||
|
||||
GPUShader(Stage stage) : m_stage(stage) {}
|
||||
virtual ~GPUShader() = default;
|
||||
|
||||
ALWAYS_INLINE Stage GetStage() const { return m_stage; }
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
|
||||
protected:
|
||||
Stage m_stage;
|
||||
};
|
||||
|
||||
class GPUPipeline
|
||||
{
|
||||
public:
|
||||
enum class Layout : u8
|
||||
{
|
||||
// 128 byte UBO via push constants, 1 texture.
|
||||
SingleTexture,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class Primitive : u8
|
||||
{
|
||||
Points,
|
||||
Lines,
|
||||
Triangles,
|
||||
TriangleStrips,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
union VertexAttribute
|
||||
{
|
||||
enum class Semantic : u8
|
||||
{
|
||||
Position,
|
||||
Texcoord,
|
||||
Color,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class Type : u8
|
||||
{
|
||||
Float,
|
||||
UInt8,
|
||||
SInt8,
|
||||
UNorm8,
|
||||
UInt16,
|
||||
SInt16,
|
||||
UNorm16,
|
||||
UInt32,
|
||||
SInt32,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
BitField<u32, Semantic, 0, 3> semantic;
|
||||
BitField<u32, u8, 4, 8> semantic_index;
|
||||
BitField<u32, Type, 12, 4> type;
|
||||
BitField<u32, u8, 16, 3> components;
|
||||
BitField<u32, u8, 19, 8> offset;
|
||||
u32 key;
|
||||
|
||||
// clang-format off
|
||||
ALWAYS_INLINE VertexAttribute& operator=(const VertexAttribute& rhs) { key = rhs.key; return *this; }
|
||||
ALWAYS_INLINE bool operator==(const VertexAttribute& rhs) const { return key == rhs.key; }
|
||||
ALWAYS_INLINE bool operator!=(const VertexAttribute& rhs) const { return key != rhs.key; }
|
||||
ALWAYS_INLINE bool operator<(const VertexAttribute& rhs) const { return key < rhs.key; }
|
||||
// clang-format on
|
||||
|
||||
static constexpr VertexAttribute Make(Semantic semantic, u8 semantic_index, Type type, u8 components, u8 offset)
|
||||
{
|
||||
VertexAttribute ret = {};
|
||||
#if 0
|
||||
ret.semantic = semantic;
|
||||
ret.semantic_index = semantic_index;
|
||||
ret.type = type;
|
||||
ret.components = components;
|
||||
ret.offset = offset;
|
||||
#else
|
||||
// Nasty :/ can't access an inactive element of a union here..
|
||||
ret.key = (static_cast<u32>(semantic) & 0x7) | ((static_cast<u32>(semantic_index) & 0xff) << 4) |
|
||||
((static_cast<u32>(type) & 0xf) << 12) | ((static_cast<u32>(components) & 0x7) << 16) |
|
||||
((static_cast<u32>(offset) & 0xff) << 19);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct InputLayout
|
||||
{
|
||||
gsl::span<const VertexAttribute> vertex_attributes;
|
||||
u32 vertex_stride;
|
||||
|
||||
bool operator==(const InputLayout& rhs) const;
|
||||
bool operator!=(const InputLayout& rhs) const;
|
||||
};
|
||||
|
||||
struct InputLayoutHash
|
||||
{
|
||||
size_t operator()(const InputLayout& il) const;
|
||||
};
|
||||
|
||||
enum class CullMode : u8
|
||||
{
|
||||
None,
|
||||
Front,
|
||||
Back,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class DepthFunc : u8
|
||||
{
|
||||
Never,
|
||||
Always,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Equal,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class BlendFunc : u8
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
SrcColor,
|
||||
InvSrcColor,
|
||||
DstColor,
|
||||
InvDstColor,
|
||||
SrcAlpha,
|
||||
InvSrcAlpha,
|
||||
SrcAlpha1,
|
||||
InvSrcAlpha1,
|
||||
DstAlpha,
|
||||
InvDstAlpha,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class BlendOp : u8
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
ReverseSubtract,
|
||||
Min,
|
||||
Max,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
union RasterizationState
|
||||
{
|
||||
BitField<u8, CullMode, 0, 2> cull_mode;
|
||||
u8 key;
|
||||
|
||||
// clang-format off
|
||||
ALWAYS_INLINE RasterizationState& operator=(const RasterizationState& rhs) { key = rhs.key; return *this; }
|
||||
ALWAYS_INLINE bool operator==(const RasterizationState& rhs) const { return key == rhs.key; }
|
||||
ALWAYS_INLINE bool operator!=(const RasterizationState& rhs) const { return key != rhs.key; }
|
||||
ALWAYS_INLINE bool operator<(const RasterizationState& rhs) const { return key < rhs.key; }
|
||||
// clang-format on
|
||||
|
||||
static RasterizationState GetNoCullState();
|
||||
};
|
||||
|
||||
struct DepthState
|
||||
{
|
||||
BitField<u8, DepthFunc, 0, 3> depth_test;
|
||||
BitField<u8, bool, 4, 1> depth_write;
|
||||
u8 key;
|
||||
|
||||
// clang-format off
|
||||
ALWAYS_INLINE DepthState& operator=(const DepthState& rhs) { key = rhs.key; return *this; }
|
||||
ALWAYS_INLINE bool operator==(const DepthState& rhs) const { return key == rhs.key; }
|
||||
ALWAYS_INLINE bool operator!=(const DepthState& rhs) const { return key != rhs.key; }
|
||||
ALWAYS_INLINE bool operator<(const DepthState& rhs) const { return key < rhs.key; }
|
||||
// clang-format on
|
||||
|
||||
static DepthState GetNoTestsState();
|
||||
static DepthState GetAlwaysWriteState();
|
||||
};
|
||||
|
||||
struct BlendState
|
||||
{
|
||||
BitField<u32, bool, 0, 1> enable;
|
||||
BitField<u32, BlendFunc, 1, 4> src_blend;
|
||||
BitField<u32, BlendFunc, 5, 4> src_alpha_blend;
|
||||
BitField<u32, BlendFunc, 9, 4> dst_blend;
|
||||
BitField<u32, BlendFunc, 13, 4> dst_alpha_blend;
|
||||
BitField<u32, BlendOp, 17, 3> blend_op;
|
||||
BitField<u32, BlendOp, 20, 3> alpha_blend_op;
|
||||
BitField<u32, bool, 24, 1> write_r;
|
||||
BitField<u32, bool, 25, 1> write_g;
|
||||
BitField<u32, bool, 26, 1> write_b;
|
||||
BitField<u32, bool, 27, 1> write_a;
|
||||
BitField<u32, u8, 24, 4> write_mask;
|
||||
u32 key;
|
||||
|
||||
// clang-format off
|
||||
ALWAYS_INLINE BlendState& operator=(const BlendState& rhs) { key = rhs.key; return *this; }
|
||||
ALWAYS_INLINE bool operator==(const BlendState& rhs) const { return key == rhs.key; }
|
||||
ALWAYS_INLINE bool operator!=(const BlendState& rhs) const { return key != rhs.key; }
|
||||
ALWAYS_INLINE bool operator<(const BlendState& rhs) const { return key < rhs.key; }
|
||||
// clang-format on
|
||||
|
||||
static BlendState GetNoBlendingState();
|
||||
static BlendState GetAlphaBlendingState();
|
||||
};
|
||||
|
||||
struct GraphicsConfig
|
||||
{
|
||||
Layout layout;
|
||||
|
||||
Primitive primitive;
|
||||
InputLayout input_layout;
|
||||
|
||||
RasterizationState rasterization;
|
||||
DepthState depth;
|
||||
BlendState blend;
|
||||
|
||||
const GPUShader* vertex_shader;
|
||||
const GPUShader* pixel_shader;
|
||||
|
||||
GPUTexture::Format color_format;
|
||||
GPUTexture::Format depth_format;
|
||||
u32 samples;
|
||||
bool per_sample_shading;
|
||||
};
|
||||
|
||||
GPUPipeline() = default;
|
||||
virtual ~GPUPipeline() = default;
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
};
|
||||
|
||||
class GPUDevice
|
||||
{
|
||||
public:
|
||||
|
@ -86,7 +386,7 @@ public:
|
|||
virtual bool IsFullscreen() = 0;
|
||||
virtual bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) = 0;
|
||||
virtual AdapterAndModeList GetAdapterAndModeList() = 0;
|
||||
virtual bool CreateResources() = 0;
|
||||
virtual bool CreateResources();
|
||||
virtual void DestroyResources();
|
||||
|
||||
virtual bool SetPostProcessingChain(const std::string_view& config) = 0;
|
||||
|
@ -94,11 +394,37 @@ public:
|
|||
/// Call when the window size changes externally to recreate any resources.
|
||||
virtual void ResizeWindow(s32 new_window_width, s32 new_window_height) = 0;
|
||||
|
||||
/// Vertex/index buffer abstraction.
|
||||
virtual void MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space, u32* map_base_vertex);
|
||||
virtual void UnmapVertexBuffer(u32 used_vertex_count);
|
||||
virtual void MapIndexBuffer(u32 index_count, u16** map_ptr, u32* map_space, u32* map_base_index);
|
||||
virtual void UnmapIndexBuffer(u32 used_index_count);
|
||||
|
||||
void UploadVertexBuffer(const void* vertices, u32 vertex_size, u32 vertex_count, u32* base_vertex);
|
||||
void UploadIndexBuffer(const u16* indices, u32 index_count, u32* base_index);
|
||||
|
||||
/// Uniform buffer abstraction.
|
||||
virtual void PushUniformBuffer(const void* data, u32 data_size);
|
||||
|
||||
/// Drawing setup abstraction.
|
||||
virtual void SetFramebuffer(GPUFramebuffer* fb);
|
||||
virtual void SetPipeline(GPUPipeline* pipeline);
|
||||
virtual void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler);
|
||||
virtual void SetViewport(u32 x, u32 y, u32 width, u32 height);
|
||||
virtual void SetScissor(u32 x, u32 y, u32 width, u32 height);
|
||||
void SetViewportAndScissor(u32 x, u32 y, u32 width, u32 height);
|
||||
|
||||
// Drawing abstraction.
|
||||
virtual void Draw(u32 base_vertex, u32 vertex_count);
|
||||
virtual void DrawIndexed(u32 base_index, u32 index_count, u32 base_vertex);
|
||||
|
||||
/// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below.
|
||||
virtual std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
|
||||
GPUTexture::Type type, GPUTexture::Format format,
|
||||
const void* data = nullptr, u32 data_stride = 0,
|
||||
bool dynamic = false) = 0;
|
||||
virtual std::unique_ptr<GPUSampler> CreateSampler(const GPUSampler::Config& config);
|
||||
|
||||
virtual bool DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data,
|
||||
u32 out_data_stride) = 0;
|
||||
virtual void CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
|
||||
|
@ -107,6 +433,10 @@ public:
|
|||
GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width,
|
||||
u32 height);
|
||||
|
||||
/// Framebuffer abstraction.
|
||||
virtual std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt, u32 rt_layer, u32 rt_level, GPUTexture* ds,
|
||||
u32 ds_layer, u32 ds_level);
|
||||
|
||||
/// Shader abstraction.
|
||||
virtual std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data);
|
||||
virtual std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||
|
@ -230,8 +560,14 @@ protected:
|
|||
std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect() const;
|
||||
std::tuple<s32, s32, s32, s32> CalculateSoftwareCursorDrawRect(s32 cursor_x, s32 cursor_y) const;
|
||||
|
||||
bool CreateImGuiResources();
|
||||
void DestroyImGuiResources();
|
||||
|
||||
WindowInfo m_window_info;
|
||||
|
||||
std::unique_ptr<GPUSampler> m_point_sampler;
|
||||
std::unique_ptr<GPUSampler> m_linear_sampler;
|
||||
|
||||
u64 m_last_frame_displayed_time = 0;
|
||||
|
||||
s32 m_mouse_position_x = 0;
|
||||
|
@ -252,6 +588,7 @@ protected:
|
|||
s32 m_display_texture_view_width = 0;
|
||||
s32 m_display_texture_view_height = 0;
|
||||
|
||||
std::unique_ptr<GPUPipeline> m_imgui_pipeline;
|
||||
std::unique_ptr<GPUTexture> m_imgui_font_texture;
|
||||
|
||||
std::unique_ptr<GPUTexture> m_cursor_texture;
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gpu_texture.h"
|
||||
|
||||
#include "common/bitfield.h"
|
||||
#include "common/types.h"
|
||||
|
||||
#include "gsl/span"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
class GPUShader;
|
||||
|
||||
class GPUPipeline
|
||||
{
|
||||
public:
|
||||
enum class Layout : u8
|
||||
{
|
||||
// 128 byte UBO via push constants, 1 texture.
|
||||
SingleTexture,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class Primitive : u8
|
||||
{
|
||||
Points,
|
||||
Lines,
|
||||
Triangles,
|
||||
TriangleStrips,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
union VertexAttribute
|
||||
{
|
||||
enum class Semantic : u8
|
||||
{
|
||||
Position,
|
||||
Texcoord,
|
||||
Color,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class Type : u8
|
||||
{
|
||||
Float,
|
||||
UInt8,
|
||||
SInt8,
|
||||
UNorm8,
|
||||
UInt16,
|
||||
SInt16,
|
||||
UNorm16,
|
||||
UInt32,
|
||||
SInt32,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
BitField<u32, Semantic, 0, 3> semantic;
|
||||
BitField<u32, u8, 4, 8> semantic_index;
|
||||
BitField<u32, Type, 12, 4> type;
|
||||
BitField<u32, u8, 16, 2> components;
|
||||
BitField<u32, u8, 18, 8> offset;
|
||||
u32 key;
|
||||
};
|
||||
|
||||
struct InputLayout
|
||||
{
|
||||
gsl::span<const VertexAttribute> vertex_attributes;
|
||||
u32 vertex_stride;
|
||||
|
||||
bool operator==(const InputLayout& rhs) const;
|
||||
bool operator!=(const InputLayout& rhs) const;
|
||||
};
|
||||
|
||||
struct InputLayoutHash
|
||||
{
|
||||
size_t operator()(const InputLayout& il) const;
|
||||
};
|
||||
|
||||
enum class CullMode : u8
|
||||
{
|
||||
None,
|
||||
Front,
|
||||
Back,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class DepthFunc : u8
|
||||
{
|
||||
Never,
|
||||
Always,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Equal,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class BlendFunc : u8
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
SrcColor,
|
||||
InvSrcColor,
|
||||
DstColor,
|
||||
InvDstColor,
|
||||
SrcAlpha,
|
||||
InvSrcAlpha,
|
||||
SrcAlpha1,
|
||||
InvSrcAlpha1,
|
||||
DstAlpha,
|
||||
InvDstAlpha,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
enum class BlendOp : u8
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
ReverseSubtract,
|
||||
Min,
|
||||
Max,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
union RasterizationState
|
||||
{
|
||||
BitField<u8, CullMode, 0, 2> cull_mode;
|
||||
u8 key;
|
||||
|
||||
static RasterizationState GetNoCullState();
|
||||
};
|
||||
|
||||
struct DepthState
|
||||
{
|
||||
BitField<u8, DepthFunc, 0, 3> depth_test;
|
||||
BitField<u8, bool, 4, 1> depth_write;
|
||||
u8 key;
|
||||
|
||||
static DepthState GetNoTestsState();
|
||||
static DepthState GetAlwaysWriteState();
|
||||
};
|
||||
|
||||
struct BlendState
|
||||
{
|
||||
BitField<u32, bool, 0, 1> enable;
|
||||
BitField<u32, BlendFunc, 1, 4> src_blend;
|
||||
BitField<u32, BlendFunc, 5, 4> src_alpha_blend;
|
||||
BitField<u32, BlendFunc, 9, 4> dst_blend;
|
||||
BitField<u32, BlendFunc, 13, 4> dst_alpha_blend;
|
||||
BitField<u32, BlendOp, 17, 3> blend_op;
|
||||
BitField<u32, BlendOp, 20, 3> alpha_blend_op;
|
||||
BitField<u32, bool, 24, 1> write_r;
|
||||
BitField<u32, bool, 25, 1> write_g;
|
||||
BitField<u32, bool, 26, 1> write_b;
|
||||
BitField<u32, bool, 27, 1> write_a;
|
||||
BitField<u32, u8, 24, 4> write_mask;
|
||||
u32 key;
|
||||
|
||||
static BlendState GetNoBlendingState();
|
||||
static BlendState GetAlphaBlendingState();
|
||||
};
|
||||
|
||||
struct GraphicsConfig
|
||||
{
|
||||
Layout layout;
|
||||
|
||||
Primitive primitive;
|
||||
InputLayout input_layout;
|
||||
|
||||
RasterizationState rasterization;
|
||||
DepthState depth;
|
||||
BlendState blend;
|
||||
|
||||
const GPUShader* vertex_shader;
|
||||
const GPUShader* pixel_shader;
|
||||
|
||||
GPUTexture::Format color_format;
|
||||
GPUTexture::Format depth_format;
|
||||
u32 samples;
|
||||
bool per_sample_shading;
|
||||
};
|
||||
|
||||
GPUPipeline() = default;
|
||||
virtual ~GPUPipeline() = default;
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
};
|
|
@ -1,29 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
class GPUShader
|
||||
{
|
||||
public:
|
||||
enum class Stage
|
||||
{
|
||||
Vertex,
|
||||
Pixel,
|
||||
Compute
|
||||
};
|
||||
|
||||
GPUShader(Stage stage) : m_stage(stage) {}
|
||||
virtual ~GPUShader() = default;
|
||||
|
||||
ALWAYS_INLINE Stage GetStage() const { return m_stage; }
|
||||
|
||||
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||
|
||||
protected:
|
||||
Stage m_stage;
|
||||
};
|
|
@ -19,12 +19,6 @@ add_library(frontend-common
|
|||
imgui_overlays.cpp
|
||||
imgui_overlays.h
|
||||
platform_misc.h
|
||||
postprocessing_chain.cpp
|
||||
postprocessing_chain.h
|
||||
postprocessing_shader.cpp
|
||||
postprocessing_shader.h
|
||||
postprocessing_shadergen.cpp
|
||||
postprocessing_shadergen.h
|
||||
)
|
||||
|
||||
target_link_libraries(frontend-common PUBLIC core common imgui tinyxml2 rapidjson scmversion)
|
||||
|
@ -39,16 +33,8 @@ endif()
|
|||
|
||||
if(WIN32)
|
||||
target_sources(frontend-common PRIVATE
|
||||
d3d11_host_display.cpp
|
||||
d3d11_host_display.h
|
||||
d3d12_host_display.cpp
|
||||
d3d12_host_display.h
|
||||
dinput_source.cpp
|
||||
dinput_source.h
|
||||
imgui_impl_dx11.cpp
|
||||
imgui_impl_dx11.h
|
||||
imgui_impl_dx12.cpp
|
||||
imgui_impl_dx12.h
|
||||
win32_raw_input_source.cpp
|
||||
win32_raw_input_source.h
|
||||
xaudio2_audio_stream.cpp
|
||||
|
@ -59,25 +45,6 @@ if(WIN32)
|
|||
target_link_libraries(frontend-common PRIVATE d3d11.lib dxgi.lib)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENGL)
|
||||
target_sources(frontend-common PRIVATE
|
||||
opengl_host_display.cpp
|
||||
opengl_host_display.h
|
||||
imgui_impl_opengl3.cpp
|
||||
imgui_impl_opengl3.h
|
||||
)
|
||||
target_link_libraries(frontend-common PRIVATE glad)
|
||||
endif()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
target_sources(frontend-common PRIVATE
|
||||
imgui_impl_vulkan.cpp
|
||||
imgui_impl_vulkan.h
|
||||
vulkan_host_display.cpp
|
||||
vulkan_host_display.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_sources(frontend-common PRIVATE
|
||||
platform_misc_win32.cpp
|
||||
|
|
Loading…
Reference in New Issue